【问题标题】:Recyclerview, I can't get item view with getChildAt(position). Null object referenceRecyclerview,我无法使用 getChildAt(position) 获取项目视图。空对象引用
【发布时间】:2015-04-02 17:19:12
【问题描述】:

我在导航抽屉中使用了一个 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 方法之外获取第一个项目时,我遇到了崩溃(空引用):

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();
        }
    });

【问题讨论】:

标签: android android-recyclerview get-childitem


【解决方案1】:

我终于解决了这个问题 (source):

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);
        }
    });

顺便说一句,如果有人有更好的解决方案,我想知道。

【讨论】:

  • 我们仍然得到一些getChildViiew(0) 使用这种方法为空的实例。我个人无法复制它。使用setAdapter 会触发子视图膨胀,因此理想情况下会在子视图膨胀并添加到 RecyclerView 时调用回调
【解决方案2】:

我会使用findViewHolderForAdapterPosition()findViewByPosition() 代替在该索引处查找根视图。但是,确保数据加载的方式取决于您。

【讨论】:

    【解决方案3】:

    在我的情况下,工作就像一个魅力

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

    【讨论】:

    • 给出警告“在 Android 4.1 之前,方法 int android.support.v7.widget.ListViewCompat.lookForSelectablePosition(int, boolean) 会错误地覆盖 android.widget.ListView 中的包私有方法”
    • 它返回null
    • 似乎只有在项目现在可见时才有效,没用。即使我在调用findViewByPosition(position) 之前先调用layoutManager.scrollToPosition(position),它仍然不起作用
    【解决方案4】:

    这对我有用。

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

    【讨论】:

    • 很好,这非常适合使用 getChildAt()getChildViewHolder() 获取显示的孩子和查看者
    • 值得注意的是,你不能用它来操作许多 UI 元素,因为你是在不同的线程中工作的。您必须设置线程间通信。
    【解决方案5】:

    findViewByPositionLayoutManager的一个方法,适用于所有的LayoutManager。

    所以你可以使用recycleView.getLayoutManager()findViewByPosition(pos)

    recyclerView.findViewHolderForAdapterPosition(pos) 也可以使用。

    欲了解更多信息,请查看此RecyclerView - Get view at particular position

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-07-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多