工作小記~~~使用LinearLayout實現仿ListView(解決巢狀ListView顯示不全)
阿新 • • 發佈:2019-02-05
使用LinearLayout實現仿ListView(解決巢狀ListView顯示不全)
滑動控制元件巢狀ListView時就會出現ListView中的資料顯示不全的現象,這時我們就會想到巢狀NoScrollListView去實現。功能是可以實現但是在列表中使用NoScrollListView的話會出現滑動卡頓的現象。 因為NoScrollListView是在顯示前計算好高度顯示的,所以如果在顯示前隱藏了控制元件顯示後再去顯示該控制元件就會造成內容顯示不全。我們可以自定義的LinearLayout做一個仿ListView的控制元件。既然是仿ListView那我們除了自定義控制元件之外,我們還需要自定義一個Adapter。
- 自定義LinearLayout程式碼
public class CustomNoScrollListView extends LinearLayout {
private CustomAdapter mAdapter;
public CustomNoScrollListView(Context context) {
super(context);
setOrientation(LinearLayout.VERTICAL);
}
public CustomNoScrollListView(Context context, AttributeSet attrs) {
super (context, attrs);
setOrientation(LinearLayout.VERTICAL);
}
public CustomNoScrollListView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
setOrientation(LinearLayout.VERTICAL);
}
public void setAdapter(CustomAdapter adapter) {
if (adapter == null) {
throw new NullPointerException("CustomAdapter is null, please check setAdapter(CustomAdapter adapter)...");
}
mAdapter = adapter;
adapter.setOnNotifyDataSetChangedListener(new CustomAdapter.OnNotifyDataSetChangedListener() {
@Override
public void OnNotifyDataSetChanged() {
notifyDataSetChanged();
}
});
adapter.notifyDataSetChanged();
}
public CustomAdapter getAdapter() {
return mAdapter;
}
private void notifyDataSetChanged() {
removeAllViews();
if (mAdapter == null || mAdapter.getCount() == 0) {
return;
}
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
for (int i = 0; i < mAdapter.getCount(); i++) {
final int index = i;
View view = mAdapter.getView(index);
if (view == null) {
throw new NullPointerException("item layout is null, please check getView()...");
}
addView(view, index, layoutParams);
}
}
}
- 自定義Adapter程式碼(像普通的listView一樣,繼承下面的adapter新增自己的佈局及邏輯即可)
public abstract class CustomAdapter {
public abstract int getCount();
public abstract Object getItem(int i);
public abstract long getItemId(int i);
public abstract View getView(int i);
public void notifyDataSetChanged(){
if(null != mOnNotifyDataSetChangedListener){
mOnNotifyDataSetChangedListener.OnNotifyDataSetChanged();
}
}
/**
* 釋放一個介面 串聯adapter與view中間的資料重新整理
*/
public interface OnNotifyDataSetChangedListener{
void OnNotifyDataSetChanged();
}
private OnNotifyDataSetChangedListener mOnNotifyDataSetChangedListener;
public void setOnNotifyDataSetChangedListener(OnNotifyDataSetChangedListener listener){
mOnNotifyDataSetChangedListener = listener;
}
}
其實可以把Adapter的程式碼定義到View中,分開定義是為了替換ListView或NoScrollListView時方便。
使用方法與ListView一樣直接呼叫setAdapter()設定自定義的介面卡,重新整理資料使用adapter的notifyDataSetChanged()方法