編輯:關於android開發
Android開發中經常需要使用Adapter。
傳統方法是自定義一個Adapter並繼承AndroidSDK內的BaseAdapter,
這種方式代碼量大,耦合度高,靈活性差(各種監聽事件需要對View單獨寫,或者自定義一個比較統一的方法);
而ZBLibrary中的BaseViewAdapter不僅預處理了通用方法(getCount,getItem等) 以及 Item復用邏輯,
而且將對Item的處理代碼單獨寫在一個BaseView(提供了大量常用方法)的子類,
所以使用繼承BaseViewAdapter的新方式能大幅精簡代碼,並且帶來高靈活性和低耦合度。
比如這個界面
傳統方式實現的CommonAdapter代碼如下
1 package com.example.quickadapter; 2 3 import java.util.ArrayList; 4 import java.util.List; 5 6 import zuo.biao.library.ui.WebViewActivity; 7 import zuo.biao.library.util.ImageLoaderUtil; 8 import android.app.Activity; 9 import android.view.LayoutInflater; 10 import android.view.View; 11 import android.view.View.OnClickListener; 12 import android.view.ViewGroup; 13 import android.widget.BaseAdapter; 14 import android.widget.ImageView; 15 import android.widget.TextView; 16 17 public class CommonAdapter extends BaseAdapter { 18 19 private Activity context; 20 private List<User> list; 21 private LayoutInflater inflater; 22 public CommonAdapter(Activity context, List<User> list) { 23 this.context = context; 24 this.list = new ArrayList<>(list); 25 this.inflater = context.getLayoutInflater(); 26 } 27 28 @Override 29 public int getCount() { 30 return list.size(); 31 } 32 33 @Override 34 public User getItem(int position) { 35 return list.get(position); 36 } 37 38 @Override 39 public long getItemId(int position) { 40 return position; 41 } 42 43 public synchronized void refresh(List<User> list) { 44 if (list != null && list.size() > 0) { 45 this.list = new ArrayList<>(list); 46 } 47 notifyDataSetChanged(); 48 } 49 50 @Override 51 public View getView(final int position, View convertView, ViewGroup parent) { 52 ViewHolder holder = convertView == null ? null : (ViewHolder) convertView.getTag(); 53 if (holder == null) { 54 convertView = inflater.inflate(R.layout.user_item, parent, false); 55 holder = new ViewHolder(); 56 57 holder.ivUserItemHead = (ImageView) convertView.findViewById(R.id.ivUserItemHead); 58 holder.ivUserItemStar = (ImageView) convertView.findViewById(R.id.ivUserItemStar); 59 60 holder.tvUserItemSex = (TextView) convertView.findViewById(R.id.tvUserItemSex); 61 62 holder.tvUserItemName = (TextView) convertView.findViewById(R.id.tvUserItemName); 63 holder.tvUserItemId = (TextView) convertView.findViewById(R.id.tvUserItemId); 64 holder.tvUserItemNumber = (TextView) convertView.findViewById(R.id.tvUserItemNumber); 65 66 convertView.setTag(holder); 67 } 68 69 final User user = getItem(position); 70 71 ImageLoaderUtil.loadImage(holder.ivUserItemHead, user.getHead(), ImageLoaderUtil.TYPE_OVAL); 72 holder.ivUserItemStar.setImageResource(user.getStarred() ? R.drawable.star_light : R.drawable.star); 73 74 holder.tvUserItemSex.setBackgroundResource(user.getSex() == User.SEX_FEMAIL ? R.drawable.circle_pink : R.drawable.circle_blue); 75 holder.tvUserItemSex.setText(user.getSex() == User.SEX_FEMAIL ? "女" : "男"); 76 holder.tvUserItemSex.setTextColor(context.getResources().getColor(user.getSex() == User.SEX_FEMAIL ? R.color.pink : R.color.blue)); 77 78 holder.tvUserItemName.setText("" + user.getName()); 79 holder.tvUserItemId.setText("ID:" + user.getId()); 80 holder.tvUserItemNumber.setText("Phone:" + user.getPhone()); 81 82 holder.ivUserItemHead.setOnClickListener(new OnClickListener() { 83 84 @Override 85 public void onClick(View v) { 86 context.startActivity(WebViewActivity.createIntent(context, user.getName(), user.getHead())); 87 } 88 }); 89 90 holder.ivUserItemStar.setOnClickListener(new OnClickListener() { 91 92 @Override 93 public void onClick(View v) { 94 user.setStarred(! user.getStarred()); 95 list.set(position, user); 96 refresh(null); 97 } 98 }); 99 100 holder.tvUserItemSex.setOnClickListener(new OnClickListener() { 101 102 @Override 103 public void onClick(View v) { 104 user.setSex(user.getSex() == User.SEX_FEMAIL ? User.SEX_MAIL : User.SEX_FEMAIL); 105 list.set(position, user); 106 refresh(null); 107 } 108 }); 109 110 return convertView; 111 } 112 113 class ViewHolder { 114 public ImageView ivUserItemHead; 115 public ImageView ivUserItemStar; 116 117 public TextView tvUserItemSex; 118 119 public TextView tvUserItemName; 120 public TextView tvUserItemId; 121 public TextView tvUserItemNumber; 122 } 123 }
繼承BaseViewAdapter的新方式實現的QuickAdapter代碼如下
1 package com.example.quickadapter; 2 3 import java.util.List; 4 5 import zuo.biao.library.base.BaseView; 6 import zuo.biao.library.base.BaseViewAdapter; 7 import zuo.biao.library.ui.WebViewActivity; 8 import zuo.biao.library.util.ImageLoaderUtil; 9 import zuo.biao.library.util.StringUtil; 10 import android.annotation.SuppressLint; 11 import android.app.Activity; 12 import android.content.res.Resources; 13 import android.view.LayoutInflater; 14 import android.view.View; 15 import android.view.View.OnClickListener; 16 import android.view.ViewGroup; 17 import android.widget.ImageView; 18 import android.widget.TextView; 19 20 import com.example.quickadapter.QuickAdapter.UserView; 21 22 public class QuickAdapter extends BaseViewAdapter<User, UserView> { 23 24 public QuickAdapter(Activity context, List<User> list) { 25 super(context, list); 26 } 27 28 @Override 29 public UserView createView(int position, View convertView, ViewGroup parent) { 30 return new UserView(context, resources); 31 } 32 33 public class UserView extends BaseView<User> implements OnClickListener { 34 public UserView(Activity context, Resources resources) { 35 super(context, resources); 36 } 37 38 public ImageView ivUserViewHead; 39 public ImageView ivUserViewStar; 40 41 public TextView tvUserViewSex; 42 43 public TextView tvUserViewName; 44 public TextView tvUserViewId; 45 public TextView tvUserViewNumber; 46 @SuppressLint("InflateParams") 47 @Override 48 public View createView(LayoutInflater inflater) { 49 convertView = inflater.inflate(R.layout.user_view, null); 50 51 ivUserViewHead = findViewById(R.id.ivUserViewHead, this); 52 ivUserViewStar = findViewById(R.id.ivUserViewStar, this); 53 54 tvUserViewSex = findViewById(R.id.tvUserViewSex, this); 55 56 tvUserViewName = findViewById(R.id.tvUserViewName); 57 tvUserViewId = findViewById(R.id.tvUserViewId); 58 tvUserViewNumber = findViewById(R.id.tvUserViewNumber); 59 60 return convertView; 61 } 62 63 @Override 64 public void setView(User data){ 65 if (data == null) { 66 return; 67 } 68 this.data = data; 69 70 ImageLoaderUtil.loadImage(ivUserViewHead, data.getHead(), ImageLoaderUtil.TYPE_OVAL); 71 ivUserViewStar.setImageResource(data.getStarred() ? R.drawable.star_light : R.drawable.star); 72 73 tvUserViewSex.setBackgroundResource(data.getSex() == User.SEX_FEMAIL ? R.drawable.circle_pink : R.drawable.circle_blue); 74 tvUserViewSex.setText(data.getSex() == User.SEX_FEMAIL ? "女" : "男"); 75 tvUserViewSex.setTextColor(getColor(data.getSex() == User.SEX_FEMAIL ? R.color.pink : R.color.blue)); 76 77 tvUserViewName.setText(StringUtil.getTrimedString(data.getName())); 78 tvUserViewId.setText("ID:" + data.getId()); 79 tvUserViewNumber.setText("Phone:" + StringUtil.getNoBlankString(data.getPhone())); 80 } 81 82 @Override 83 public void onClick(View v) { 84 if (data == null) { 85 return; 86 } 87 switch (v.getId()) { 88 case R.id.ivUserViewHead: 89 toActivity(WebViewActivity.createIntent(context, data.getName(), data.getHead())); 90 break; 91 case R.id.ivUserViewStar: 92 data.setStarred(! data.getStarred()); 93 setView(data); 94 break; 95 case R.id.tvUserViewSex: 96 data.setSex(data.getSex() == User.SEX_FEMAIL ? User.SEX_MAIL : User.SEX_FEMAIL); 97 setView(data); 98 break; 99 default: 100 break; 101 } 102 } 103 } 104 }
看下ZBLibrary中的BaseView,裡面有大量常用的 且 AndroidSDK內的BaseAdapter沒有提供的 方法。
package zuo.biao.library.base; import zuo.biao.library.util.CommonUtil; import zuo.biao.library.util.Log; import android.app.Activity; import android.content.Intent; import android.content.res.Resources; import android.graphics.drawable.Drawable; import android.support.annotation.NonNull; import android.view.LayoutInflater; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnLongClickListener; import android.view.View.OnTouchListener; /**基礎自定義View * @author Lemon * @param <T> 數據模型(model/JavaBean)類 * @see #onDestroy * @use extends BaseView<T>, 具體參考.DemoView */ public abstract class BaseView<T> { private static final String TAG = "BaseView"; /** * 傳入的Activity,可在子類直接使用 */ protected Activity context; protected Resources resources; public BaseView(Activity context, Resources resources) { this.context = context; this.resources = resources == null ? context.getResources() : resources; } /**數據改變回調接口 * (Object) getData() - 改變的數據 */ public interface OnDataChangedListener { void onDataChanged(); } public OnDataChangedListener onDataChangedListener;//數據改變回調監聽類的實例 /**設置數據改變事件監聽類 * @param l */ public void setOnDataChangedListener(OnDataChangedListener l) { onDataChangedListener = l; } public OnTouchListener onTouchListener;//接觸View回調監聽類的實例 /**設置接觸View事件監聽類 * @param l */ public void setOnTouchListener(OnTouchListener l) { onTouchListener = l; } public OnClickListener onClickListener;//點擊View回調監聽類的實例 /**設置點擊View事件監聽類 * @param l */ public void setOnClickListener(OnClickListener l) { onClickListener = l; } public OnLongClickListener onLongClickListener;//長按View回調監聽類的實例 /**設置長按View事件監聽類 * @param l */ public void setOnLongClickListener(OnLongClickListener l) { onLongClickListener = l; } /** * 子類整個視圖,可在子類直接使用 * @must createView方法內對其賦值且不能為null */ protected View convertView = null; /**通過id查找並獲取控件,使用時不需要強轉 * @param id * @return */ @SuppressWarnings("unchecked") public <V extends View> V findViewById(int id) { return (V) convertView.findViewById(id); } /**通過id查找並獲取控件,並setOnClickListener * @param id * @param l * @return */ public <V extends View> V findViewById(int id, OnClickListener l) { V v = findViewById(id); v.setOnClickListener(l); return v; } /**創建一個新的View * @return */ public abstract View createView(@NonNull LayoutInflater inflater); /**獲取convertView的寬度 * @warn 只能在createView後使用 * @return */ public int getWidth() { return convertView.getWidth(); } /**獲取convertView的高度 * @warn 只能在createView後使用 * @return */ public int getHeight() { return convertView.getHeight(); } /** * data在列表中的位置 * @must 只使用setView(int position, T data)方法來設置position,保證position與data對應正確 */ protected int position = 0; /**獲取data在列表中的位置 */ public int getPosition() { return position; } protected T data = null; /**獲取數據 * @return */ public T getData() { return data; } /**設置並顯示內容 * @warn 只能在createView後使用 * @param position - data在列表中的位置 * @param data - 傳入的數據 */ public void setView(int position, T data) { this.position = position; setView(data); } /**設置並顯示內容 * @warn 只能在createView後使用 * @param data - 傳入的數據 */ public abstract void setView(T data); /**獲取可見性 * @warn 只能在createView後使用 * @return 可見性 (View.VISIBLE, View.GONE, View.INVISIBLE); */ public int getVisibility() { return convertView.getVisibility(); } /**設置可見性 * @warn 只能在createView後使用 * @param visibility - 可見性 (View.VISIBLE, View.GONE, View.INVISIBLE); */ public void setVisibility(int visibility) { convertView.setVisibility(visibility); } /**設置背景 * @warn 只能在createView後使用 * @param resId */ public void setBackground(int resId) { if (resId > 0 && convertView != null) { try { convertView.setBackgroundResource(resId); } catch (Exception e) { Log.e(TAG, "setBackground try { convertView.setBackgroundResource(resId);" + " \n >> } catch (Exception e) { \n" + e.getMessage()); } } } //resources方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< public String getString(int id) { return resources.getString(id); } public int getColor(int id) { return resources.getColor(id); } public Drawable getDrawable(int id) { return resources.getDrawable(id); } public float getDimension(int id) { return resources.getDimension(id); } //resources方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //show short toast 方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< /**快捷顯示short toast方法,需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以這個類裡不寫 * @param stringResId */ public void showShortToast(int stringResId) { CommonUtil.showShortToast(context, stringResId); } /**快捷顯示short toast方法,需要long toast就用 Toast.makeText(string, Toast.LENGTH_LONG).show(); ---不常用所以這個類裡不寫 * @param string */ public void showShortToast(String string) { CommonUtil.showShortToast(context, string); } //show short toast 方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //啟動新Activity方法<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< /**打開新的Activity,向左滑入效果 * @param intent */ public void toActivity(final Intent intent) { CommonUtil.toActivity(context, intent); } /**打開新的Activity * @param intent * @param showAnimation */ public void toActivity(final Intent intent, final boolean showAnimation) { CommonUtil.toActivity(context, intent, showAnimation); } /**打開新的Activity,向左滑入效果 * @param intent * @param requestCode */ public void toActivity(final Intent intent, final int requestCode) { CommonUtil.toActivity(context, intent, requestCode); } /**打開新的Activity * @param intent * @param requestCode * @param showAnimation */ public void toActivity(final Intent intent, final int requestCode, final boolean showAnimation) { CommonUtil.toActivity(context, intent, requestCode, showAnimation); } //啟動新Activity方法>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> /**銷毀並回收內存,建議在對應的View占用大量內存時使用 * @warn 只能在UI線程中調用 */ public void onDestroy() { if (convertView != null) { try { convertView.destroyDrawingCache(); } catch (Exception e) { Log.w(TAG, "onDestroy try { convertView.destroyDrawingCache();" + " >> } catch (Exception e) {\n" + e.getMessage()); } convertView = null; } onDataChangedListener = null; onTouchListener = null; onClickListener = null; onLongClickListener = null; data = null; position = 0; context = null; } }
本示例工程QuickAdapter
下載地址
http://files.cnblogs.com/files/tommylemon/QuickAdapter.zip
下載試用
QuickAdapter.apk
用到的開源庫ZBLibrary(歡迎Star,歡迎Fork)
下載地址
https://github.com/TommyLemon/Android-ZBLibrary
下載試用
ZBLibraryDemoApp.apk
實現Android K的假裝沉浸式,android假裝沉浸在Android 5.0之後引入了MD風格,並且狀態欄沉浸也成為了一種設計習慣。而停留在之Android L之前
使用ViewPager切換Fragment時,防止頻繁調用OnCreatView,fragmentoncreat使用ViewPager切換Fragment,我原先使用系統
上一節講到了Gallery畫廊,本節主要講解Android組件Service,
android TextView實現跑馬燈效果 最近忙著項目,很久沒有總結提交博客和提交github了。接下來我打算整理下項目中用到的比較有用的發表到博客上。也打算總