效果圖
上面咱們已經實現了滑動的效果,今天來實現數據的添加;效果如下:
這裏學習一下 listview 或 Recyclerview 的數據封裝,我們也整蠱一下 adapter;
考慮到,頂部 tab 可能要有未讀消息,或者不同的控件,所以 layoutId 肯定是要有的,datas 數據肯定也是,且這個 data 類型用泛型修飾;
所以,大致可以這麼寫:
/**
* @author by zhengshaorui on 2019/10/8
* Describe: 數據構建基類
*/
public abstract class TabAdapter<T> {
private int mLayoutId;
private List<T> mDatas;
public TabAdapter(int layoutId, List<T> data) {
mLayoutId = layoutId;
mDatas = data;
}
/**
* 獲取個數
* @return
*/
int getItemCount(){
return mDatas == null ? 0 : mDatas.size();
}
/**
* 獲取id
* @return
*/
int getLayoutId(){
return mLayoutId;
}
/**
* 獲取數據
* @return
*/
List<T> getDatas(){
return mDatas;
}
/**
* 公佈給外部的數據
* @param view
* @param data
* @param position
*/
public abstract void bindView(View view,T data,int position);
/**
* 單擊
* @param view
* @param position
*/
public void onItemClick(View view,T data,int position){}
/**
* 通知數據改變
*/
public void notifyDataChanged(){
if (mListener != null) {
mListener.notifyDataChanged();
}
}
/**
* 構建一個listener,用來改變數據
*/
public AdapterListener mListener;
void setListener(AdapterListener listener){
mListener = listener;
}
/**
* 常用模板
*/
public TabAdapter setText(View view,int viewId,int resId){
TextView textView = view.findViewById(viewId);
if (textView != null) {
textView.setText(resId);
}
return this;
}
public TabAdapter setText(View view,int viewId,String msg){
TextView textView = view.findViewById(viewId);
if (textView != null) {
textView.setText(msg);
}
return this;
}
}
同樣,配置完 adapter ,那麼肯定要有個入口去設置 adapter ,沒錯,這次我們又新建一個類: TabFlowLayout 用來實現數據的配置和一部分UI的繪製;
首先是 setAdapter 方法了:
/**
* 添加adapter,
* @param adapter
*/
public void setAdapter(TabAdapter adapter){
mAdapter = adapter;
mAdapter.setListener(this);
//實現數據更新
notifyDataChanged();
}
setAdapter 非常簡單,就是配置監聽,然後拿到 view 之後,addview 進去即可:
@Override
public void notifyDataChanged() {
removeAllViews();
TabAdapter adapter = mAdapter;
int itemCount = adapter.getItemCount();
for (int i = 0; i < itemCount; i++) {
View view = LayoutInflater.from(getContext()).inflate(adapter.getLayoutId(),this,false);
adapter.bindView(view,adapter.getDatas().get(i),i);
configClick(view,i);
addView(view);
}
}
private void configClick(final View view, final int i) {
view.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mAdapter.onItemClick(view,mAdapter.getDatas().get(i),i);
}
});
}
當然,在 configClick 這裏,還可以添加更多的操作,比如子控件的點擊事件;view 的select 狀態,從而實現選擇效果或者點擊效果;這個可以根據自己需求去實現。
這樣,在Activity 的配置也會變得特別簡單:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_tab);
TabFlowLayout tabFlowLayout = findViewById(R.id.tabflow);
mAdapter = new TabFlowAdapter(R.layout.item_tab_text, mTitle);
tabFlowLayout.setAdapter(mAdapter);
}
public void update(View view) {
mTitle.clear();
ArrayList<String> strings = new ArrayList<>(Arrays.asList("Life is like an ocean. Only strong willed people can reach the other side".split(" ")));
mTitle.addAll(strings);
Log.d(TAG, "zsr - update: "+mTitle.size());
mAdapter.notifyDataChanged();
}
class TabFlowAdapter extends TabAdapter<String>{
public TabFlowAdapter(int layoutId, List<String> data) {
super(layoutId, data);
}
@Override
public void bindView(View view, String data, int position) {
setText(view,R.id.item_text,data);
}
@Override
public void onItemClick(View view,String data,int position) {
super.onItemClick(view,data,position);
Toast.makeText(TabActivity.this, data, Toast.LENGTH_SHORT).show();
}
}
這樣,只需要繼承 TabAdapter 就可以像 listview 或者 recyclerview 這樣的數據配置方式了;
下一章,我們將學習與 viewpager 結合,實現多種效果