I have some images arranged in horizontal grid. I want to move my grid from left to right and right to left using key events. When I move through the grid two things happened
The item at second position is selected. For example, I'm at position 0 and want to select the next item at position 1, but my grid select the position 2 item and skips the position 1 item.
on scrolling I get the null pointer exception
if(keyCode == KeyEvent.KEYCODE_DPAD_RIGHT)
{
if (mCurrentSelectedPosition + 1 < getItemCount()) {
Log.e("current position1",Integer.toString(mCurrentSelectedPosition));
gridHolder = (GridView_Holder) mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition);
gridHolder.itemView.setSelected(false);
notifyItemChanged(mCurrentSelectedPosition);
notifyDataSetChanged();
int lastItem = lm.findLastCompletelyVisibleItemPosition();
Log.e("last item",Integer.toString(lastItem));
if ((mCurrentSelectedPosition + 1) > lastItem) {
// Log.e("Is less", "true");
recyclerView.smoothScrollToPosition(mCurrentSelectedPosition + 1);
Log.e("current position2",Integer.toString(mCurrentSelectedPosition));
} else {
gridHolder = (GridView_Holder) mRecyclerView.findViewHolderForPosition(mCurrentSelectedPosition + 1);
gridHolder.itemView.setSelected(true);
Log.e("current position3",Integer.toString(mCurrentSelectedPosition));
}
mCurrentSelectedPosition += 1;
Log.e("current position4",Integer.toString(mCurrentSelectedPosition));
}
return true;
}
scroll listener
gridRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(RecyclerView recyclerView, int x, int y)
{
super.onScrolled(recyclerView, x, y);
try {
GridView_Holder gridHolder;
gridHolder= (GridView_Holder) recyclerView.findViewHolderForPosition(adapter.mCurrentSelectedPosition);
gridHolder.itemView.setSelected(true);
}catch(Exception e){
Log.e("exception",e.getMessage());
}
}
this is my logcat
java.lang.NullPointerException: Attempt to read from field 'android.view.View android.support.v7.widget.RecyclerView$ViewHolder.itemView' on a null object reference
at com.winettv.recylcerviewwithdpad.GridView_Recycler_Adapter$1.onKey(GridView_Recycler_Adapter.java:193)
at android.view.View.dispatchKeyEvent(View.java:9230)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1635)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.widget.ScrollView.dispatchKeyEvent(ScrollView.java:379)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at android.view.ViewGroup.dispatchKeyEvent(ViewGroup.java:1640)
at com.android.internal.policy.PhoneWindow$DecorView.superDispatchKeyEvent(PhoneWindow.java:2395)
at com.android.internal.policy.PhoneWindow.superDispatchKeyEvent(PhoneWindow.java:1727)
at android.app.Activity.dispatchKeyEvent(Activity.java:2725)
at android.support.v7.app.AppCompatActivity.dispatchKeyEvent(AppCompatActivity.java:543)
at android.support.v7.view.WindowCallbackWrapper.dispatchKeyEvent(WindowCallbackWrapper.java:53)
at android.support.v7.app.AppCompatDelegateImplBase$AppCompatWindowCallbackBase.dispatchKeyEvent(AppCompatDelegateImplBase.java:315)
When I developed library with custom translation during scroll I had the same issue. Only in fast scrolling, when i tried to access View element from List, that was null and here is NPE.
So there is pretty simple solution just skip elements, which is empty, and continue with new one. In my case it was like this:
// Other init....
for (int i = 0; i < MainListView.getChildCount; i++) {
if (MainListView.getChildAt(i) == null)
continue;
// Continue base behavior
}
This happens, based on ScrollView (which is parent for RecycleView, ListView, etc.) When we trying to access View which is redrawing now. Anyway just simple Null checking should solve your problem.
UPDATE 1:
Also based on caching View layouts of RecyclerView, you need another option. See below.
gridRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener(){
@Override
public void onScrolled(RecyclerView recyclerView, int x, int y)
{
super.onScrolled(recyclerView, x, y);
GridView_Holder gridHolder;
gridHolder= (GridView_Holder) recyclerView.findViewHolderForPosition(adapter.mCurrentSelectedPosition);
if (gridHolder != null && gridHolder.itemView != null) {
gridHolder.itemView.setSelected(true);
}
}
}