web-dev-qa-db-ja.com

Recyclerview、getChildAt(position)でアイテムビューを取得できません。ヌルオブジェクト参照

ナビゲーションドロワー内でrecyclerViewを使用しており、このライブラリを使用しています Twoway-view クリックと選択のサポートを取得しています。

それは完璧に機能し、各位置のOnClickメソッド内で問題なくテキストとアイコンの色を変更できます。

itemClickSupport.setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
        @Override
        public void onItemClick(RecyclerView parent, View view, int position, long id) {
            TypedValue typedValue = new TypedValue();
            MainActivity.this.getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
            final int color = typedValue.data;

            //TODO Icon and text colors

            for (int i = 0; i < drawerTitles.length; i++){
                if (i == position){
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(color);
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(255);
                    }else{
                        imageViewDrawerIcon.setAlpha(255);
                    }
                    textViewDrawerTitle.setTextColor(color);
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(true);
                }else{
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(getResources().getColor(R.color.md_text));
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(138);
                    }else{
                        imageViewDrawerIcon.setAlpha(138);
                    }
                    textViewDrawerTitle.setTextColor(getResources().getColor(R.color.md_text));
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(false);
                }
            }

            //TODO Fragments (closedrawers before setfragment)
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // Do something after some time

                }
            }, 250);
            mDrawerLayout.closeDrawers();
        }
    });

問題は、そのメソッドのように最初のアイテムにアクセスしたいのですが、その前に(最初に選択したアイテムを異なる色で設定するなど)です。

しかし、OnClickメソッドの外部で最初のアイテムを取得しようとするとクラッシュ(null参照)が発生します:

ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.imageViewDrawerIcon);

すべてのコード:

// Setup RecyclerView inside drawer
    recyclerViewDrawer = (RecyclerView) findViewById(R.id.recyclerViewDrawer);
    recyclerViewDrawer.setHasFixedSize(true);
    recyclerViewDrawer.setLayoutManager(new LinearLayoutManager(MainActivity.this));

    ArrayList<DrawerItem> drawerItems = new ArrayList<>();
    final String[] drawerTitles = getResources().getStringArray(R.array.drawer);
    final TypedArray drawerIcons = getResources().obtainTypedArray(R.array.drawerIcons);
    for (int i = 0; i < drawerTitles.length; i++) {
        drawerItems.add(new DrawerItem(drawerTitles[i], drawerIcons.getDrawable(i)));
    }
    drawerIcons.recycle();
    adapterDrawer = new DrawerAdapter(drawerItems);
    recyclerViewDrawer.setAdapter(adapterDrawer);

    // Here is the problem
    ImageView imageViewDrawerIcon2 = (ImageView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.imageViewDrawerIcon);

    // RecyclerView item listener.
    ItemClickSupport itemClickSupport = ItemClickSupport.addTo(recyclerViewDrawer);
    itemClickSupport.setOnItemClickListener(new ItemClickSupport.OnItemClickListener() {
        @Override
        public void onItemClick(RecyclerView parent, View view, int position, long id) {
            TypedValue typedValue = new TypedValue();
            MainActivity.this.getTheme().resolveAttribute(R.attr.colorAccent, typedValue, true);
            final int color = typedValue.data;

            //TODO Icon and text colors

            for (int i = 0; i < drawerTitles.length; i++){
                if (i == position){
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(color);
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(255);
                    }else{
                        imageViewDrawerIcon.setAlpha(255);
                    }
                    textViewDrawerTitle.setTextColor(color);
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(true);
                }else{
                    ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.imageViewDrawerIcon);
                    TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(i).findViewById(R.id.textViewDrawerItemTitle);
                    imageViewDrawerIcon.setColorFilter(getResources().getColor(R.color.md_text));
                    if(Build.VERSION.SDK_INT > 15){
                        imageViewDrawerIcon.setImageAlpha(138);
                    }else{
                        imageViewDrawerIcon.setAlpha(138);
                    }
                    textViewDrawerTitle.setTextColor(getResources().getColor(R.color.md_text));
                    RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(i).findViewById(R.id.relativeLayoutDrawerItem);
                    relativeLayoutDrawerItem.setFocusableInTouchMode(false);
                }
            }

            //TODO Fragments (closedrawers before setfragment)
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    // Do something after some time

                }
            }, 250);
            mDrawerLayout.closeDrawers();
        }
    });

私はこれで最終的に解決しました( ソース ):

recyclerViewDrawer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            ImageView imageViewDrawerIcon = (ImageView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.imageViewDrawerIcon);
            TextView textViewDrawerTitle = (TextView) recyclerViewDrawer.getChildAt(0).findViewById(R.id.textViewDrawerItemTitle);
            imageViewDrawerIcon.setColorFilter(color);
            if (Build.VERSION.SDK_INT > 15) {
                imageViewDrawerIcon.setImageAlpha(255);
            } else {
                imageViewDrawerIcon.setAlpha(255);
            }
            textViewDrawerTitle.setTextColor(color);
            RelativeLayout relativeLayoutDrawerItem = (RelativeLayout) recyclerViewDrawer.getChildAt(0).findViewById(R.id.relativeLayoutDrawerItem);
            relativeLayoutDrawerItem.setFocusableInTouchMode(true);
            // unregister listener (this is important)
            recyclerViewDrawer.getViewTreeObserver().removeGlobalOnLayoutListener(this);
        }
    });

ちなみに、誰かがもっと良い解決策を持っているなら、私はそれを知りたいです。

私の場合、それは魅力のように機能します

View viewItem = recycleView.getLayoutManager().findViewByPosition(position);
    View icon = viewItem.findViewById(R.id.view);
13

これは私のために働いた。

recyclerView.post(new Runnable() {
  @Override
  public void run() {
    View viewItem = recycleView.getLayoutManager().findViewByPosition(position);
    View icon = viewItem.findViewById(R.id.view);
  }
});
6
Herman

代わりに findViewHolderForAdapterPosition() または findViewByPosition( )を使用して、そのインデックスでルートビューを検索します。ただし、データを確実にロードする方法はあなた次第です。

5
AllDayAmazing

findViewByPositionLayoutManagerのメソッドであり、すべてのLayoutManagerで機能します。

したがって、recycleView.getLayoutManager()およびfindViewByPosition(pos)を使用できます。

また、recyclerView.findViewHolderForAdapterPosition(pos)も機能します。

詳細については、これを参照してください RecyclerView-特定の位置でビューを取得します

0
Kaibo