2015-05-09 110 views
0

我想编写我自己的recyclerview slector算法。到目前为止,除了处理第一个选择之外,我成功地部分编写了代码。基本上我想设置背景为蓝色选择的项目,白色在别处(与ListView的setSelection相同)。RecyclerView抽屉 - 设置选择

所以,这个想法是:

  1. 设置在适配器的onCreateViewHolder方法的第一个元素蓝色背景。
  2. 在ActivityMain,定义一个intance查看变量navMenuSelection存储当前选择
  3. 在recyclerView的onclick监听器,设置点击视图蓝,背景navMenuSelection,为白色的背景,并更新navMenuSelection到点击视图

所有工作除外: 1.无法用第一个视图初始化navMenuSelection。试图用mDrawerLayout.getChildAt(0)在onPostCreate方法,但返回null

  • 如何通过在savedInstanceState视图navMenuSelection捆绑?
  • 任何想法将不胜感激。

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

    更好地把它放在recyclerview的适配器上。显示适配器代码 – Genevieve

    +0

    right ur ..已将代码移至适配器..但是,无法从位置获取oldviewholder。 – abdfahim

    +0

    显示适配器的代码 – Genevieve

    回答

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

    只是尝试调试,如果有任何错误或错字。我没有使用任何代码编辑器,因此可能有一些错误

    +0

    谢谢,有想法..它会工作,我可以理解..顺便说一句,在这种方法中,我设置每个元素的背景,不管新旧背景是否相同,对吗?也只是出于好奇,我可以使用findViewHolderForAdapterPosition函数吗?我无法让findViewHolderForAdapterPosition起作用。 – abdfahim

    1

    至于你的问题:

    1. 为了让你在RecyclerView需要你可以使用mRecyclerView.findViewHolderForAdapterPosition(position)视图。
    2. 我可能是错的,但我认为你只需要保存视图的位置,而不是视图本身,这只是int

    另一种模式,我以前用过,是增加一个布尔数组你RecyclerView.Adapter,节省了大约什么看法(S)(与您的数据集合中的位置有关)的信息应在瞬间被激活。基于这个数组,我改变了onBindViewHolder()中的背景。

    如果回收站视图足够短以便在单个屏幕上显示,那么您当前的解决方案是可以的。但只要它开始回收旧的观看者,您就会在未选择的视图上重新使用“选定”的背景 - 所有这些都是因为您记住了视图,而不是与他们相关的数据位置。

    编辑

    我把这里的一些相关的代码从适配器来说明我的想法实现。在我的方法中,我使用了一个状态列表,可以用激活的状态的“selected”背景绘制,但您可以通过手动设置背景完成相同的操作。

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

    非常感谢理念。但我找不到方法mRecyclerView.findViewHolderForAdapterPosition(int)虽然它被记录..非常奇怪!而且,如果我在适配器的onBindViewHolder中实现onclick方法,如何调用它? – abdfahim

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