Chaining action modes - android

In my activity, I have an action mode defined as follows.
#Override
public void onShowPlace(final String placeId, final String placeName) {
Log.i("PLACE", placeId);
actionModeFeedByLocation = startSupportActionMode(new ActionMode.Callback(){
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.setTitle(placeName);
om.slideHorizontal(R.id.overlay_nf_bylocation_fragment_container,
NewsfeedFragment.newInstance(om), TAG_NFBYLOCATION_FRAGMENT);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
Log.i("DESTROY_ACTIONMODE", "TEST");
om.back();
}
});
}
This renders a newsfeed for a single place in an overlay fragment.
From this feed, I want to show the detail in yet a second overlay by creating another action mode:
#Override
public void onShowUser(final User user) {
actionModeUserProfile = startSupportActionMode(new ActionMode.Callback(){
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.setTitle(user.getFbName());
om.slideHorizontal(R.id.overlay_nf_userprofile_fragment_container,
UserProfileFragment.newInstance(user.getFbId(), user.getFbName(), user.getGender()), TAG_USERPROFILE_FRAGMENT);
Log.i("ACTION_MODE", String.valueOf(actionModeFeedByLocation == actionModeUserProfile));
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
om.back();
}
});
}
Unfortunately, this doesn't work; the call to the detail of the user destroys the first action mode.
I use action mode to maintain consistent "back" behaviour.
As illustration, this is what I need to achieve visually:
It is important to note that:
These fragment appear as overlays on top of each other (should not be destroyed unless "back" is called on them, so I created containers for each in the activity xml)
The "home" (first) screen has set a toolbar to the SupportActionBar
What I need is the back button (in the header + device button) to behave consistently on each overlay, and remove each later correctly.

I solved the problem by overriding onBackPressedand onOptionsItemSelected, and manually syncing the toolbars title / managing the fragment backstack through custom code in the aforementioned callbacks.

Related

How to disable the,Paste,selectALL for the editText view

I have an login fragment. For password (Edittext), I need to disable the Paste and select ALL options.
I tried setCustomSelectionActionModeCallback and "set longClickable " but they are not working.
Any suggestions Thanks in advance
edittext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
Returning false from onCreateActionMode(ActionMode, Menu) will prevent the action mode from being started(Select All, Cut, Copy and Paste actions).
This will definitely work
All you need to do is add mode.finish() in onCreateActionMode()
mEntryText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) { return false; }
public void onDestroyActionMode(ActionMode mode) { }
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
/* This is done to solve the issue of SELECT ALL PASTE etc., showing up.
mode.finish() should not be called at this point. If called, it will throw
this exception "E/DecorView[]: Destroying unexpected ActionMode instance of TYPE_FLOATING;
com.android.internal.view.FloatingActionMode#2e022bc was not the current floating action mode! Expected null"
This makes that class not to execute the rest of the code and hence the FloatingAction is never created!
I wish the the author of FloatingActionMode class gave me a method to just stop showing it. menu.clear()
is supposed to do it, but doesn't do.
*/
mode.finish(); // menu.close(); menu.clear();
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) { return false; }
});

Android: How can you stop Screenshots or copying text

I want to stop a user from copying text or images from my screen to any text editor.
Also I want to prevent taking screen shots of activities.
How can I do it programmatically in Android?
In terms of screenshots - try using FLAG_SECURE - as the docs state
Window flag: treat the content of the window as secure, preventing it from appearing in screenshots or from being viewed on non-secure displays.
You can use it in an Activity as follows:
public class NonScreenshotableActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Place this before setting layout but after calling super method
getWindow().setFlags(LayoutParams.FLAG_SECURE,
LayoutParams.FLAG_SECURE);
setContentView(R.layout.my_layout);
//Rest of your activity code here
}
}
You can also stop any EditText fields from being copy/pasteable by using the following:
yourEditText.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
You can see the docs for ActionMode.Callback() for more on this but it essentially aborts loading the copy/paste dialog
Ed George answers the first part!
Here is the Second half
If you are using API level 11 or above then you can stop copy,paste,cut and custom context menus from appearing by.
edittext.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
public void onDestroyActionMode(ActionMode mode) {
}
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
});
Returning false from onCreateActionMode(ActionMode, Menu) will prevent the action mode from being started(Select All, Cut, Copy and Paste actions).

how to implement CAB for multiple fragments

I have an ActionBarActivity that has two tabs. I have implemented a ActionMode.Callback in tab1(fragment1). Now i want to implement it in tab2(fragment2) as well. The problem is that the tab1 Contextual action bar is active even after i swipe to tab2. This means a CAB is meant to be implemented for an activity, not for specific fragment.
So what is the approach to take to have different CABs in two fragments hosted in the same activity?
In the onCreateActionMode callback save a reference of the ActionMode in your fragment, and then in your fragment's onPause you can finish your action. Example:
protected class MultiChoiceModeListener implements AbsListView.MultiChoiceModeListener {
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
ConversationFragment.this.actionMode = mode;
MenuInflater menuInflater = getActivity().getMenuInflater();
menuInflater.inflate(R.menu.menu_delete_conversation, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(final ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
ConversationFragment.this.actionMode = null;
}
}
#Override
public void onPause() {
super.onPause();
if (actionMode != null) {
actionMode.finish();
}
}

How to override Contextual Action Bar when selecting text in a WebView in Android?

I've googled a lot, and find some tutorials and answers here in stackoverflow, but I am facing some difficults to resolve this issue.
I have a Fragment with a WebView, and I want to show my custom Contextual Action Bar when the user selects some text of my web view. I have two main issues here:
1 Currently, my custom CAB is showed when the user performs long click in any part of the web view.
2 The text is not selected when the user performs long click in some text of my web view.
Some of my current code:
Custom interface:
public class SelectActionModeCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
}
Custom WebView
public class CustomWebView extends WebView {
private SelectActionModeCallback actionModeCallback;
public CustomWebView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
public ActionMode startActionMode(Callback callback) {
actionModeCallback = new SelectActionModeCallback();
return super.startActionMode(actionModeCallback);
}
In my fragment, I have this:
#Override
public void onResume() {
super.onResume();
myWebView.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View view) {
if (mActionMode != null) {
Toast.makeText(getActivity(), "test", Toast.LENGTH_SHORT).show();
return false;
}
mActionMode = getActivity().startActionMode(mActionModeCallback);
view.setSelected(true);
return true;
}
});
}
private SelectActionModeCallback mActionModeCallback = new SelectActionModeCallback() {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.custom, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_sustom:
customMethod();
mode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
mActionMode = null;
}
};
THERE IS A BETTER WAY! See the following answer: https://stackoverflow.com/a/22391169/2608235
In short, you can't use an OnLongClickListener and keep the selection within a WebView. Android does some weird stuff behind the scenes for selecting text within WebViews. If you override OnLongClickListener in order to call startActionMode, you will lose the selection, as you have found out.
What you should do instead is override startActionMode in your fragment, rather than its parent View (in your case, CustomWebView).
I don't have the mod permission to mark this question as a duplicate, but it is.
See my question for more info: Use a custom contextual action bar for WebView text selection

Have OnItemLongClickListener invoked even when in action mode CHOICE_MODE_MULTIPLE_MODAL

I registered an OnItemLongClickListener to a listview but when in actionmode, the listener isn't invoked.
This is the expected behavior, as seen in the perfromLongPress method.
Anyone knows how can I make the lonk click listener to be invoked?
The reason I want this behavior is to make multiple files selection in one long click. See the QuickPic app for an example.
I Think you should use registered instead a MultiChoiceModeListener and Override its method:
#Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
}
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
// this is where you will inflate the CAB just in case
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}

Categories

Resources