首先這并不是多級列表實現(xiàn)的最優(yōu)方式脓钾,多級列表從表現(xiàn)形式上來看無非就是數(shù)據(jù)+縮進(或者顏色,字體大小等)竞帽,通過讀個RecycleView且套可以實現(xiàn)但是如果列表層級過多則會比較累贅,前面說到的縮進等表現(xiàn)形式完全可以在一個RecycleView中來實現(xiàn)具體可以參考以下鏈接
[1]: http://www.reibang.com/p/b76572fb4e60
布局文件
主界面布局
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="rar.uchannel.com.recyclelviewandrecycleview.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</android.support.constraint.ConstraintLayout>
主RecycleView的Item的布局
<?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="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv"
android:layout_width="match_parent"
android:layout_height="30dp"
android:background="@color/colorPrimary"
android:gravity="center" />
<LinearLayout
android:id="@+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView_son"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
子RecycleView的Item的布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/ll_other"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_other"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
這玩意就不多說了,主要講嵌套中會出現(xiàn)的問題
主RecycleView的適配器
public class CustomAdapter extends RecyclerView.Adapter<CustomViewHolder> {
private Context context;
private List<String> data;
CustomAdapter(Context context, List<String> data) {
this.context = context;
this.data = data;
}
@Override
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new CustomViewHolder(LayoutInflater.from(context).inflate(R.layout.item_for_recycleview, parent, false));
}
@Override
public void onBindViewHolder(final CustomViewHolder holder, final int position) {
holder.textView.setText(data.get(position));
if (onItemClickListener != null) {
holder.textView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Log.e("xxx", holder.isRecyclable() + "");
int pos = holder.getLayoutPosition();
onItemClickListener.onItemClick(holder, pos);
holder.setIsRecyclable(false);//view復(fù)用造成一處點擊多處響應(yīng)的問題 設(shè)置為被點擊的item不可以被復(fù)用,
Log.e("xxx", holder.isRecyclable() + "");
}
});
}
}
@Override
public int getItemCount() {
return data.size();
}
void setOnItemClickListener(OnItemClickListener itemClickListener) {
this.onItemClickListener = itemClickListener;
}
private OnItemClickListener onItemClickListener;
interface OnItemClickListener {
void onItemClick(CustomViewHolder holder, int position);
}
}
問題1:點擊RecycleView中的某個Item會出現(xiàn)多個Item響應(yīng)的問題歹袁,可能有規(guī)律。
解決:RecycleView中的點擊事件不要直接在Adapter中實現(xiàn)寝优,通過回調(diào)傳入在外部實現(xiàn)条舔,回調(diào)接口中參數(shù)為ViewHolder是應(yīng)為某些情況下點擊事件有一個控件響應(yīng)之后去修改其他控件的內(nèi)容》Ψ可以修改為對應(yīng)View
問題2:點擊一個RecycleView中的Item展開其次級列表時后面的Item也會復(fù)用當前已經(jīng)展開的Item(這個跟上面有點類似)
解決: 這里解決方案比較多設(shè)置Tag之類的都是可行的孟抗,究其原理無非是展開的Item不進行復(fù)用迁杨,這里采用的方式是直接設(shè)置Item不可復(fù)用holder.setIsRecyclable(false);
這里僅僅對單個已經(jīng)點擊的item有效,而且當該item畫出屏幕外再次滑動回到屏幕內(nèi)時其復(fù)用狀態(tài)會重新更新為可以復(fù)用凄硼,可以看到代碼中的兩個Log铅协,當Item出現(xiàn)在屏幕內(nèi)首次點擊之前該Item都是可以復(fù)用的,對性能影響較小摊沉。
這里滑動沖突不需要進行處理警医,應(yīng)為RecycleView布局使用的是
android:layout_height="wrap_content"
如果各位在且套的時候要求內(nèi)部子RecycleView長度固定且可以滑動就需要通過setScrollEnabled
處理滑動沖突,(額坯钦,直說吧這里我根本沒嘗試...)
MainActivity代碼
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
List<String> getData() {
ArrayList<String> strings = new ArrayList<>();
for (int i = 0; i < 100; i++) {
strings.add("i=" + i);
}
return strings;
}
List<String> getData2Inner() {
ArrayList<String> strings = new ArrayList<>();
for (int i = 0; i < 5; i++) {
strings.add("i=" + i);
}
return strings;
}
void initView() {
RecyclerView recyclerView = findViewById(R.id.recycleView);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
final CustomAdapter adapter = new CustomAdapter(this, getData());
adapter.setOnItemClickListener(new CustomAdapter.OnItemClickListener() {
@Override
public void onItemClick(CustomViewHolder holder, int position) {
LinearLayoutManager llm = new LinearLayoutManager(MainActivity.this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
InnerAdapter innerAdapter = new InnerAdapter(MainActivity.this, getData2Inner());
holder.recyclerView.setLayoutManager(llm);
holder.recyclerView.setAdapter(innerAdapter);
ViewGroup.LayoutParams layoutParams = holder.linearLayout.getLayoutParams();
layoutParams.height = 0;
holder.linearLayout.setLayoutParams(layoutParams);
startAnimation(holder.linearLayout);
}
});
recyclerView.setAdapter(adapter);
recyclerView.setLayoutManager(linearLayoutManager);
}
public void startAnimation(final View view) {
ValueAnimator animator;
if (view.getHeight() == 0) {
animator = ValueAnimator.ofInt(0, getMeasureHeight(view));
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = (int) animation.getAnimatedValue();
view.setLayoutParams(layoutParams);
}
});
} else {//if (view.getHeight() == getMeasureHeight(view))
animator = ValueAnimator.ofInt(view.getHeight(), 0);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.height = (int) animation.getAnimatedValue();
view.setLayoutParams(layoutParams);
}
});
}
animator.setDuration(1000);
animator.start();
}
/**
* 測量控件的顯示的時候的真實高度
*
* @param view target view
* @return target view real height
*/
public int getMeasureHeight(View view) {
int w = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
int h = View.MeasureSpec.makeMeasureSpec(0,
View.MeasureSpec.UNSPECIFIED);
view.measure(w, h);
return view.getMeasuredHeight();
}
}
其他ViewHolder和子Adapter就不貼了预皇,沒有什么需要注意的地方改怎么寫就怎么寫