2015-05-09 93 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)); 
    
    } 
    }