Recyclerview selection + clickable items - java

I recently implemented a small RecyclerView setup and tried out the recyclerview-selection library. So far, the selection works fine but I also connected a click handler on the recyclerview items and now every time I long-press an item to activate the selection mode, it also counts as a simple tap and the activity changes (because that is what I programmed it to do on item tap). I managed to avoid this by adding a simple boolean to my recyclerview adapter, which is called when the selection mode starts:
void setIgnoreClicks(boolean b) {
this.ignoreClicks = b;
}
and then in the bind-function of my viewholder:
void bind(MyModelClass m) {
...
view.setOnClickListener(() -> {
if(!adapter.isIgnoreClicks()) {
...
}
});
}
now when the selection mode ends, the boolean is set back to false and the taps go through again.
The problem is that when only one item selected and you tap on it to deselt it, the selection mode is also exited - which is fine, except that that tap is now not ignored anymore and so, the activity changes. What I want basically is to ignore that last tap too. Is there some way to stop the event if the selection mode is still active?
Thanks

Ok, solved this myself. What I did was to add a touch listener to my recyclerview which sets the ignoreClick to true if the actionmode is active and no item is clicked:
modelList.addOnItemTouchListener(new RecyclerView.OnItemTouchListener() {
#Override
public boolean onInterceptTouchEvent(#NonNull RecyclerView rv, #NonNull MotionEvent e) {
if (e.getAction() != MotionEvent.ACTION_UP)
return false;
if(actionMode != null)
ignoreClick = rv.findChildViewUnder(e.getX(), e.getY()) != null; // ignore click if child is null (not clicked on a child, but the empty background of the recycler view)
return false;
}
...
});
and then in my item click handler:
private void showDetails(final Model model) {
if(ignoreClick)
ignoreClick = false; // the click is ignored, reset to false
else if (!selectionTracker.hasSelection()) {
final Intent intent = new Intent(MainActivity.this, ModelViewActivity.class);
intent.putExtra(Codes.DATA_MODEL, model);
startActivityForResult(intent, Codes.INTENT_MODEL_SHOW);
}
}

Related

Closing an Android Popup Menu

I am attempting to use a popup menu that uses the view of a dynamically added EditText box.
When I do not create the new popup menu inside the onTouch method, the popup closes as expected but, I could not figure out a way to use the view of the touched EditText this way. Instead the popup would show up in the view of the last added EditText.
View.OnTouchListener subjectListener(final EditText editText) {
return new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
popupMenu = new PopupMenu(MainActivity.this, editText);
popupMenu.getMenu().add("works");
popupMenu.show();
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
popupMenu.getMenu().close();
list.get((Integer) editText.getTag()).setText(item.getTitle());
return true;
}
});
return false;
}
};
}
With this code the popup menu shows up exactly where I want it too except it does not close unless I touch another EditText a few times. Which makes me think I am creating multiple popup menu's behind each other or something.
Any ideas?
popupmenu.dismiss();
You can use this to close popup

How to create navigation view open on condition?

First of all, I have two navigation view for both sides in android as shown in this Image. Left side for user who signup as parents meanwhile the right side for the user who signup as a tuition provider. For example, if User A signs up as a parent, so he/she can only open the left side navigation ONLY. I have made some studies, mostly using radio button/radio group. Unfortunately, I have to use the spinner, what coding should I write to ensure the navigation view can be opened for certain users. For your information, I have 3 activity.
1) User.Java wherein coding, I have coding initialize, constructor and getter.
2) RegistrationActivity.Java where I put all the spinner coding.
//USER TYPE SPINNER
List<String> categories = new ArrayList<>();
categories.add(0, "Choose Category");
categories.add("Parents");
categories.add("Tuition Provider");
ArrayAdapter<String> dataAdapter;
dataAdapter = new ArrayAdapter(this,android.R.layout.simple_spinner_item, categories);
dataAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
RegisterUserType.setAdapter(dataAdapter);
RegisterUserType.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener()
{
#Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
if(position==0)
{
//Toast.makeText(getApplicationContext(),"No Item Selected",Toast.LENGTH_LONG).show();
}
else
{
Toast.makeText(getApplicationContext(),parent.getItemAtPosition(position) +" Selected",Toast.LENGTH_SHORT).show();
}
}
#Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
3) Home.Java where I put all my navigation view coding.
menuLeft = (ImageButton) findViewById(R.id.menu_left);
menuRight = (ImageButton) findViewById(R.id.menu_right);
parentsNavigation = findViewById(R.id.nav_view);
tuitionProviderNavigation = findViewById(R.id.nav_view2);
menuLeft.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (drawerLayout.isDrawerOpen(GravityCompat.START))
{
drawerLayout.closeDrawer(GravityCompat.START);
}
else
{
drawerLayout.openDrawer(GravityCompat.START);
}
}
});
menuRight.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
if (drawerLayout.isDrawerOpen(GravityCompat.END))
{
drawerLayout.closeDrawer(GravityCompat.END);
}
else
{
drawerLayout.openDrawer(GravityCompat.END);
}
}
});
parentsNavigation.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
{
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item)
{
UserMenuSelector(item);
return false;
}
});
tuitionProviderNavigation.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener()
{
#Override
public boolean onNavigationItemSelected(#NonNull MenuItem item)
{
UserMenuSelector(item);
return false;
}
});
I can not paste all my coding here because it is too long but I can email you to better understand my XML layout.
All you have to do is lock the drawer that you want to Disable and unlock again if you want to Enable it
use drawerLayout.setDrawerLockMode();
in your case below code will close your one drawer that have gravity start
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, GravityCompat.START);
and when you want to unlock again then simply
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, GravityCompat.START);
Remember one more thing
drawerLayout.setDrawerLockMode() allows the application to restrict the user's ability to open or close the given drawer (cannot open via sliding) but DrawerLayout will still respond to calls to openDrawer(), closeDrawer()
so in your case you also consider disabling the ImageView click because they have these methods
In Your Case
when user will click on a spinner item you check if(position==1)
if this condition true you know it's a parent
so do this in your Home.Java
do this
if(parent==true){
//this will disable right drawer
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, GravityCompat.END);
//and this will enable left drawer
drawerLayout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED, GravityCompat.START);
//and also do to disable right ImageView
menuRight.setEnabled(false);
//and also do to enable left ImageView
menuLeft.setEnabled(true);}
now for tuition provider do same but this time enable right and disable left,
also same for menu button.

disable onClick on recyclerView when is OnlongClick option

How to disable onClick when I click for LongClick?
It's a code from recyclerView, when I try long click I just see that normal click just spamming like hell.
holder.title.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(context, "To clear your recomendations, press for few seconds. ", Toast.LENGTH_SHORT).show();
}
});
holder.title.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
clearPreferences(R.string.preferences_reminder);
Toast.makeText(context, "Recomendations cleared.", Toast.LENGTH_SHORT).show();
return true;
}
});
In case if there is necessity to listen both onLongClick and onClick,
Here is another approach:
Example:
#Override
public boolean onLongClick(View view) {
//return value true to make sure only onLongClick is executed without triggering normal onClick
return true; // or false
}
return true means that the event is consumed. It is handled. No other click events will be notified.
return false means the event is not consumed. Any other click events will continue to receive notifications.
So to make sure both onClick and onLongClick are not triggered at the same time, return true from onLongClick event.
Add this line
holder.title.setOnClickListener(null);

Not propagating clicks

When I click an Android button the Android's Software Keys are shown (hidden before) instead of firing the onClick() method for the actual button that I click.
I have two methods for showing or hiding the system UI:
1.
// Set up the user interaction to manually show or hide the system UI.
contentView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (TOGGLE_ON_CLICK) {
mSystemUiHider.toggle();
} else {
mSystemUiHider.show();
}
}
});
and 2:
/**
* Touch listener to use for in-layout UI controls to delay hiding the
* system UI. This is to prevent the jarring behavior of controls going away
* while interacting with activity UI.
*/
View.OnTouchListener mDelayHideTouchListener = new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (AUTO_HIDE) {
delayedHide(AUTO_HIDE_DELAY_MILLIS);
}
return false;
}
};
And I also have another method which a switch to get the onClick() event on buttons
public void onClick(View v) { switch() { } }
Is it possible to fix this behaviour and when I click the actual button will be fired and the System UI will be shown?
There is no workaround to overcome this behaviour until you have both touch listener and also a click listener inside the same view. Try using
View.SYSTEM_UI_FLAG_LOW_PROFILE|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
instead. Add the below code before setcontentview() method.
View decorView = getWindow().getDecorView();
int uiOptions = View.SYSTEM_UI_FLAG_LOW_PROFILE|View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
decorView.setSystemUiVisibility(uiOptions);

How to get click, double tap, and long click gestures for a view inside a gridview?

I have ImageViews inside of a GridView, I had been using an OnItemClickListener along with an OnItemLongClickListener set on the GridView to open the image on a larger page and to delete the item respectively. Now, I have to implement rearranging of the ImageViews in the GridView, so I plan to move the deletion function to a double tap gesture, (please do not lecture me on android style guidelines (including the possibility of contextual actionbars, which I suggested), as this is what my boss asks for to emulate functions inside our ios app) in order to reserve long click for the drag and drop. I set an OnTouchListener on each view in the getView of my custom adapter, feeding a GestureDetecter with a listener extending SimpleOnGestureListener the given MotionEvent with onTouchEvent. I know what to do up to that point, but when I included (onDown of course, to get other callbacks) onDoubleTap, onSingleTapConfirmed, and onLongPressed all taps were interpreted as long clicks. And when I removed the both callback methods to be replaced with their listener counterparts once again (ie OnItemClickListeners) I received those two gestures but not the double tap, which makes sense, as double taps start out as a single tap unless you wait for a bit less than a second to confirm them as singles rather than potential doubles. I also tried placing the OnItemClickListener, but not the OnItemLongClickListener, with the callback in the extended SimpleOnGestureListener. In this case, only long presses were ever interpreted, but other gestures caused no response. Here is my code as it stands now, and do note that I returned false in the onTouchEvent in order to allow others (itemclicklisteners) to consume the events following the attempts made in the GestureDetector.
public class MainBoardGridAdapter extends GenericBoardGridAdapter implements OnItemLongClickListener {
private class Ges extends GestureDetector.SimpleOnGestureListener {
int pos;
public Ges(View v) {
pos = (Integer) v.getTag();
}
#Override
public boolean onDown(MotionEvent me) {
//this does get called but none of these methods below
return true;
}
#Override
public boolean onDoubleTap(MotionEvent me) {
new DeleteConfirmationPrompt(c, "board") {
#Override
protected boolean onDeleteConfirmed() {
// delete the visionboard
return deleteBoard(pos);
}
}; // Constructor shows dialog
return false;
}
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {
MainBoardGridAdapter.super.flagForUpdate(pos);
if (listener != null) {
listener.onBoardClick(pos, getName(pos));
} else {
Intent intent = new Intent(c, VisionBoardActivity.class);
intent.putExtra(VisionBoardActivity.EXTRA_VISION_BOARD_NAME, getName(pos));
frag.startActivityForResult(intent, MyBoardsFragment.REQUEST_EDIT);
}
return false;
}
}
#Override
public boolean onItemLongClick(AdapterView<?> parent, View v,
final int pos, long id) {
Toast.makeText(c, "Long", Toast.LENGTH_LONG).show();
return false;
}
// called by getView of extended adapter
#Override
public void onImageLoaded(ImageView iv, String data, View root) {
iv.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
(new GestureDetector(c, (new Ges(v)))).onTouchEvent(event);
return false;
}
});
}
}
And in the Activity, gv is my GridView:
gv.setOnItemLongClickListener(gridAdapter);
Also note that I had been using true in the return value in the GestureDetector methods, until trying the current configuration.There was no difference to be seen.
Thank you for your valuable time and help, I hope that someone will be able to point out what I am doing incorrectly.
-Jackson

Categories

Resources