I am having an activity with custom list view. In my list view there are two types of items, with different layout. On items there is a switch and when I turn off the switch I go to Activity A, and when I turn on the switch I go to Activity B.
Here is my code:
Switch enable = (Switch) rowView.findViewById(R.id.enable);
enable.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
Intent intentChange = new Intent(getContext(), ActivityA.class);
intentChange.putExtra(PROPERTY, "test1");
((Activity)getContext()).startActivityForResult(intentChange, 100);
} else {
Intent newIntent=newIntent(getContext(),ActivityB.class);
((Activity)getContext()).startActivityForResult(newIntent, 200);
}
}
});
In each of these activities I call this:
Intent changedIntent=new Intent();
changedLimitIntent.putExtra("changed",changed);
changedLimitIntent.putExtra("changedDesc","desc);
setResult(Activity.RESULT_OK,changedIntent);
finish();
In my activity with custom adapter I have this code:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == ActivityA.REQUEST_CODE) {
....
} else if (requestCode == ActivityB.REQUEST_CODE) {
.....
}
}
}
This work OK for me, however, when I receive the result from Activity A or Activity B on the activity with custom list view, and when I click back button is how I have this activity as many times I wait for result from other activities on back stack. I don't know what the problem is. I don't like to have my activity as many times I wait for result from other activities.
I hope I was clear with my question.
Try this to launch new activity. Hope it will help you.
Activity_A.this.finish();
Intent intentSettings = new Intent(Activity_A.this, Activity_B.class);
intentSettings.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intentSettings);
Related
I am trying to implement RecyclerView in a small project and ran into some problem. My adapter works fine for adding new elements, but doesn't do anything when I edit existing ones.
For creating a new element I use FloatingActionButton in my fragment and send an appropiate request code. For editing an element I tried implementing onClickListener() in onBindViewHolder(). Here's the code:
#Override
public void onBindViewHolder(RecyclerViewAdapter.EventViewHolder holder, int position) {
final Event event = mEvents.get(position);
holder.mLabel.setText(event.getLabel());
holder.mComment.setText(event.getComment());
holder.mStartTime.setText(DateFormat.format("HH:mm", event.getTime()));
holder.mDuration.setText(event.getDurationInFormat(mContext));
holder.itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(mContext.getApplicationContext(), EventCreatorActivity.class);
intent.putExtra(EX_EVENT_ID, event.getId());
intent.putExtra(EX_DAY_ID, event.getParent().getId());
((Activity) mContext).startActivityForResult(intent, DayViewFragment.RC_EDIT);
}
});
}
(itemView is where I keep the entire element view, and the Textviews are just components).
Here's where I initialize the RecyclerViewAdapter:
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
// Restore data after app-configuration
if(savedInstanceState != null && !savedInstanceState.isEmpty())
mDay = Day.findDayById(UUID.fromString(savedInstanceState.getString(DAY_ID)));
else
mDay = new Day(Calendar.getInstance().getTime());
adapter = new RecyclerViewAdapter(getActivity(), new ArrayList<Event>());
adapter.updateDataSet(mDay.getEvents());
adapter.notifyDataSetChanged();
}
And here's where I recieve the results in the fragment:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if(resultCode != Activity.RESULT_OK)
return;
UUID eventId = (UUID)data.getSerializableExtra(EventCreatorFragment.EX_EVENT_ID);
Event event = mDay.findEventById(eventId);
switch (requestCode){
case RC_EDIT:{
int previousPosition = adapter.getPreviousPosition(eventId);
if(previousPosition == mDay.getIndex(event))
adapter.notifyItemChanged(mDay.getIndex(event));
else {
adapter.updateDataSet(mDay.getEvents());
adapter.notifyItemMoved(previousPosition, mDay.getIndex(event));
}
} break;
case RC_ADD:{
adapter.updateDataSet(mDay.getEvents());
adapter.notifyItemInserted(mDay.getIndex(event));
} break;
}
}
Here's where I set the result, in the fragment of the activity which creates\edits new elements:
public void sendResult(){
Intent data = new Intent();
data.putExtra(EX_EVENT_ID, mThisEvent.getId());
getActivity().setResult(Activity.RESULT_OK, data);
}
A few things worth noting:
As I said, adding new elements work just fine.
When an element is clicked, it sends for the EvenetCreatorActivity just fine, and there it shows the data has been edited successfuly (The various values change).
I traced through the code, and onActivityResult() isn't called at all after editing an element.
I've read online that it's possible that the activity that's supposed to get the results is destroyed for some reason, but it isn't the case.
Would appreciate your help.
You will receive at onActivityResult at Fragment only if you used the fragment context for startActivityForResult but you are using Activity... the onActivityResult will get back to the Activity that is the context from the adapter.
I am trying to change theme (day or night) from a Fragment that extends PreferenceFragmentCompat. After setting the Theme I call activity.recreate() to apply the theme but it only changes the theme for the current screen (when I press back the old them is visible). If I call activity.finish(), it changes the theme for the whole app. But I don't want to exit the current screen. Any idea of how to fix this? Thanks in advance.
preferenceTheme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
PreferencesUtils.setThemeDayOrNight(newValue.toString());
Activity activity = getActivity();
if(activity != null){
activity.recreate();
}
return true;
}
});
public static void setThemeDayOrNight(String themeValue) {
if (themeValue.equalsIgnoreCase(THEME_DAY)) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
} else {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
}
}
I found a quick solution but not sure if it is the best.
Starting the preferences Activity using startForActivityResult from previous Activity and onActivityResult return back to the preferences Activity like so:
Intent intent = new Intent(this, MyPreferencesActivity.class);
startActivityForResult(intent, RC_SETTINGS);
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode == RESULT_OK && requestCode == RC_PREFERENCES) {
// To be able to change theme from settings and stay in the same screen after it we need
// to get if theme was changed and then return to settings screen
if (resultCode == RESULT_OK && data.getBooleanExtra(SettingsActivity.EXTRA_CHANGE_THEME, false)) {
Intent intent = new Intent(this, MyPreferencesActivity.class);
startActivityForResult(intent, RC_SETTINGS);
}
}
}
And on MyPreferencesActivity.class:
preferenceTheme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
#Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
PreferencesUtils.setThemeDayOrNight(newValue.toString());
if(activity != null) {
Intent resultIntent = new Intent();
resultIntent.putExtra(EXTRA_CHANGE_THEME, true);
setResult(Activity.RESULT_OK, resultIntent);
activity.finish();
}
return true;
}
});
I have an app that has a few tabs. These tabs are all fragments. On the first tab fragment, I have a text view and a button, which I press on to call an activity.
This activity displays a list of items, car names.
I want to be able to click on a car in the list and return back to the calling fragment and update the text view with the car name I selected.
Can anyone help me out with this?
startActivityForResult() is probably what you're looking for. So a quick example (making super-basic assumptions about your data structure -- substitute as required) would be to make your fragment override onActivityResult(), define a request code, and then start the activity using that request code:
// Arbitrary value
private static final int REQUEST_CODE_GET_CAR = 1;
private void startCarActivity() {
Intent i = new Intent(getActivity(), CarActivity.class);
startActivityForResult(i, REQUEST_CODE_GET_CAR);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
// If the activity result was received from the "Get Car" request
if (REQUEST_CODE_GET_CAR == requestCode) {
// If the activity confirmed a selection
if (Activity.RESULT_OK == resultCode) {
// Grab whatever data identifies that car that was sent in
// setResult(int, Intent)
final int carId = data.getIntExtra(CarActivity.EXTRA_CAR_ID, -1);
} else {
// You can handle a case where no selection was made if you want
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
Then, in the CarActivity, wherever you set a click listener for your list, set the result and pass back whatever data you need in an Intent:
public static final String EXTRA_CAR_ID = "com.my.application.CarActivity.EXTRA_CAR_ID";
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
// Assuming you have an adapter that returns a Car object
Car car = (Car) parent.getItemAtPosition(position);
Intent i = new Intent();
// Throw in some identifier
i.putExtra(EXTRA_CAR_ID, car.getId());
// Set the result with this data, and finish the activity
setResult(RESULT_OK, i);
finish();
}
call startActivityForResult(theIntent, 1);
In the activity started, once the user selects a car, make sure to put the car in an intent and set the result of the activity to that intent
Intent returnIntent = new Intent();
returnIntent.putExtra("result", theCar);
setResult(RESULT_OK, returnIntent);
finish();
Then, in your fragment, implement onActivityResult
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1) {
if(resultCode == RESULT_OK){
String result = data.getStringExtra("result");
}
if (resultCode == RESULT_CANCELED) {
//Write your code if there's no result
}
}
} //onActivityResult
Make Sure to override onActivityResult() in the fragment's hosting activity too, and call the super
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
}
This is because the parent activity hijacks the onActivityResult method, and if you don't call super() then it wont get passed to the fragment to handle it
I have a problem with my code about back button. I've tried a lot of answers here in this site.
I have the mainActivity that calls a second activity with startActivityforResult. This second activity starts bluetooth and show a list of the bonded devices, but if I press the backbutton it stops the app with an error.
public class Main extends Activity implements OnSeekBarChangeListener{
...
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
String address = data.getExtras().getString(BondedDevices.DEVICE_ADDRESS);
if (resultCode==Activity.RESULT_CANCELED){
Toast.makeText(getApplicationContext(), "Finalizando dispositivos pareados", Toast.LENGTH_SHORT).show();
return;
}
switch (requestCode) {
case DISPOSITIVOS_PAREADOS:
if(resultCode==Activity.RESULT_OK){
mConnectThread = new ConnectThread(address);
mConnectThread.start();
estado = EST_CONECTADO; //informa que esta conectado
atualizaEstado();
break;
}
return;
}
}
But when I am in the second activity, and try to back to the mainactivity just pressing the back button, I get an error on main activity and my app return an error:
public class BondedDevices extends ListActivity {
....
#Override
public void onBackPressed() {
// TODO Auto-generated method stub
if(D) Log.e(TAG, "+++ ON BACK PRESSED +++");
setResult(Activity.RESULT_CANCELED);
this.finish();
}
or like this:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(event.getAction() == KeyEvent.ACTION_DOWN)
{
switch(keyCode)
{
case KeyEvent.KEYCODE_BACK:
Intent returnIntent = new Intent();
setResult(Activity.RESULT_CANCELED, returnIntent);
finish();
return true;
}
}
return false;
}
I have tried a lot of different code, but it still doesn't work. Please someone help me. Thank you.
you should call super.onBackPressed();
like this
#Override
public void onBackPressed() {
super.onBackPressed();
if(D) Log.e(TAG, "+++ ON BACK PRESSED +++");
setResult(Activity.RESULT_CANCELED);
this.finish();
}
When you return from the second Activity, you have not set an Intent as the data for the result in the back button case, yet the first thing you do before checking the value of resultCode for RESULT_CANCELED is try to obtain the address from the Intent, which is null so this will cause a NullPointerException.
You need to reorder the lines in your onActivityResult() to look more like this:
if (resultCode==Activity.RESULT_CANCELED){
Toast.makeText(getApplicationContext(), "Finalizando dispositivos pareados", Toast.LENGTH_SHORT).show();
return;
}
//Do this after checking for cancel
String address = data.getExtras().getString(BondedDevices.DEVICE_ADDRESS);
/* The rest of the existing code */
Also, you should NOT override BOTH the onBackPressed() and onKeyDown(), stick with one of them. You're only causing confusion about which code path gets called first. Even in the case where the result is set with a blank Intent, you will still get a NullPointerException in your existing code because the extras bundle of that Intent will still be null.
Android 2.1 via eclipse
I have an activity that opens a dialog themed activity via checkbox onChecked function
Im creating this new dialog themed activity with an Intent.
Problem is, how do i dismiss the dialog themed activity once i finish with it? (the way it stands now, i have to send a new intent in order to go back to the previous activity via click of a button)
Any help would be greatly apprieciated!
Code snippet:
Main activity:
cbReminder.setOnCheckedChangeListener(new OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked)
{
Intent intent = new Intent(getApplicationContext(), DateTimeDialog.class);
startActivity(intent);
}
}
});
Dialog themed activity:
public void onClick(View v) {
if (v.getId() == R.id.b_datetime_save)
{
}
else if (v.getId() == R.id.b_datetime_cancel)
{
finish();
Intent intent = new Intent(getApplicationContext(), MakeNoteActivity.class);
startActivity(intent);
}
}
As you specified, the intent was indeed not needed to return to the previous activity and should be removed.
To uncheck the checkbox after returning from the dialog, you can use startActivityForResult and set a callback for when you return.
Open your dialog like this:
Intent intent = new Intent( getApplicationContext(), DateTimeDialog.class );
startActivityForResult( intent, UNIQUE_IDENTIFIER );
Then add a callback to that same activity:
#Override
protected void onActivityResult( int requestCode, int resultCode, Intent data )
{
if ( requestCode == UNIQUE_IDENTIFIER )
{
cbReminder.setChecked( false );
}
}
The UNIQUE_IDENTIFIER can be any number that uniquely identifies this dialog. Let me know if you have any more questions.