2016-07-20 2 views
2
  • Я реализую Recyclerview в своем приложении, и мне нужно, чтобы его элемент щелкнул обновление другого списка, поэтому я применил событие onClick в действии. Он работает нормально.
  • Но мне также нужно было, чтобы High Light RecyclerView выбрал вид, а другие остались в норме.
  • Для этого я использовал метод RecyclerView getChild, чтобы сделать все представление нормальным, а затем выбранным.
  • Я понимаю, что он работает только для видимых видов RecyclerView. Но мне нужно было сделать нормальные все виды Recyclerview, и если бы я использовал getChildAt с более крупной позицией, то итоговый видимый счетчик возвращает исключение Null Pointer.
    • Log, что я получаю

E/Пункт Pos: 29RecyclerView getChildAt (position) возвращает null

E/Item Rv: 15

E/Детский адаптер: 30

MainActivity.java

public class MainActivity extends Activity { 
RecyclerView reView; 
ArrayList<RvModel> rvModels; 
revAdapter adapter; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 
    reView = (RecyclerView) findViewById(R.id.reView); 
    reView.setLayoutManager(new GridLayoutManager(MainActivity.this, 3)); 

    rvModels = new ArrayList<>(); 
    adapter = new revAdapter(MainActivity.this, rvModels); 
    reView.setAdapter(adapter); 
    prepareData(); 
    reView.addOnItemTouchListener(new RecyclerItemClickListener(MainActivity.this, reView, new RecyclerItemClickListener.OnItemClickListener() { 
     @Override 
     public void onItemClick(View view, int position) { 
      Log.e("Item Pos", "" + position); 
      Log.e("Item Rv", "" + reView.getChildCount()); 
      Log.e("Child Adapter", "" + reView.getAdapter().getItemCount()); 

      for (int i = 0; i < reView.getChildCount(); i++) { 
       View v = reView.getChildAt(i); 
       TextView txtText = (TextView) v.findViewById(R.id.txtText); 

       txtText.setBackgroundColor(Color.WHITE); 
       txtText.setTextColor(Color.BLUE); 
      } 
      TextView txtText = (TextView) view.findViewById(R.id.txtText); 
      txtText.setBackgroundColor(Color.BLUE); 
      txtText.setTextColor(Color.WHITE); 
     } 

     @Override 
     public void onLongItemClick(View view, int position) { 

     } 
    })); 
} 

private void prepareData() { 
    rvModels.clear(); 
    for (int i = 0; i < 30; i++) { 
     RvModel rvModel = new RvModel(); 
     rvModel.setTitle("Item : " + i); 
     rvModels.add(rvModel); 
    } 
    adapter.notifyDataSetChanged(); 
    } 
} 

revAdapter.java

public class revAdapter extends RecyclerView.Adapter<revAdapter.ViewHolder> { 
Context context; 
ArrayList<RvModel> rvModels; 
LayoutInflater inflater; 

public revAdapter(Context context, ArrayList<RvModel> rvModels) { 
    this.context = context; 
    this.rvModels = rvModels; 
    inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 
} 

public class ViewHolder extends RecyclerView.ViewHolder { 
    ImageView ivIcon; 
    TextView txtText; 

    public ViewHolder(View itemView) { 
     super(itemView); 
     ivIcon = (ImageView) itemView.findViewById(R.id.ivIcon); 
     txtText = (TextView) itemView.findViewById(R.id.txtText); 
    } 
} 

@Override 
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { 
    View itemView = inflater.inflate(R.layout.rv_raw, parent, false); 
    return new ViewHolder(itemView); 
} 

@Override 
public void onBindViewHolder(ViewHolder holder, int position) { 
    RvModel rvModel = rvModels.get(position); 
    holder.txtText.setText(rvModel.getTitle()); 
} 

@Override 
public int getItemCount() { 
    return rvModels.size(); 
} 

@Override 
public int getItemViewType(int position) { 
    return position; 
    } 
} 

rv_raw.xml

<?xml version="1.0" encoding="utf-8"?> 
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
android:gravity="center" 
android:orientation="vertical"> 

<LinearLayout 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:orientation="vertical" 
    android:padding="10dp"> 

    <ImageView 
     android:id="@+id/ivIcon" 
     android:layout_width="100dp" 
     android:layout_height="100dp" 
     android:src="@mipmap/ic_launcher" /> 

    <TextView 
     android:id="@+id/txtText" 
     android:layout_width="wrap_content" 
     android:layout_height="wrap_content" 
     android:text="Medium Text" 
     android:textAppearance="?android:attr/textAppearanceMedium" /> 
</LinearLayout> 

ответ

4

Проблема в том, что recyclerView как в виде списка есть число просмотров ребенка (элементов) зависит от ваш размер экрана, а не на сколько у вас предметов. Это предотвращает приложение из исключения OOM. Например, если у вас есть 1M-элементы, то из вашей логики представление recycler должно было создать 1M-подпункты, и это плохо. Вы можете узнать больше о виде списка here (вид ресайклера работает точно так же)

Так что в вашем случае в onClick событиям не нужно искать и изменять его. Вам нужно изменить некоторые так называемые «настройки» и написать notifyDataSetChanged или notifyItemChanged для большей оптимизации.

Также я проверил ваш код, и я прошу вас. Пожалуйста, пожалуйста, удалите эту перекрываться функцию:

@Override 
public int getItemViewType(int position) { 
    return position; 
} 

Вы используете тот же держатель для всех элементов, таким образом, есть только один тип взглядов на ваш взгляд ресайклера. Переопределяя этот метод таким образом, вы сообщаете вашему ресайклеру, что каждый элемент использует разный макет, который снижает производительность.

Так, по вашему вопросу, вы будете иметь какой-то:

reView.addOnItemTouchListener(new RecyclerItemClickListener(MainActivity.this, reView, new RecyclerItemClickListener.OnItemClickListener() { 
    @Override 
    public void onItemClick(View view, int position) { 
     Log.e("Item Pos", "" + position); 
     Log.e("Item Rv", "" + reView.getChildCount()); 
     Log.e("Child Adapter", "" + reView.getAdapter().getItemCount()); 

     if (!adapter.isChecked(position)) { 
      adapter.setChecked(position); 
     } 
    } 

    @Override 
    public void onLongItemClick(View view, int position) { 

    } 
})); 

адаптер:

private int checkedPosition = -1; 

@Override 
public void onBindViewHolder(ViewHolder holder, int position) { 
    RvModel rvModel = rvModels.get(position); 
    holder.txtText.setText(rvModel.getTitle()); 

    if (position == checkedPosition) { 
     txtText.setBackgroundColor(Color.BLUE); 
     txtText.setTextColor(Color.WHITE); 
    } else { 
     txtText.setBackgroundColor(Color.WHITE); 
     txtText.setTextColor(Color.BLUE); 
    } 
} 

public boolean isChecked(int position) { 
    return checkedPosition == position; 
} 

public void setChecked(int position) { 
    int prevChecked = checkedPosition; 
    checkedPosition = position; 

    if (prevChecked != -1) { 
     notifyItemChanged(prevChecked); 
    } 
    notifyItemChanged(checkedPosition) 
} 
+0

Благодарности Great Разъяснение. Я также не хочу использовать метод getItemViewType, но всякий раз, когда я его не использовал, представление просмотра Recycler обновляется во время прокрутки, а не в этом примере.Это происходит в другом приложении, в котором я использую макет сетки просмотра ресайклеров. –

Смежные вопросы