RecyclerView抽屉 - 设置选择

时间:2015-05-09 04:08:29

标签: android android-recyclerview

我正在尝试编写自己的recyclerview slector算法。到目前为止,除了处理第一个选择之外,我成功地设法编写了部分代码。基本上我想将背景设置为所选项目的蓝色,其他地方为白色(与ListView&#39的setSelection相同)。

所以,这个想法是:

  1. 为Adapter的onCreateViewHolder方法中的第一个元素设置蓝色背景。
  2. 在ActivityMain中,定义一个intance View变量navMenuSelection来存储当前选择
  3. 在recyclerView的onclick监听器中,将单击视图的背景设置为蓝色,将navMenuSelection的背景设置为白色,并将navMenuSelection更新为单击的视图
  4. 一切正常,除了: 1.无法使用第一个视图初始化navMenuSelection。试图在onPostCreate方法中使用mDrawerLayout.getChildAt(0),但返回null

    1. 如何在savedInstanceState包中传递视图navMenuSelection?
    2. 任何想法都将受到高度赞赏。

      public class ActivityMain extends AppCompatActivity {
          private View navMenuSelection = null; // Select current view
      
          protected void onCreate(Bundle savedInstanceState) {
          // ALL THE CODES TO DEFINE RECYCLERVIEW
      
              mRecyclerView.addOnItemTouchListener(new RecycleTouchListener(this, new ClickListner() {
                  @Override
                  public void onClick(View view, int position) {
                      if(view != navMenuSelection){
                          setNavItemSelected(view);
                          removeNavItemSelected(navMenuSelection);
                          navMenuSelection = view;
                          mDrawerLayout.closeDrawers();
                      }
                  }
              }));
          }
      
          @Override
          protected void onPostCreate(Bundle savedInstanceState) {
              super.onPostCreate(savedInstanceState);
              mDrawerToggle.syncState();
              navMenuSelection = mDrawerLayout.getChildAt(0);
          }
          @Override
          public void onSaveInstanceState(Bundle savedInstanceState){
              //savedInstanceState.put???("currselection", navMenuSelection); // HOW TO DO THAT
              super.onSaveInstanceState(savedInstanceState);
          }
      
          public void setNavItemSelected(View v){
              if(v!= null) {
                  v.setBackgroundColor(R.color.BLUE));
              }
          }
      
          public void removeNavItemSelected(View v){
              if(v!= null) {
                  v.setBackgroundColor(R.color.WHITE));
              }
          }
      }
      

      适配器类(将onClick事件移至适配器后)

      public class NavDrawerAdapter extends RecyclerView.Adapter<NavDrawerAdapter.ViewHolder> {
      
          private String[] mNavTitles; // stores title
          private int[] mIcons; // stores icon
      
          private Context context;
          private int oldpostion = 0;
      
          public NavDrawerAdapter(Context context, String Titles[], int[] Icons){
              this.context = context;
              mNavTitles = Titles;
              mIcons = Icons;
          }
      
          public class ViewHolder extends RecyclerView.ViewHolder {
      
              TextView textView;
              ImageView imageView;
      
              public ViewHolder (View itemView) {
                  super(itemView);
                  textView = (TextView) itemView.findViewById(R.id.title);
                  imageView = (ImageView) itemView.findViewById(R.id.icon);
              }
          }
      
          @Override
          public NavDrawerAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
              View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.navdrawer_item,parent,false);
              return new ViewHolder(v,viewType);
          }
      
          @Override
          public void onBindViewHolder(NavDrawerAdapter.ViewHolder holder, final int position) {
              holder.textView.setText(mNavTitles[position]);
              holder.imageView.setImageResource(mIcons[position]);
              if(position == 0) {
                  setNavItemSelected(holder.itemView);
              }
              holder.itemView.setOnClickListener(new View.OnClickListener() {
                  @Override
                  public void onClick(View v) {
                      if(position != oldpostion){
                          setNavItemSelected(v);
                          //removeNavItemSelected(OLD VIEW);
                          oldpostion = position;
                      }
                  }
              });
          }
      
          @Override
          public int getItemCount() {
              return mNavTitles.length;
          }
      
          @Override
          public int getItemViewType(int position) {
              return 1;
          }
      
          public void setNavItemSelected(View v){
              if(v!= null) {
                  v.setBackgroundColor(context.getResources().getColor(R.color.navdrawer_item_selected_bg));
                  TextView tview = (TextView) v.findViewById(R.id.title);
                  tview.setTextColor(context.getResources().getColor(R.color.navdrawer_item_selected_text));
              }
          }
      
          public void removeNavItemSelected(View v){
              if(v!= null) {
                  v.setBackgroundResource(R.drawable.list_selector_nav_drawer);
                  TextView tview = (TextView) v.findViewById(R.id.title);
                  tview.setTextColor(context.getResources().getColorStateList(R.color.list_selector_nav_drawer_text));
              }
          }
      }
      

3 个答案:

答案 0 :(得分:1)

关于你的问题:

  1. 要在RecyclerView中获取您需要的视图,您可以使用mRecyclerView.findViewHolderForAdapterPosition(position)
  2. 我可能错了,但我认为你只需要保存视图的位置,而不是视图本身,这只是int
  3. 我之前使用的另一种模式是向RecyclerView.Adapter添加一个布尔数组,用于保存当前应激活哪些视图(与数据集合中的位置相关联)的信息。基于这个数组,我正在改变onBindViewHolder()中的观点背景。

    如果回收站视图足够短,可以在单个屏幕上看到,那么您当前的解决方案是可以的。但是一旦它开始回收它的旧观看者,你就会在未选择的视图中重复使用“选定”背景 - 所有这些都是因为你记住了视图,而不是连接到它们的数据位置。

    修改

    我将在这里放一些来自适配器的相关代码来说明我对实现的想法。在我的方法中,我使用了一个状态列表,可以使用“选定”背景绘制激活的状态,但你可以通过手动设置背景来完成所有操作。

    public class RecyclerAdapter
            extends RecyclerView.Adapter<RecyclerAdapter.YourViewHolder> {
    
        private final List<...> data;
        private final RecyclerAdapterCallbacks listener; //e.g. for activity callbacks
        private final List<Boolean> activation;
    
        public RecyclerAdapter(List<...> data, RecyclerAdapterCallbacks listener) {
            this.data = data;
            this.listener = listener;
            this.activation = new ArrayList<>(data.size());
            fillActivationList();
        }
    
        private void fillActivationList() {
            int size = data.size();
            for (int i = 0; i < size; i++) activation.add(false);
        }
    
        //------YourViewHolder implementation here------
    
        public interface RecyclerAdapterCallbacks { //Callbacks interface if needed
            void onRowSelected(... dataPiece);
    
            void onRowDeselected();
        }
    
        @Override
        public WordsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            //your code
        }
    
        @Override
        public void onBindViewHolder(YourViewHolder holder, final int position) {
            holder.field.setText(data.get(position).getString());
    
            holder.itemView.setActivated(activation.get(position));
            holder.itemView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    Boolean previousState = activation.get(position);
                    deactivateAll();
                    activation.set(position, !previousState);
                    notifyDataSetChanged();
                    if (!previousState) {
                        listener.onRowSelected(data.get(position));
                    } else {
                        listener.onRowDeselected();
                    }
                }
            });
        }
    
        private void deactivateAll() {
            Collections.fill(activation, false);
        }
    
        @Override
        public int getItemCount() {
            return data.size();
        }
    
        public void clearResults() {
            notifyItemRangeRemoved(0, data.size());
            data.clear();
            activation.clear();
        }
    
        public void add(Word item) {
            data.add(item);
            notifyItemInserted(data.size() - 1);
            activation.add(false);
        }
    

答案 1 :(得分:0)

由于你已经在使用数组来传递你的图标和标题,让我们添加另一个数组来保存你当前的选择

 private boolean isSelected[] = {true, false, false, false, false};   //make sure that the length of this array matches the length of navtitles and navicon. set the first element to true since you want the first item to be selected by default. you can declare this directly on the adapter if this is static

或者您可以将其作为参数传递

private boolean isSelected[];
public NavDrawerAdapter(Context context, String Titles[], int[] Icons, boolean[] isSelected){
    this.context = context;
    mNavTitles = Titles;
    mIcons = Icons;
    this.isSelected = isSelected;
}

....


@Override
public void onBindViewHolder(NavDrawerAdapter.ViewHolder holder, final int position) {

    holder.itemView.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            for(int i=0; i < isSelected.length(); i++){
                if (i==position){
                    isSelected[position]=true;
                else
                    isSelected[position]=false;
            }
            notifyDataSetChanged();
        }
    });

    if (isSelected[position]==true){
        //execute your codes here
    }else{
        //execute your codes here

    }
}

只是尝试调试是否有任何错误或拼写错误。我没有使用任何代码编辑器,所以可能会有一些错误

答案 2 :(得分:0)

为了方便您,我建议您只在视图中添加布局,这样您就可以更改布局的背景。不是最干净的方法,但这个应该为你做的伎俩

public class ViewHolder extends RecyclerView.ViewHolder {

    TextView textView;
    ImageView imageView;
    LinearLayout layout; //whatever layout your using, just an example

    public ViewHolder (View itemView) {
        super(itemView);
        textView = (TextView) itemView.findViewById(R.id.title);
        imageView = (ImageView) itemView.findViewById(R.id.icon);
        layout = (LinearLayout) itemView.findViewById(R.id.layout);
    }
}

...

@Override
public void onBindViewHolder(NavDrawerAdapter.ViewHolder holder, final int position) {

holder.itemView.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        for(int i=0; i < isSelected.length(); i++){
            if (i==position){
                isSelected[position]=true;
            else
                isSelected[position]=false;
        }
        notifyDataSetChanged();
    }
});

if (isSelected[position]==true){
    //execute your codes here
     holder.layout.setBackgroundResource(R.drawable.list_selector_nav_drawer);          
     holder.textView.setTextColor(context.getResources().getColorStateList(R.color.list_selector_nav_drawer_text));

}else{
    //execute your codes here
     holder.layout.setBackgroundResource(R.drawable.list_selector_nav_drawer);
     holder.textView.setTextColor(context.getResources().getColorStateList(R.color.list_selector_nav_drawer_text));

}
}