I use this function to create animation when switching between 2 activities. But it makes my app stop (not crash, just like pause). I call overridePendingTransition from Adapter in a Fragment of a Activity.
public class LessonAdapter extends RecyclerView.Adapter {
private List<Lesson> lessonList;
private Context mContext;
public LessonAdapter(Context context, List<Lesson> ll) {
lessonList = ll;
mContext = context;
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.lesson_card,parent, false);
return new LessonHolder(view);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
final LessonHolder lessonHolder = (LessonHolder) holder;
lessonHolder.lessonName.setText(lessonList.get(position).getLessonName());
lessonHolder.lessonName.setTextColor(Color.parseColor("#0B8E46"));
lessonHolder.lessonDescription.setText(lessonList.get(position).getLessonDescription());
lessonHolder.lessonDescription.setTextColor(Color.parseColor("#686868"));
if (lessonList.get(position).getUuid() == 1) {
lessonHolder.lessonCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(mContext, WordTypeLessonActivity.class);
mContext.startActivity(i);
((Activity) mContext).overridePendingTransition(R.anim.slide_in, R.anim.slide_out);
}
});
}
if (lessonList.get(position).getUuid() == 2) {
lessonHolder.lessonCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(mContext, TenseLessonActivity.class);
mContext.startActivity(i);
((Activity) mContext).overridePendingTransition(R.anim.slide_in, R.anim.slide_out);
}
});
}
if (lessonList.get(position).getUuid() > 2) {
lessonHolder.lessonCard.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent i = new Intent(mContext, LessonActivity.class);
i.putExtra("lesson_id", lessonList.get(position).getUuid());
mContext.startActivity(i);
((Activity) mContext).overridePendingTransition(R.anim.slide_in, R.anim.slide_out);
}
});
}
}
#Override
public int getItemCount() {
return lessonList.size();
}
}
You can try calling finish() first.
https://developer.android.com/reference/android/app/Activity.html#overridePendingTransition(int, int)
or supply the desired animation information through a ActivityOptions bundle to startActivity(Intent, Bundle) or a related function
as it recommends in the docs
a stacktrace would be nice and some code from the second activity, also why are you using fragments? Seems like you could do it all in one activity using fragments or not use fragments at all and use two activities.
Related
In fragment'A' when a certain condition is established, it should go to 'ChatActivity'.
Intent intent = new Intent(getContext(), ChatActivity.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("uid", matchedUid);
startActivity(intent);
The problem is when other fragment or Activity is showing on the top, the condition is established so startActivity is not executed.. occur an error
'java.lang.String android.content.Context.getPackageName()' on a null object reference
below is entire code
public class MatchFragment extends Fragment implements MatchMVP.View {
private static final String TAG = "MatchFragment";
private MatchPresenter matchPresenter;
private ToggleButton randomMatchBtn;
private ProgressBar progressBar, progressCircle;
private TextView searchingText;
private AdView adView;
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
// Inflate the layout for this fragment
View v;
setupMVP();
if(matchPresenter.checkOnlineStatus(getContext())) {
v = inflater.inflate(R.layout.fragment_match, container, false);
setupView(v);
matchPresenter.isSearching();
initAd(v);
} else {
v = inflater.inflate(R.layout.fragment_offline, container, false);
}
return v;
}
private void setupMVP() {
matchPresenter = new MatchPresenter(this);
}
private void setupView(View v) {
progressBar = v.findViewById(R.id.progressbar);
progressCircle = v.findViewById(R.id.progressbar_circle);
searchingText = v.findViewById(R.id.searching_text);
progressBar.setVisibility(View.INVISIBLE);
progressCircle.setVisibility(View.INVISIBLE);
searchingText.setVisibility(View.INVISIBLE);
randomMatchBtn = v.findViewById(R.id.random_match_btn);
randomMatchBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(matchPresenter.checkOnlineStatus(getContext())) {
if(randomMatchBtn.isChecked()) {
matchPresenter.searchRandomUser();
progressBar.setVisibility(View.VISIBLE);
} else {
matchPresenter.stopMatch();
progressBar.setVisibility(View.VISIBLE);
}
} else {
showSnackBar("error");
}
}
});
}
private void initAd(View v) {
MobileAds.initialize(getActivity(), "ca-app-pub-6263138384822549~5566878684");
adView = v.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder().build();
adView.loadAd(adRequest);
}
#Override
public void createChatRoom(String matchedUid) {
Intent intent = new Intent(getContext(), ChatActivity.class);
intent.addFlags(FLAG_ACTIVITY_CLEAR_TOP);
intent.putExtra("uid", matchedUid);
startActivity(intent);
Vibrator vibrator;
if(getContext() != null) {
vibrator = (Vibrator) getContext().getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(700);
}
}
#Override
public void showSnackBar(String msg) {
Snackbar snackbar = Snackbar.make(getActivity().findViewById(android.R.id.content), msg, 2500);
View snackBarLayout = snackbar.getView();
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
// Layout must match parent layout type
lp.setMargins(0, 300, 0, 0);
// Margins relative to the parent view.
snackBarLayout.setLayoutParams(lp);
snackbar.show();
}
#Override
public void randomMatchBtnOff() {
randomMatchBtn.setChecked(false);
}
#Override
public void randomMatchBtnDisable() {
randomMatchBtn.setEnabled(false);
}
#Override
public void randomMatchBtnEnable() {
randomMatchBtn.setEnabled(true);
progressBar.setVisibility(View.INVISIBLE);
}
#Override
public void showProgressCircle() {
progressCircle.setVisibility(View.VISIBLE);
searchingText.setVisibility(View.VISIBLE);
}
#Override
public void hideProgressCircle() {
progressCircle.setVisibility(View.INVISIBLE);
searchingText.setVisibility(View.INVISIBLE);
}
#Override
public void goAuthActivity() {
Intent intent = new Intent(getContext(), AuthActivity.class);
intent.putExtra("isSanctioned", true);
startActivity(intent);
assert getActivity() != null;
getActivity().finish();
}
#Override
public void onResume() {
super.onResume();
matchPresenter.checkIsSan();
}
#Override
public void onPause() {
super.onPause();
if(isThreadRunning) {
timeCheckThread.interrupt();
}
}
}
Cause of error is 'Fragment is not attached to its Activity'. Yeah I know. I'm making a randomChatting app with firebase. In this MatchFragment, I'm searching other users. When other users start searching, matched with me then let me know by go to 'ChatActivity'.
But if I'm in other fragment of activity, searching is activating, it can't go ChatActivity. 'Fragment is not attached to its Activity'.
Because I'm in other activity not in this MatchFragment. MatchFragment detached to its Activity.
How go to ChatActivity even if I'm in other activity.
You can either try using requireActivity() instead of getActivity() but since you only need a Context object and not necessarily an Activity object, I suggest you replace getActivity() with requireContext().
If that doesn't work out then you can try following this answer: https://stackoverflow.com/a/30498143
PS: I know this should be shared as a comment but my reputation is currently only 41 and I can't post a comment so writing this as an answer.
So basically, I have a dialog where the user inputs data. This dialog is launched from a recyclerView with a custom adapter. I need to call notifyDataSetChanged on the fragment from the dialog after the user clicks "finish".
How do I do this?
Code:
public class FoodListAdapter extends RecyclerView.Adapter<FoodListAdapter.ViewHolder>
implements View.OnClickListener {
//blabla
#Override
public void onClick(View v) {
int position = (int) v.getTag();
String foodItemTitle = mFoodItemList.get(position).getTitle();
FoodEditDietDialog dialog = new FoodEditDietDialog();
dialog.show(fm, mFoodItemList.get(position).getTimeStamp());
}
public class Fragment extends Fragment {
//blabla
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View fragment = inflater.inflate(R.layout.fragment, container, false);
foodList = databaseHelper.getList("somethingsomething");
recyclerView = Fragment.findViewById(R.id.list);
recyclerView.setHasFixedSize(false);
layoutManager = new LinearLayoutManager(this.getContext());
recyclerView.setLayoutManager(layoutManager);
adapter = new FoodListAdapter(fm, foodList);
recyclerView.setAdapter(adapter);
}
public class FoodEditDietDialog extends DialogFragment {
//blabla
button = dialog.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseHelper.doSomething();
dismissDialog();
//TODO: call method in dietFragment to notify adapters
}
});
}
You need to do this through your hosting Activity.
public interface DataChangeListener {
void onDataChange();
}
public class YourActivity extends Activity implements DataChangeListener {
private List<DataChangeListener> dataChangeListeners = new ArrayList<>();
#Override
public void onDataChange() {
for(DataChangeListener listener in dataChangeListeners) {
listener.onDataChange();
}
}
public void addDataChangeListener(DataChangeListener listener) {
dataChangeListeners.add(listener);
}
public void removeDataChangeListener(DataChangeListener listener) {
dataChangeListeners.remove(listener);
}
}
public class Fragment extends Fragment implements DataChangeListener {
#Override
public void onAttach(Activity activity) {
if (activity instanceOf YourActivity) {
activity.addDataChangeListener(this)
}
}
#Override
public void onDetach() {
Activity activity = getActivity();
if (activity instanceOf YourActivity) {
activity.removeDataChangeListener(this)
}
}
#Override
public void onDataChange() {
adapter.notifyDataSetChanged();
}
}
public class FoodEditDietDialog extends DialogFragment {
//blabla
button = dialog.findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
databaseHelper.doSomething();
dismissDialog();
//TODO: call method in dietFragment to notify adapters
Activity activity = getActivity();
if (activity instanceOf DataChangeListener) {
activity.onDataChange();
}
}
});
}
So basically, dialog will call activity, activity will notify fragment, fragment will notify adapters. Alternatively, you can pass your fragment (as DataChangeListener) to your adapter, and to your dialog. And call it from there.
I've looked everywhere and can't figure out how to change an intent class in a Recyclerview's onBindViewHolder from the main activity.
If someone knows of a post that explains how you can do this for each different recycled view to go to a different activity please comment it! If you know how to do this even better!
#Override
public void onBindViewHolder(RecyclerViewHolder holder, final int position) {
holder.crate.setImageResource(listData.get(position).getCrate());
holder.crateName.setText(listData.get(position).getCrateName());
holder.cratePrice.setText(listData.get(position).getCratePrice());
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(context, ***changeThisClass***.class);
context.startActivity(intent);
}
});
}
I've looked everywhere and can't figure out how to change an intent
class in a Recyclerview's onBindViewHolder from the main activity.
You need to give transfer the control of your itemClickListener in RecylerView to the main activity by using a Listener. First, create an interface for the listener in your Adapter:
public class YourAdapter extends RecyclerView.Adapter<YourAdapter.RecyclerViewHolder> {
private YourAdapterListener mListener;
// define the listener
public interface YourAdapterListener {
void onItemClickListener();
}
// set the listener with this
public void setListener(YourAdapterListener listener) {
this.mListener = listener;
}
...
#Override
public void onBindViewHolder(RecyclerViewHolder holder, final int position) {
...
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view) {
// tell the listener about the click event.
mListener.onItemClickListener();
}
});
}
}
Then, you need to set the listener in the main activity:
YourAdapter adapter = new YourAdapter();
recyclerView.setLayoutManager(new LinearLayoutManager(this));
recyclerView.setAdapter(adapter);
adapter.setListener(new YourAdapter.YourAdapterListener() {
#Override
public void onItemClickListener() {
Intent intent = new Intent(YourActivity.this, YourClass.class);
startActivity(intent);
}
});
Now you can set each class for intent for different RecyclerView by changing it inside the Activity where the RecyclerView reside.
Do you want to change that class based on some rule? Activity.class - is an object of type Class.
So, you can create a separate method:
private Class selectClass(int param){
if (param == 0)
return Activity1.class;
if (param == 1)
return Activity2.class;
....
}
and then do:
Intent intent = new Intent(context, selectClass(...);
or you can do something like this:
Class clazz = null;
if (param == 0)
clazz = Activity1.class;
if (param == 1)
clazz = Activity2.class;
....
if (clazz != null) {
Intent intent = new Intent(context, clazz);
....
}
I am creating an android app, where I'll be asking for multiple types of questions using RadioButtons. I don't want to make multiple Activities for these questions. Can anyone please tell me how to do that with a short example, of at least two questions?
You can use multiples fragments... or call the activity itself multiple times...
I did an app like yours and i choose the first method!
This is some fragment of a project that i wrote, and the activity that manipulate it, you will have to change it according to your needs.
Activity
public class CollectActivity extends FragmentActivity {
MyPageAdapter pageAdapter;
NonSwipeableViewPager pager;
SpringIndicator springIndicator;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_collect);
List<Fragment> fragments = getFragments();
pager = (NonSwipeableViewPager) findViewById(R.id.view_pager);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
PagerModelManager manager = new PagerModelManager();
manager.addCommonFragment(fragments, getTitles());
ModelPagerAdapter adapter = new ModelPagerAdapter(getSupportFragmentManager(), manager);
pager.setAdapter(adapter);
springIndicator = (SpringIndicator) findViewById(R.id.indicator);
springIndicator.setViewPager(pager);
springIndicator.setOnTabClickListener(new TabClickListener() {
#Override
public boolean onTabClick(int position) {
return false;
}
});
}
private List<Fragment> getFragments() {
List<Fragment> fList = new ArrayList<Fragment>();
fList.add(CollectFragment.newInstance("Fragment 1"));
fList.add(CollectFragment.newInstance("Fragment 2"));
fList.add(CollectFragment.newInstance("Fragment 3"));
//add your fragments with a loop
return fList;
}
private List<String> getTitles() {
return Lists.newArrayList("1", "2", "3");
}
public void swipeFragment() {
pager.setCurrentItem(pager.getCurrentItem() + 1);
}
public int getFragment() {
return pager.getCurrentItem();
}
}
Fragment
public class CollectFragment extends Fragment {
private Button openButton;
private Button confirmationCloseButton;
private Button yesRenew;
private Button noRenew;
private BroadcastReceiver udpMessages;
public static final String EXTRA_MESSAGE = "EXTRA_MESSAGE";
public static final CollectFragment newInstance(String message) {
CollectFragment f = new CollectFragment();
Bundle bdl = new Bundle(1);
bdl.putString(EXTRA_MESSAGE, message);
f.setArguments(bdl);
return f;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
String message = getArguments().getString(EXTRA_MESSAGE);
View v = null;
if (message.compareTo("Fragment 1") == 0) {
v = inflater.inflate(R.layout.fragment_collect_open, container, false);
openButton = (Button) v.findViewById(R.id.open_button);
openButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i2 = new Intent();
i2.setComponent(new ComponentName("qira.com.locker", "qira.com.locker.Service.MessageService"));
i2.putExtra("Message", "CONFIRM_LOCKER_1_CLOSED");
getContext().startService(i2);
}
});
}
if (message.compareTo("Fragment 2") == 0) {
v = inflater.inflate(R.layout.fragment_collect_close, container, false);
confirmationCloseButton = (Button) v.findViewById(R.id.confirmation_close_button);
confirmationCloseButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i2 = new Intent();
i2.setComponent(new ComponentName("qira.com.locker", "qira.com.locker.Service.MessageService"));
i2.putExtra("Message", "OPEN_LOCKER_1");
getContext().startService(i2);
}
});
}
if (message.compareTo("Fragment 3") == 0) {
v = inflater.inflate(R.layout.fragment_collect_renew, container, false);
yesRenew = (Button) v.findViewById(R.id.yes_button);
noRenew = (Button) v.findViewById(R.id.no_button);
yesRenew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
((CollectActivity) getActivity()).swipeFragment();
}
});
noRenew.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(getContext(), ReserveActivity.class);
startActivity(i);
}
});
}
return v;
}
#Override
public void onResume() {
super.onResume();
udpMessages = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
if (intent.getAction() != null && intent.getAction().equals("UDP.MESSAGES.COLLECT")) {
if (intent.getExtras().getString("Type").compareTo("OPEN_LOCKER_1-LOCKER_OPENED") == 0) {
if (((CollectActivity) getActivity()).getFragment() != 0) { // onCreateView called twice, dont know why... workaround to solve this problem
((CollectActivity) getActivity()).swipeFragment();
}
}
if (intent.getExtras().getString("Type").compareTo("CONFIRM_LOCKER_1_CLOSED-TRUE") == 0) {
if (((CollectActivity) getActivity()).getFragment() != 1) { // onCreateView called twice, dont know why... workaround to solve this problem
((CollectActivity) getActivity()).swipeFragment();
}
}
}
}
};
getContext().registerReceiver(udpMessages, new IntentFilter("UDP.MESSAGES.COLLECT"));
}
#Override
public void onPause() {
super.onPause();
getContext().unregisterReceiver(udpMessages);
}
#Override
public void onDestroyView() {
super.onDestroyView();
}
}
I try to make my own gallery. User can add a rating to every photo.
I want something like this: Main class put all photos on a screen. User click a photo then he can add a rating. Click back button on phone and main class refresh a rating, but intent is always null. Take a look on comments in code.
//My main class.
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView)findViewById(R.id.imagegallery);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager layoutManager = new GridLayoutManager(getApplicationContext(),2);
recyclerView.setLayoutManager(layoutManager);
createLists = prepareData();
adapter = new MyAdapter(getApplicationContext(), createLists);
recyclerView.setAdapter(adapter);
}
//My Adapter class from I send an Intent.
public MyAdapter(Context context, ArrayList<CreateList> galleryList) {
this.galleryList = galleryList;
this.context = context;
}
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.photo_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final MyAdapter.ViewHolder viewHolder, final int i) {
viewHolder.title.setText(galleryList.get(i).getImage_title());
stars = (RatingBar) viewHolder.itemView.findViewById(R.id.ratingBar1);
stars.setRating(galleryList.get(i).getStars());
Picasso.with(context)
.load(galleryList.get(i)
.getImage_ID()).centerCrop()
.resize(240, 240)
.onlyScaleDown()
.into(viewHolder.img);
viewHolder.img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent nextScreen = new Intent(context, ShowPhotoActivity.class);
nextScreen.putExtra("fullPhoto", galleryList.get(i));
nextScreen.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(nextScreen); //everything is OKAY
}
});
}
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.show_photo_activity_layout);
fullPhoto = (CreateList) getIntent().getSerializableExtra("fullPhoto"); //IS OKAY
photoID = fullPhoto.getImage_ID();
stars = (RatingBar)findViewById(R.id.ratingBar);
stars.setRating(fullPhoto.getStars());
if(savedInstanceState != null){
stars.setNumStars(savedInstanceState.getInt(starsPoint));
}
mImageView = (ImageView) findViewById(photoID);
mImageView = (ImageView) findViewById(R.id.image1);
mImageView.setImageResource(photoID);
//message = new Intent(getApplicationContext(), MainActivity.class);
stars.setOnRatingBarChangeListener(new RatingBar.OnRatingBarChangeListener() {
public void onRatingChanged(RatingBar ratingBar, float rating,
boolean fromUser) {
fullPhoto.set_Stars(rating);
message = new Intent(getApplicationContext(), MainActivity.class);
message.putExtra("Photo", fullPhoto);
message.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
System.out.println(fullPhoto.getStars()); //OKAY
startActivity(message);
}
});
}
//Now we are in main class. ALWAYS null. I've tried every solution on stack
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
CreateList photo = (CreateList) getIntent().getSerializableExtra("Photo"); //NULL
for(CreateList photoTemp : createLists) {
if (photoTemp.getImage_ID() == photo.getImage_ID()) {
photoTemp.set_Stars(photo.getStars());
}
}
}
Use onNewIntent callback provides intent parameter instead of call getIntent() method, so, your code must be like the follow:
#Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
CreateList photo = (CreateList) intent.getSerializableExtra("Photo");
for(CreateList photoTemp : createLists) {
if (photoTemp.getImage_ID() == photo.getImage_ID()) {
photoTemp.set_Stars(photo.getStars());
}
}
}