I have and application in which I am using the Single activity and different fragments let say on activity start I call fragment A , and then after taking inputs I switch to fragment B and then Fragment C .
For Some reasons I have changed the Overflow Icon successfully from styles. But now The only problem is that for some reasons I want to show the overflow icons on Fragment B but not on Fragment A and C . for this I am doing this
public static void setOverflowButtonColor(final Activity activity, final int i) {
final String overflowDescription = activity.getString(R.string.abc_action_menu_overflow_description);
final ViewGroup decorView = (ViewGroup) activity.getWindow().getDecorView();
final ViewTreeObserver viewTreeObserver = decorView.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
TintImageView overflow = null;
final ArrayList<View> outViews = new ArrayList<View>();
decorView.findViewsWithText(outViews, overflowDescription,
View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
if (outViews.isEmpty()) {
return;
}
overflow = (TintImageView) outViews.get(0);
//overflow.setColorFilter(Color.CYAN);
overflow.setImageResource(R.drawable.my_overflow_image);
if (i == 1 && overflow!=null) {
overflow.setEnabled(false);
overflow.setVisibility(View.GONE);
} else if (overflow != null) {
overflow.setEnabled(true);
overflow.setVisibility(View.VISIBLE);
}
overflow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(activity, "Overflow", Toast.LENGTH_SHORT).show();
}
});
removeOnGlobalLayoutListener(decorView, this);
}
});
}
public static void removeOnGlobalLayoutListener(View v, ViewTreeObserver.OnGlobalLayoutListener listener) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
v.getViewTreeObserver().removeGlobalOnLayoutListener(listener);
}
else {
v.getViewTreeObserver().removeOnGlobalLayoutListener(listener);
}
}
So from Fragment A I am sending 1 in parameter so to hide the Icon but from Activity B I am sending 0 in parameter to re visible it , but it is not getting call.
Let me tell you this function working when it is called from Fragment A , I mean it is calling one time but not 2nd time or so on .
please tell me how to do this , if you know any other best method
Define an interface like below.
public interface FragmentHost{
public void onFragmentChange(int currentFragment);
}
Activity A should implement this interface.
class A extends Activity implents FragmentHost {
public static final int FRAGMENT_B = 0;
public static final int FRAGMENT_C = 1;
#Override
public void onFragmentChange(int currentFragment) {
if (currentFragment == FRAGMENT_A) {
// enable or disable button
} else if(currentFragment == FRAGMENT_B) {
// enable or disable button
}
}
}
And in each fragment . OnResume function call the onFragmentChange() method and pass the fragment id.
class B extends Fragment {
#Override
public void onResume() {
((FragmentHost) getParentActivity()).onFragmentChange(A.FRAGMENT_B);
}
}
Related
1) In my application, the user may receive a lot of notifications from FCM
2) If the user has an application open, he needs to display the custom DialogFragment
3) If the DialogFragment is already displayed, then the next time the notification arrives, it is necessary to prohibit the repeated display of this DialogFragment
4) My dialogue code:
public final class NotificationEventDialog extends DialogFragment implements DialogInterface.OnKeyListener, View.OnClickListener {
private Activity mCurrentActivity;
private NotificationEventDialogListener mNotificationEventDialogListener;
public interface NotificationEventDialogListener {
void showEvent();
}
public NotificationEventDialog() {
}
public static NotificationEventDialog newInstance() {
NotificationEventDialog notificationEventDialog = new NotificationEventDialog();
notificationEventDialog.setCancelable(false);
return notificationEventDialog;
}
#Override
public void onAttach(Context context) {
super.onAttach(context);
mCurrentActivity = (Activity)context;
try {
mNotificationEventDialogListener = (NotificationEventDialogListener) mCurrentActivity;
} catch (ClassCastException e) {
throw new ClassCastException(mCurrentActivity.toString() + " must implemented NotificationEventDialogListener");
}
}
#NonNull
#Override
public Dialog onCreateDialog(#Nullable Bundle savedInstanceState) {
LayoutInflater inflater = LayoutInflater.from(mCurrentActivity);
#SuppressLint("InflateParams") View view = inflater.inflate(R.layout.dialog_notification_event, null);
Button btnNotificationEventYes = view.findViewById(R.id.notification_event_dialog_yes);
btnNotificationEventYes.setOnClickListener(this);
Button btnNotificationEventNo = view.findViewById(R.id.notification_event_dialog_no);
btnNotificationEventNo.setOnClickListener(this);
AlertDialog.Builder builder = new AlertDialog.Builder(mCurrentActivity);
builder.setView(view);
return builder.create();
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
if (getDialog() != null && getDialog().getWindow() != null) {
getDialog().getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getDialog().setOnKeyListener(this);
}
return super.onCreateView(inflater, container, savedInstanceState);
}
#Override
public void onDetach() {
super.onDetach();
mCurrentActivity = null;
mNotificationEventDialogListener = null;
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.notification_event_dialog_yes:
dismiss();
mNotificationEventDialogListener.showEvent();
break;
case R.id.notification_event_dialog_no:
dismiss();
break;
}
}
#Override
public boolean onKey(DialogInterface dialog, int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK)) {
dismiss();
return true;
} else return false;
}
}
5) Each time I receive a notification from FCM, I create a dialog box:
DialogFragment notificationEventDialog = NotificationEventDialog.newInstance();
notificationEventDialog.show(getSupportFragmentManager(), "");
6) How to check if DialogFragment is already displayed? Every time I create a new object of this window and I cannot make it as Singleton, because This leads to a memory leak.
Found an answer in which a person suggests using Weak links to solve this problem:
Also you can store a weak link to the shown dialog in that singletone
class. Using such method, you can detect is your dialog currently
shown or not.
There was also such an answer:
I suggest to save link to the dialog in single instance class. In that
instance create method ensureShowDialog(Context context). That method
would check is current shown dialog or not. If yes, you can show the
dialog. In another casr you can pass new data you to the dialog.
But, honestly, I can’t quite understand how to use these tips in practice. Please can help with this realization or suggest another way? Thanks in advance.
You can use:
val ft: FragmentTransaction = fragmentManager!!.beginTransaction()
val prev: Fragment? = fragmentManager!!.findFragmentByTag("typeDialog")
if (prev == null) {
val fm = fragmentManager
val courseTypeListDialogFragment =
CourseTypeListDialogFragment()
courseTypeListDialogFragment.isCancelable = false
courseTypeListDialogFragment.setStyle(
DialogFragment.STYLE_NO_TITLE,
0
)
courseTypeListDialogFragment.setTargetFragment(this, 1)
if (fm != null) {
courseTypeListDialogFragment.show(ft, "typeDialog")
}
}
You can check if dialog fragment is showing by calling isAdded () inside DialogFragment or by
DialogFragment notificationEventDialog = NotificationEventDialog.newInstance();
notificationEventDialog.isAdded()
from activity
It will return true if fragment is added to an Activity, in case of dialog fragment - is shown.
You can store last shown dialog fragment date via putting System.currentTimeMillis() in SharedPreferences
I think you'v got the idea.
I have fragment that contains recyclerview and products inside of it. When click row opens a new activity (SuggestionActivity). This activity also contains recyclerview inside of suggested products. When I click this products selecting or deselecting. Under the recyclerview I have button and when clicked this button it should be listen first recyclerview adapter and notifying data.
Ex:
ProductsFragment -> RecyclerAdapter -> Click Row -> Open Activity -> Click one or multiple rows and select -> Click Button -> Close activity and notify fragment adapter
My first recyclerview inside fragment
public class MyView extends RecyclerView.ViewHolder {
public MyView(View view) {
super(view);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
SuggestionActivity x = new SuggestionActivity();
x.setTab2AdapterListener(new SuggestionActivity.Tab2AdapterListener() {
#Override
public void interfaceClicked() {
Log.d("interfaceClicked", "interfaceClicked"); // This line doesn't work!
}
});
Intent i = new Intent(mContext, SuggestionActivity.class);
i.putExtra("first", String.valueOf(tag));
i.putExtra("second", String.valueOf(getAdapterPosition()));
mContext.startActivity(i);
}
});
}
}
My Interface defined on SuggestionActivity
private Tab2AdapterListener tab2AdapterListener;
public interface Tab2AdapterListener {
void interfaceClicked();
}
public void setTab2AdapterListener(Tab2AdapterListener tab2AdapterListener) {
this.tab2AdapterListener = tab2AdapterListener;
}
And Button inside SuggestionActivity
btnSendSuggestions.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String suggested = "";
for (int i = 0; i < suggestedProductsList.size(); i++) {
if (suggestedProductsList.get(i).getIsSelected())
suggested += suggestedProductsList.get(i).getProductId() + ",";
}
if ( suggested.length() > 0 ) {
suggested = suggested.substring(0, suggested.length() - 1);
}
if (tab2AdapterListener != null)
tab2AdapterListener.interfaceClicked();
// tab2AdapterListener comes null
}
});
I have an AppCompatActivity that, at some point, display a DialogFragment. In this dialog, there are items for which I ask confirmation before deleting them. That confirmation is asked through another Yes/No DialogFragment. When the user clicks Yes in that second dialog, I want the first dialog to refresh its ListView (just need to update the adapter and call its notifyDataSetChanged method). The problem is that I don't know when to update the listview.
Because that delete functionality is called from various sources, I implement a listener Interface at the activity level and call an "onDeleteRequest" event from that interface whenever I need an item to be deleted, and that's the activity who opens up the confirmation dialog and perform the actual delete.
Since I don't care much about refreshing the ListView in unnecessary situations, I tried to update the list in the onResume event, but the event is not called when I come back to the first dialog after the confirmation one is dismissed.
So my question is: how can I know when a dialog B displayed on top of a dialog A has been dismissed so I can refresh dialog A accordingly?
EDIT : A bit of code to support my question:
My activity class:
public class MonthActivity
extends AppCompatActivity
implements OnEditCalendarsDialogListener
{
...
//That's where dialog A is shown
#Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
...
if (id == R.id.action_select_calendar) {
final CalendarSelection currentSelection = mCalendarSelectionAdapter.getCurrentCalendarSelection();
if (currentSelection != null) {
EditCalendarsDialogFragment dialogFragment = EditCalendarsDialogFragment.newInstance(currentSelection);
dialogFragment.show(getSupportFragmentManager());
}
return true;
}
return super.onOptionsItemSelected(item);
}
...
//OnEditCalendarsDialogListener interface implementation
//That's where Dialog B is shown over Dialog A
#Override
public void onEditCalendarsDialogDelete(long calendarID) {
final Repository repository = Repository.getInstance(this);
final Calendar calendar = repository.fetchOneByID(Calendar.class, calendarID);
if (calendar != null) {
YesNoDialog yesNoDialog = YesNoDialog.newInstance(this, R.string.yes_no_dialog_confirmation, R.string.yes_no_dialog_calendar_delete);
setCurrentOnDecisionClickListener(new OnPositiveClickListener() {
#Override
public boolean onPositiveClick(DialogInterface dialog) {
//Delete calendar
repository.delete(calendar);
//That's where I'd like to notify Dialog A that it needs to be refreshed
return true;
}
});
yesNoDialog.show(getSupportFragmentManager());
}
}
}
My dialog class
public class EditCalendarsDialogFragment
extends DialogFragment
{
private OnEditCalendarsDialogListener mDialogListener;
public static EditCalendarsDialogFragment newInstance(CalendarSelection calendarSelection) {
EditCalendarsDialogFragment dialog = new EditCalendarsDialogFragment();
Bundle arguments = new Bundle();
if (calendarSelection != null) {
arguments.putLong(KEY_ID, calendarSelection.getID());
}
else {
arguments.putLong(KEY_ID, 0L);
}
dialog.setArguments(arguments);
return dialog;
}
...
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
mDialogListener = (OnEditCalendarsDialogListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement OnCalendarSelectionDialogListener");
}
}
...
private View getLayoutView() {
View rootView = getActivity().getLayoutInflater().inflate(R.layout.calendar_list, null, false);
if (rootView != null) {
mCalendars = (ListView) rootView.findViewById(R.id.calendars);
if (mCalendars != null) {
//Create adaptor
mCalendarAdapter = new ArrayAdapter<Calendar>(
getContext(),
android.R.layout.simple_list_item_2,
android.R.id.text1,
new ArrayList<Calendar>()
) {
#NonNull
#Override
public View getView(int position, #Nullable View convertView, #NonNull ViewGroup parent) {
View view = super.getView(position, convertView, parent);
final Calendar calendar = getItem(position);
if (calendar != null && calendar.hasID()) {
...
view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if (mDialogListener != null) {
//That's where I request delete from calling activity
mDialogListener.onEditCalendarsDialogDelete(calendar.getID());
}
return true;
}
});
}
return view;
}
};
mCalendars.setAdapter(mCalendarAdapter);
refreshCalendarList();
}
}
return rootView;
}
}
Use EventBus.
Register your dialog A to listen to events. When you dismiss dialog B post an event and pass the listitem's adapter position or whatever data you want to use to identify which item is to be deleted. Inside your dialog A write a function to receive this event inside which you delete the item.
OK, so I finally used the "over-abusive-callback" method.
I created the following interface:
public interface OnDeletedListener {
void onDeleted();
}
Updated the OnEditCalendarsDialogListener interface so that the callback has a callback to this interface too:
public interface OnEditCalendarsDialogListener {
void onEditCalendarsDialogDelete(long calendarID, OnDeletedListener onDeletedListener);
}
Implemented the OnDeletedListener interface in "Dialog A" class:
public class EditCalendarsDialogFragment
extends DialogFragment
implements OnDeletedListener
{
...
//OnDeletedListener interface implementation
#Override
public void onDeleted() {
//That's where I'm called back after item is deleted
refreshCalendarList();
}
...
private View getLayoutView() {
...
view.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
if (mDialogListener != null) {
//That's where I request delete from calling activity, asking to call me back once deleted
mDialogListener.onEditCalendarsDialogDelete(calendar.getID(), EditCalendarsDialogFragment.this);
}
return true;
}
});
...
}
}
And finally, call the callback when delete is accepted and performed:
public class MonthActivity
extends AppCompatActivity
implements OnEditCalendarsDialogListener
{
//OnEditCalendarsDialogListener interface implementation
//That's where Dialog B is shown over Dialog A
#Override
public void onEditCalendarsDialogDelete(long calendarID, final OnDeletedListener onDeletedListener) {
final Repository repository = Repository.getInstance(this);
final Calendar calendar = repository.fetchOneByID(Calendar.class, calendarID);
if (calendar != null) {
YesNoDialog yesNoDialog = YesNoDialog.newInstance(this, R.string.yes_no_dialog_confirmation, R.string.yes_no_dialog_calendar_delete);
setCurrentOnDecisionClickListener(new OnPositiveClickListener() {
#Override
public boolean onPositiveClick(DialogInterface dialog) {
//Delete calendar
repository.delete(calendar);
//That's where I notify Dialog A that it needs to be refreshed
if (onDeletedListener != null) {
onDeletedListener.onDeleted();
}
return true;
}
});
yesNoDialog.show(getSupportFragmentManager());
}
}
}
Works smoothly!
I am Implementing tabhost with 5 tabs.On 5th tab i have an activitygroup with 2 child activity.From child activity if i press back button the app returns to the parent activity.
But what i need is on pressing tab button too it has to return to the parent activity.
this is my activity group:
public class Activitygroup extends ActivityGroup {
private Stack<String> stack;
public static Activitygroup grp;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
grp = new Activitygroup();
if (stack == null) {
stack = new Stack<String>();
}
push("HomeStackActivity", new Intent(this,Extras.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
}
#Override
public void finishFromChild(Activity child) {
pop();
}
#Override
public void onBackPressed() {
pop();
}
public void push(String id, Intent intent) {
Window window = getLocalActivityManager().startActivity(id,
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP));
if (window != null) {
stack.push(id);
setContentView(window.getDecorView());
}
}
public void pop() {
if (stack.size() == 1) {
finish();
}
LocalActivityManager manager = getLocalActivityManager();
manager.destroyActivity(stack.pop(), true);
if (stack.size() > 0) {
Intent lastIntent = manager.getActivity(stack.peek()).getIntent()
.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
Window newWindow = manager.startActivity(stack.peek(), lastIntent);
setContentView(newWindow.getDecorView());
}
}
this is where i am handling second tab press in tabhost activity:
int numberOfTabs = tabHost.getTabWidget().getChildCount();
for (int t = 0; t < numberOfTabs; t++) {
tabHost.getTabWidget().getChildAt(t).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
String currentSelectedTag = MainActivity.this.getTabHost().getCurrentTabTag();
String currentTag = (String) v.getTag();
if (currentSelectedTag.equalsIgnoreCase(currentTag)) {
MainActivity.this.getTabHost().setCurrentTabByTag(currentTag);
String newSelectedTabTag = MainActivity.this.getTabHost().getCurrentTabTag();
if (newSelectedTabTag.toLowerCase().indexOf("extras") != -1) {
"BACKPRESS FUNCTIONALITY"-MUST BRING THE PARENT ACTIVITY ON TOP HERE
}
return true;
}
}
return false;
}
});
}
Iphone has this functionality by default.On pressing tab on current activity it bring the parent activity on top.Please suggest me some workaround for this.thanks in advance!!!
This code is used to sense the tab press from the child activity
int numberOfTabs = tabHost.getTabWidget().getChildCount();
for (int t = 0; t < numberOfTabs; t++) {
tabHost.getTabWidget().getChildAt(t).setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_UP) {
String currentSelectedTag = MainActivity.this.getTabHost().getCurrentTabTag();
String currentTag = (String) v.getTag();
if (currentSelectedTag.equalsIgnoreCase(currentTag)) {
MainActivity.this.getTabHost().setCurrentTabByTag(currentTag);
String newSelectedTabTag = MainActivity.this.getTabHost().getCurrentTabTag();
if (newSelectedTabTag.toLowerCase().indexOf("extras") != -1) {
****Here call a static method to check whether the child activity is active****
childactivity.getappcontext();
}
return true;
}
}
return false;
}
});
}
In child activity paste this code.If the child activity is active then it'll be closed when pressing the tab hence the parent activity will be visible.
#Override
public void onStart() {
super.onStart();
active=true;
}
#Override
public void onStop() {
super.onStop();
active=false;
}
public static void getAppContext() {
if(active){
System.out.println("gallery");
galleryActivity1.finish();
}
}
Feel free to ask if not clear.Would love to help.
I am planning on having 3 fragmentlists contained within one activity. The goal is you select the talk option from the first list, then it transitions to the run list based on what you clicked in talk list, and then in the run list, based on what you click it will transition to the final eat list. Should this be happening in the fragments themselves(like i have it) or calling the activity to handle passing data back and forth to the fragments?
public class OptionsActivity extends Activity {
protected TalkFragment talk;
protected RunFragment run;
protected EatFragment eat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
talk = new TalkFragment();
run = new RunFragment();
eat = new EatFragment();
}
}
public class TalkFragment extends ListFragment {
private Cursor mCursor;
int mCurCheckPosition = 0;
#Override
public void onActivityCreated(Bundle savedState) {
super.onActivityCreated(savedState);
}
#Override
public void onListItemClick(ListView l, View v, int pos, long id) {
mCurCheckPosition = pos;
// We can display everything in-place with fragments.
// Have the list highlight this item and show the data.
getListView().setItemChecked(pos, true);
// Check what fragment is shown, replace if needed.
RunFragment run_frag = (RunFragment) getFragmentManager().findFragmentById(R.id.fragment_run);
if (run_frag == null || run_frag.getShownIndex() != pos) {
run_frag = RunFragment.newInstance(pos);
FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.replace(R.id.details, details);
ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
ft.commit();
}
}
}
This is obviously just snippits, but you get the idea. If I do it this way, I am not really sure how to pass certain parameters to fragment properly. Ideally, the RunFragment would know what to display based on the id of the item clicked in the TalkFragment. Should these be going through the Activity instead?
The way I typically do it is have the Activity be the traffic cop for handling the fragments. Your onListItemClick implementation could just tell the Activity what it wants to do:
public class OptionsActivity extends Activity {
protected TalkFragment talk;
protected RunFragment run;
protected EatFragment eat;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
talk = new TalkFragment();
run = new RunFragment();
eat = new EatFragment();
}
public void showRunFragment() {
showFragment(R.id.fragment_run);
}
public void showEatFragment() {
showFragment(R.id.fragment_eat);
}
public void showFragment(int fragmentId) {
// Check what fragment is shown, replace if needed.
...
}
}
public class TalkFragment extends ListFragment {
private Cursor mCursor;
int mCurCheckPosition = 0;
#Override
public void onActivityCreated(Bundle savedState) {
super.onActivityCreated(savedState);
}
#Override
public void onListItemClick(ListView l, View v, int pos, long id) {
mCurCheckPosition = pos;
// We can display everything in-place with fragments.
// Have the list highlight this item and show the data.
getListView().setItemChecked(pos, true);
getActivity().showRunFragment()
}
}