I'm trying to disable the "touch highlight animation" when touching the header. onNavigationItemSelected() is correctly only called when a menu item is touched. But when I touch the header, there is an animation.
I've tried setEnabled(false), setClickable(false) setLongClickable(false), setAnimation(null), setFocusable(false), but it still showing. I cannot find a methods for manipulating the header. (other than addHeader)
Any ideas? Thanks
It seems that updating to the latest version of the design library allowed for the following:
View headerView = LayoutInflater.from(getActivity()).inflate(R.layout.header_view, mNavigationView, false);
headerView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// Consume input from header view. This disables the unwanted ripple effect.
}
});
I am quite confident that I tried this without luck before updating, though.
Related
I would like to show a custom animation to match the other animations that I have in my RecyclerView. I can’t find a straight forward way of adding custom animations for removal. I know that when RecyclerView replaced ListView one of the talking points was the ability to know when items are added or removed rather than simply saying the dataset has changed and updating everything, so I figured there would be an easy way to add an animation to a View when it is removed that I am missing.
When I add an animation to a view that is removed the animation will not play. This is likely because the View is removed and the animation stops. Is there an easy way to add an animation to a View that doesn’t get cut off? I'm assuming that I could use a second thread, but I want to know if I am missing something.
//code for removal
holder.button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//animation to be added here on view
list.remove(holder.getAdapterPosition());
notifyItemRemoved(position);
notifyItemRangeChanged(position,list.size()-position);
}
});
All add/change/delete/move animations in recyclerView are made by ItemAnimator (by default animator is DefaultItemAnimator). So if you need custom delete animation you should provide custom ItemAnimator via recyclerView.setItemAnimator(animator) method.
I suggest to extend from SimpleItemAnimator and override animateRemove method.
inception sounds
It might not be the best idea, but here's a 4 second gif of what I'm trying to do and the problem I've run into.
https://i.imgur.com/Z3iAyNc.gifv (sorry, embedding wasn't allowed).
I have a RecyclerView with in each item a LinearLayout with category details and a hidden LinearLayout with another recyclerView. The idea is you see the categories, and once you tap on it, it expands to show the relevant posts. Another tap on the category should open the category detail page and a tap on a post should open the relevant post detail page.
I have it working, but as you can see in the gif, I have to tap at least two times, even though I never wrote it like that. It's the same for the LinearLayout's onClickListener It's like the parent RecyclerView hijacks the first tap.
Here's a schematic rundown of my code
adapter.setOnItemTouchListener(new RecyclerItemListener.RecyclerTouchListener() {
#Override
public void onClickItem(View v, int position) {
final LinearLayout postView = (LinearLayout) v.findViewById(R.id.profileCheckinDetailsView);
// The IF statement prevents reloading the view when it is already open.
if (postView.getVisibility()==View.GONE){
RelativeLayout itemView = (RelativeLayout) v.findViewById(R.id.ItemView);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
[... etc]
And beneath it there's another setOnItemTouchListener for the child RecyclerView.
Am I doing this right, and if so, how to make sure both items register the first tap as well?
Thanks in advance!
Sometimes typing out a question helps you think differently. I removed the top recyclerview's touch listener and replaced the item layout with this. Both layouts get their own onClickListener. With ((LinearLayout)v.getParent()) I managed to have them control eachother.
Much easier and more effective I believe.
I have a view on top of another view. The bottom view is supposed to fire a callback when clicked. The top view is not supposed to fire any callback when clicked.
The problem I am facing is that when there is a click on the top view, the bottom view fires its callback. I want to prevent this.
I've read a number of posts on disabling clicks and they all suggest the same thing:
view.setEnabled(false);
and
view.setClickable(false);
Neither of these prevent the top view from swallowing/blocking the click event.
Do you know how I can have a view prevent passing clicks through?
Its a little hacky but the best solution I came up with was adding an empty onClickListener to swallow the event.
button.setOnClickListener(new View.OnClickListener()
{
#Override
public void onClick(View v)
{
// HACK disables click through events by swallowing click
}
});
I couldn't understand what you are trying to do without an example.
But if you want to disable click for a particular view & you don't have any click functionality for this view, then try
view.setOnClickListener(null);
Also, did you try view.setFocusable(false); ??
I'm creating a list of editable items (received from backend). I'm using the "new" recyclerview for this. There a couple of possible viewTypes in my recyclerview:
checkbox
spinner
edittext
The problem I'm having is with the EditText gaining focus. AdjustResize kicks in fine and my keyboard is shown. But the EditText that has gained focus isn't visible anymore in the list. (position in the list in the now resized portion is below the visible positions). I don't want to be using AdjustPan in this case because on top there is a pager & stuff I would like to keep fixed there..
This is happening because, at the time the keyboard is shown, your EditText does not exist anymore. I have made several attempts to find a clean solution to this problem maintaining adjustResize input mode and good user experience. Here's what I ended up with:
To ensure that EditText is visible before the keyboard is shown, you will have to scroll the RecyclerView manually and then focus your EditText.
You can do so by overriding focus and click handling in your code.
Firstly, disable focus on the EditText by setting android:focusableInTouchMode property to false:
<EditText
android:id="#+id/et_review"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusableInTouchMode="false"/>
Then you have to set a click listener for the EditText where you will manually scroll the RecyclerView and then show the keyboard. You will have to know the position of your ViewHolder which contains the EditText:
editText.setOnClickListener(new View.OnClickListener() {
#Override public void onClick(View v) {
LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager();
// you may want to play with the offset parameter
layoutManager.scrollToPositionWithOffset(position, 0);
editText.setFocusableInTouchMode(true);
editText.post(() -> {
editText.requestFocus();
UiUtils.showKeyboard(editText);
});
}
});
And finally, you must make sure that the EditText is made not focusable again when it naturally looses focus:
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus) {
editText.setFocusableInTouchMode(false);
UiUtils.hideKeyboard();
}
}
});
This is far from a simple and clean solution, but hope it will help the way it helped me.
I've had the same issue. Long story short - there is no right and elegant solution. Focus handling was always a big pain in Android.
There multiple reasons why you are loosing focus:
Keyboard hides the descendant EditText views
Next EditText is not rendered, because RecycleView hasn't even created a ViewHolder for it. Example: you have 10 views, and 5 of them are on screen and others aren't visible, because those are below.
Some other view consumes focus, in example CheckBox or some DatePicker
RecyclerView due to scroll events consumes focus
Bunch of other hidden under-the-hood stuff
Few words in terms of architecture and structural approach in my solution:
Everything works with Data binding
RecyclerView works with Adapter that supports AdapterDelegate approach
Each EditText, Spinner, DatePicker, CheckBox or RadioButton group is a separate ViewModel which is a separate unit and handles a lot of stuff on its own.
I've used a lot of tricks and mixed them together. As someone already mentioned, the first step would be to add those params to your RecyclerView:
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
Base view model for all possible inputs has defined interface, let's call it SingleInputViewModel, among that interface you can have defined next functions/methods:
void onFocusGained();
void onFocusLost();
boolean isFocusable();
In each particular input item implementation you are able to control focus, for example you are able to implement CheckBox as non-focusable and focus will jump to next isFocusable() == true item. Also you will be able to control the state and action depending on consuming/gaining focus on particular view.
Next step for fixing some of the focus passing issues - was scrolling RecyclerView when IME_ACTION_NEXT occurs. In such case you need to delegate your scroll logic to LayoutManager.scrollHorizontallyBy() or LayoutManager.scrollToPosition() with calculating appropriate offset or position.
Hard and elegant approach is to override logic inside LayoutManager, which is also responsible for focus handling. LinearLayoutManager has a lot of hidden logic, which you won't be able to override, so probably you will need to write a lot of code from scratch.
And the last and the most complex way to fix that is to extend RecyclerView and override focus search related funs/methods:
RecyclerView.focusSearch()
RecyclerView.isPreferredNextFocus()
RecyclerView.onRequestFocusInDescendants()
RecyclerView.onFocusSearchFailed()
RecyclerView.onInterceptFocusSearch()
RecyclerView.onRequestChildFocus()
P.S. Have a look at the FocusFinder and it's usage, just for general knowledge. Now you have few option to choose. I hope you will find something helpful. Good luck!
Using this in layout worked :
android:descendantFocusability="beforeDescendants"
<android.support.v7.widget.RecyclerView
android:id="#+id/recyclerview"
android:descendantFocusability="beforeDescendants"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#+id/extrasLayout"
android:layout_below="#+id/anchorView"
android:layout_marginTop="#dimen/margin5"
android:fastScrollEnabled="false"
/>
Manifest file : Add this to the activity section android:windowSoftInputMode="stateHidden|adjustPan"
<activity
android:name=".activites.CartActivity"
android:label="#string/title_activity_cart"
android:exported="true"
android:windowSoftInputMode="stateHidden|adjustPan"
android:parentActivityName=".activites.HomeActivity"
android:screenOrientation="portrait">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".activites.HomeActivity"/>
</activity>
Ok
I found a solution for this problem
I'm using a library for that and it solved easily.
when you make your recyclerView by this template, it solves this problem automatically.
NOTE: for checkbox and radiobutton only
use this
https://github.com/TakeoffAndroid/RecyclerViewTemplate
I'm going to post my solution because after 2 days being blocked by this I hope that it could help someone else.
My issue was that the RecyclerView was a wrap_content on the height, meaning it didn't have a fixed height, and every time i clicked for the first time on one of the edit text inside it, it wasn't giving the focus on the first tap, but it was just showing the keyboard, on the second tap it was gaining the focus.
The fix was to make sure the RecyclerView has a fixed height or match_parent, i don't really know why but this worked for me!
Hope it helps
I put all these three things in recyclerview finally it stopped recyclerview edittext gaining focus
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
This is happening because from the android 9.0 you have to write post()-> to gain focus of edittext in Previous versions you can just put
edittext.requestFocus();
but from 9.0 you have to run thread to gain focus of edittext like this
et.post(() -> {et.requestFocus();});
You can scroll recyclerview to selected recycler item position on edit text focus change listener . Have a look at link to use scroll option How to use RecyclerView.scrollToPosition() to move the position to the top of current view?
I know there are a lot of similar questions out here
but I couldn't get any of the provided solutions working in a simple sample app.
The problem occurs when the softkeyboard is shown for the first time. As soon as it is shown, only by pressing the editText again makes it editable.
Tried the following:
android:windowSoftInputMode="adjustPan|adjustResize"
This is not solving any issues. It seems that this line is mandatory to have the activity resized after the softkeyboard is popping up. Unfortunately, it's also causing any EditTexts to lose focus. This is probably to the ListView itself gaining focus after the resizing process. So I tried the following workaround:
listView.setDescendantFocusability(ViewGroup.FOCUS_AFTER_DESCENDANTS);
This always causes the first visible EditText that the ListView contains to gain focus, which is undesirable. The second EditText in the second row should instead gain focus when pressed, which is not happening. Also, if I eventually managed to focus another EditText other then the first one shown (e.g. by pressing 'Next' on the softkeyboard), the first visible one will receive focus after the keyboard is dismissed and the ListView being resized to its full size again.
I tried several other things like intercepting onFocusChange() events for the ListView, while knowing which EditText was pressed by its TouchListener. Requesting the focus for that certain EditText again did not lead to any success either.
Using a ScrollView instead of a ListView as suggested by other users is not an option either for the concerned project.
A classic hack for situations like this is to use a handler and postDelayed(). In your adapter:
private int lastFocussedPosition = -1;
private Handler handler = new Handler();
public View getView(final int position, View convertView, ViewGroup parent) {
// ...
edittext.setOnFocusChangeListener(new OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
handler.postDelayed(new Runnable() {
#Override
public void run() {
if (lastFocussedPosition == -1 || lastFocussedPosition == position) {
lastFocussedPosition = position;
edittext.requestFocus();
}
}
}, 200);
} else {
lastFocussedPosition = -1;
}
}
});
return convertView;
}
This works on my device, but keep this code out of production. I also wouldn't be surprised if the focus bug manifests itself differently in different android versions or roms.
There are also many other problems with embedding an EditText within a ListView that have solutions that feel like a hack. See all of the other people struggling.
It's also very easy to have something like this happen:
.
After having gone down similar paths many times myself, I've mostly given up on trying to override any of the default keyboard behaviours or quirks. I would recommend trying to find alternative solution in your app if possible.
Have you considered having the ListView rows be just a styled TextView and then displaying a Dialog with an EditText when a row is clicked, updating the TextView as necessary?
I was having problems with the ActionBar "stealing" focus when I pressed on an EditText located within a ListView row. The above solutions did not work, but the following solution worked for me:
http://www.mysamplecode.com/2013/02/android-edittext-listview-loses-focus.html
Basically I added this to my ListView:
android:descendantFocusability="beforeDescendants"
and added this to my activity:
android:windowSoftInputMode="adjustPan"
Modify your manifest xml to add windowSoftInputMode in your activity:
<activity
android:name=".YourActivity"
android:windowSoftInputMode="adjustPan">
</activity>
I know its a very old thread but this answer might be helpful to someone so here it is:
Switch to RecyclerView and you won't have to worry about these annoying issues of ListView. Instead of making new view it recycles and reuses old views.
I was having the same problem with recyclerView and trying all suggested solutions.
Finally, the problem on my case was that the recyclerView had wrap_content as value for the height on my XML by accident; changed it to match_parent and started working as expected, no focusable value set and using android:windowSoftInputMode="adjustResize"
Use Recycler View, this solves several issues from list and gridview. You can even work with staggered gridviews. You could easily start working with this.
When the list is long enough to cover the soft keyboard, the
EditText in Listview loses focus when pressed on Android 4.x.
One solution is to wrap the Listview in a linear layout with a height of half the screen.
Whenever the Listview doesn't cover the softkeyboard, everything is fine.
was having the same issue. Searched for all such solutions with inputMode, focusability et al. Best solution, migrate to recycler view.
In my case I've added local value currentlyFocusedRow in my Adapter.
In the method getView() I've add these code to each editText:
if (currentlyFocusedRow == position) {
editText.requestFocus();
}
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
if (currentlyFocusedRow == -1) {
currentlyFocusedRow = position;
}
} else {
currentlyFocusedRow = -1;
}
}
});