Android - SwitchCompact disable/stop default behaviour - java

In my android project I have SwitchCompact, onClick of which I do networking stuff and on basis response I want to change SwitchCompact to checked or not checked.
The problem I am facing now is :
When I click on SwitchCompact it changes its status (ie true to false and vice versa) which is its normal behaviour. I want to disable its normal/default behaviour.
Is that possible?
class MyClass extends Fragment implements View.OnClickListener {
SwitchCompat switchCompact;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
//my view inflating stuff
switchCompact= (SwitchCompat) view.findViewById(R.id.switch_id);
switchCompact.setOnClickListener(this);
return view;
}
#Override
public void onClick(View view) {
if (view.getId()==R.id.switch_id) {
//make http request
}
}
public void onResponse(Response response){
switchCompact.setChecked(response.getStatus());
}
}
Any help will be appreciated.

Well putting more pressure on my head I found something like work around, not an exact answer :)
#Override
public void onClick(View view) {
if (view.getId()==R.id.switch_id) {
switchCompact.setChecked(!switchCompact.isChecked());
//make networking stuff.
}
}
#RageshRamesh : I was thinking why not revert back its status before response or after onClick i.e. when the Switch changes its status. This workaround works as expected. Thanks for your help.

Related

Set content view not working

public class troopcard extends Activity implements View.OnClickListener {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.troopcard);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.pekkacard:
setContentView(R.layout.pekkacard);
break;
case R.id.dragcard:
setContentView(R.layout.dragcard);
}
}
}
The question here is why isnt the set content view working?as in the xml isnt opening of which i want. as making a intent then directing to a class then setting content view will take a hell load of time. I thought by directly setting the content view it might work. it isnt. What could be the solution. i really dont want to make a separate class for this as i have 40 + xmls. so is there a way to directly set content view without having to make a class?
This is not a true programming architecture. If you have more than one layout you should use more than one activity or fragment.
Switching on R.id won't work. You are never actually calling
setContentView(R.layout.pekkacard);
or
setContentView(R.layout.dragcard);
Try:
Override
public void onClick(View v) {
setContentView(R.layout.pekkacard);
}
to see if it displays the other layout.

How to properly change elements within Fragments

I have two pages (Fragments) in my app that each have their own interaction. A long click on either page should toggle the color scheme to black and white and back again. This is accomplished using a separate java class that is called from either page. This works perfectly when run from the second page, but when run from the first page, the second page isn't changed. Here's some of my code, simplified for length:
Page 1:
firstView = inflater.inflate(R.layout.page1, container, false);
secondView = inflater.inflate(R.layout.page2, container);
//A bunch of code and then....
element1.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
pm = sharedPreferences.getBoolean("pm", false);
if (pm) {
performance.PerfModeOff();
pm = false;
sharedPreferences.edit().putBoolean("pm", pm).apply();
} else {
performance.PerfModeOn(mContext);
pm = true;
sharedPreferences.edit().putBoolean("pm", pm).apply();
}
return true;
}
});
Page 2:
secondView= inflater.inflate(R.layout.page2, container, false);
firstView = inflater.inflate(R.layout.page1, container);
//A bunch of code and then...
element2.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
pm = sharedPreferences.getBoolean("pm", false);
if (pm) {
performance.PerfModeOff();
pm = false;
sharedPreferences.edit().putBoolean("pm", pm).apply();
} else {
performance.PerfModeOn(mContext);
pm = true;
sharedPreferences.edit().putBoolean("pm", pm).apply();
}
return true;
}
});
The class that's changing the colors:
public Performance(View firstView, View secondView,LayoutInflater inflater, ViewGroup container) {
mfirstView = inflater.inflate(R.layout.page1, container,false);
msecondView = inflater.inflate(R.layout.page2, container,true);
uparrow= (ImageView) firstView.findViewById(R.id.UpArrow);
//**A lot of lines like above
public void PerfModeOn(Context context) {
mfirstView.setBackgroundColor(Color.BLACK);
msecondView.setBackgroundColor(Color.BLACK);
uparrow.setBackgroundTintList(ColorStateList.valueOf(context.getResources().getColor(R.color.DarkTint)));
//** More lines to change colors
public void PerfModeOff() {
//**Lines to change colors back
Of course if you need to see some more code, just let me know. What can I do to fix this? Thanks for your help!
Your second view never changes because PerfModeOn() calls mfirstView.setBackgroundColor(Color.BLACK); naively. You need to pass which view to set the background of, so it sets the correct background.
In other words, your first view will only ever be the view changed because of how explicit you were when setting the background.
An alternative would be:
public void perfModeOn(Context context, View viewToSetBackgroundOf) {
viewToSetBackgroundOf.setBackgroundColor(Color.BLACK);
...
}
An even better approach would be to implement an OnLongClickListener that both of your views use. Then you get which view was clicked in your onLongClick() method. Then a simple if statement on which view was clicked, and set the background of the opposite view. This would get rid of your redundant code, and some unneeded methods.

Android AsyncHttpClient post() into infinite loop in Fragment

I'm using the android-async-http-1.4.4.jar library, here is what my code looks like, I left out the declaration/implementation of REMOTE_PHP_URL and entityJSON on purpose (assume they are implemented correctly).
public class SearchFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_search, container, false);
mFindButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
final AsyncHttpClient client = new AsyncHttpClient();
//entityJSON and REMOTE_PHP_URL are implemented correctly
client.post(getActivity(), REMOTE_PHP_URL, entityJSON, "application/json", new JsonHttpResponseHandler() {
#Override
public void onSuccess(JSONObject jsonResultObject) {
/*Success Code here*/
}
});
}
}
}
}
When it executes client.post LogCat displays:
dalvikvm GC_FOR_ALLOC freed 1463K, 21% free 6851K/8628K, paused 4ms, total 4ms
over and over again (infinite loop) until I stop the process in DDMS. LogCat doesn't display any (red) errors.
Keep in mind, the above code runs in other activities in my app just fine. I think it may have something to do with the fact that it's running in a Fragment or something to do with the context or both. I'm new to android, should I be using something other than getActivity() for the context?
I've tried to update to android-async-http-1.4.5.jar but when I do, I can't #Override onSuccess() for some reason.
Thanks.
I solved it, my PHP file was not returning a proper JSONObject. I accidentally had left a few echo's in my PHP file for debugging purposes and forgot to remove them. There was nothing wrong with the client.post statement!

Adding a Button on a View

I am going nuts over this.
I did not find any working solution (tried a few from stackoverflow)
Scenario (this is an actual screenshot what is already done):
I have a Activity that has a View as his Attribute.
This view adds another view via View.addView(myView).
I now want to add a Button to myView (to be specific: after MotionEvent.ACTION_UP the button should appear in the right lower corner (this will start the robot to drive the track))
Here is a shortcut of my code:
public class ModeRouting extends View {
public ModeRouting(Context context) {
super(context);
Button asuroStartButton = new Button(context) //does not work
}
#Override
public boolean onTouchEvent(MotionEvent event) {
int actionevent = event.getAction();
if (actionevent == MotionEvent.ACTION_UP
|| actionevent == MotionEvent.ACTION_CANCEL) {
asuroStartButton.visible=true;
view.add(asuroStartButton);
}
return true;
}
}
and my Activity:
//in constructor
contentView = (FrameLayout) findViewById(R.id.content);
onClickListenerFacade(routingMode, route);
//this removes all views from stack and places the new one on the view
private void onClickListenerFacade(View v, final View target) {
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View arg0) {
contentView.removeAllViews();
contentView.setBackgroundColor(0xff000000);
contentView.addView(target);
modeSelectorAnimation();
}
});
}
I tried to create a button in my mainactivity.xml and instantiate in my mainactivity.
I am missing some point in here but i am not sure which.
Since my view is purely dynamic (no layout.xml) i dont think i should use a layout.xml (maybe thats my mind-blockage) but instead set the button attributes dynamically too.
Any hint is appreciated!
You want to extend ViewGroup rather than just a View (LinearLayout, RelativeLayout, FrameLayout, etc) - they handle child views for you.
I think maybe you need to refresh the whole view/activity. Try to do this in the onResume methode, maybe this helps. But as you don't use a layout.xml, I'm not sure if this helps you much..
#Override
protected void onResume(){
super.onResume();
setContentView(R.layout.activity_main);
}

LoaderCallbacks.onLoadFinished is not called when loader is resused and contains data

I have 1 activity and 2 fragments. Both fragments use a custom AsyncTaskLoader to get some data from a webservice and as i'm using a Loader it should keep the data across activity and fragment re-creations. Both fragments override the onActivityCreated method and calls getLoaderManager().initLoader(0, null, this) which either creates a new or reuses an existing loader.
When the activity is first created, it adds Fragment #1 in a FrameLayout by default, loads the data, internally calls LoaderCallbacks.onLoadFinished() method and displays the result. I have a button which replaces Fragment #1 with Fragment #2 on click and Fragment #1 is pushed to the fragment-backstack. When the user hits the BACK key, it switches back to Fragment #1.
onActivityCreated gets called again on Fragment #1 and then obviously calls iniLoader() again. This time the data already exists in the loader and i expect it to automatically call the LoaderCallbacks.onLoadFinished method again, because it already has data available, as described here: http://goo.gl/EGFJk
Ensures a loader is initialized and active. If the loader doesn't already exist, one is created and (if the activity/fragment is currently started) starts the loader. Otherwise the last created loader is re-used.
In either case, the given callback is associated with the loader, and will be called as the loader state changes. If at the point of call the caller is in its started state, and the requested loader already exists and has generated its data, then callback onLoadFinished(Loader, D) will be called immediately (inside of this function), so you must be prepared for this to happen.
But the method is never called even if the loader exists and has generated data ready to deliver.
Edit #1
The problem from a users perspective:
User starts activity and sees fragment1 with some data
User clicks something which changes the first fragment to another, with different
data
User hits the BACK key
User is now looking at fragment1 again, but there's no data. (which means i need to get it from the webservice again - and i'd like to avoid that if possible)
Here is my activity:
public class FragmentTestsActivity extends Activity implements OnClickListener {
private Button btn1;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btn1 = (Button) findViewById(R.id.btn1);
btn1.setOnClickListener(this);
Fragment newFragment = new Fragment1();
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.add(R.id.fragmentContainer, newFragment).commit();
}
#Override
public void onClick(View view) {
int id = view.getId();
if (id == R.id.btn1) {
showNewFragment();
}
}
public void showNewFragment() {
// Instantiate a new fragment.
Fragment2 newFragment = new Fragment2();
// Add the fragment to the activity, pushing this transaction
// on to the back stack.
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.fragmentContainer, newFragment);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
ft.addToBackStack(null);
ft.commit();
}
}
My Fragment #1:
public class Fragment1 extends Fragment implements LoaderCallbacks<String> {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment1, container, false);
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
LoaderManager.enableDebugLogging(true);
getLoaderManager().initLoader(0, null, this);
}
private static class TestLoader extends AsyncTaskLoader<String> {
String result;
public TestLoader(Context context) {
super(context);
}
#Override
public String loadInBackground() {
// Some long-running call to a webservice - replaced with a simple string to test with
return "FirstTimeData";
}
#Override
public void deliverResult(String data) {
result = data;
if (isStarted()) {
super.deliverResult(data);
}
}
#Override
protected void onStartLoading() {
if (result != null) {
deliverResult(result);
}
if (takeContentChanged() || result == null) {
forceLoad();
}
}
#Override
protected void onStopLoading() {
cancelLoad();
}
}
#Override
public Loader<String> onCreateLoader(int id, Bundle args) {
return new TestLoader(getActivity());
}
#Override
public void onLoadFinished(Loader<String> loader, String result) {
Log.d("Fragment1", "onLoadFinished: " + result);
}
#Override
public void onLoaderReset(Loader<String> loader) {
// TODO Auto-generated method stub
}
}
Anyone know a solution to this or what i'm doing wrong here? Any help is greatly appreciated.
The correct answer, for me at least, was to move the entire Loader initialisation from onViewCreated or onActivityCreated to onStart.
After that it works fine!
From my point of view the onLoadFinished will only be called the first time cause the load has already finished, it finishes just once for both fragments. What you could do is to store the result in a property in the activity and check for it in the second fragment creation.
Update: After further investigation I found my original answer to be wrong. restartLoader will also destroy the loader if it already exists.
Nevertheless I solved my own problem. I create a standard CursorLoader in onCreateLoader and swap the cursor of my CursorAdapter in onLoadFinished. I needed to call initLoader after initializing the CursorAdapter. Now the data is still there when the fragment is returned from the backstack.
Original answer: I found two possible ways to solve this issue.
Apparently when initLoader(int id, Bundle args, LoaderCallbacks<D> callback) is called for the second time in onActivityCreated(Bundle savedInstanceState) after the Fragment is returned from the backstack, the method onLoadFinished(Loader<String> loader, String result) is never called (as you described).
However, a call to restartLoader(int id, Bundle args, LoaderCallbacks<D> callback) after or instead of initLoader will finally cause onLoadFinished to be called. To improve performance, I use a boolean argument to determine whether the Fragment is a new instance or not. Then I call restartLoader only if the Fragment is returned from the backstack.
As far as I can tell, old data persists in the loader and is not reloaded, but I'm not sure. The second possibility (especially when not using the backstack but instead creating a new Fragment instance in a transaction) is to call destroyLoader(int id) before the Fragment goes away (e.g in onPause).
I already had that issue, I can't really explain why that bug but I know that line :
getLoaderManager().initLoader(0, null, this);
don't work in my code, So you can changed it for that :
LoaderManager lm = getLoaderManager();
lm.initLoader(LOADER_ID, null, this);
The code start the methods :
onCreateLoader
you can try...

Categories