一步一步實現Android自訂群組合View
Android自訂View之組合View
Android自訂View之組合View 前序 設計圖UI效果 實現思路 動手實現 繼承LinearLayout實現外部輪廓 定義各種需要的屬性 初始化View 添加一些必要的介面方法 自訂View完成 自訂View的引用 實現
前序
最近在開發一款電商類B端APP,比較忙,現在最新版本要上線了。剛好年底才有時間停下來梳理一下自己寫過的東西,順便分享一些出來,拋磚引玉,還請大家不吝賜教。
設計圖UI效果
我們這裡要介紹的就是後面三塊的UI效果實現。可以看到這幾個塊都是類似的,但是如果要一個一個用布局寫出來,不僅工作量大,而且還會造成XML檔案代碼冗餘、檔案臃腫。顯然,我們可以通過自訂View來實現一個塊的效果,然後在需要的地方include進來就好了,代碼也簡潔好看。
實現思路
最外層布局採用LinearLayout,圖片部分和底部文字部分就可以使用android:layout_weight來控制顯示比例。文字部分也可以使用LinearLayout來布局,設定android:gravity=”center”就好,裡面的TextView就不贅述了。
動手實現繼承LinearLayout實現外部輪廓
先寫好XML布局檔案,調整好要實現的效果。下面是XML代碼:
建立Java代碼檔案RecommendedItem.java繼承LinearLayout,把上面的布局檔案使用LayoutInflater載入進來。
public class RecommendedItem extends LinearLayout { public static final String TAG = RecommendedItem .class.getSimpleName(); private Context mContext; private boolean isDataSet = false; private float titleTextSize, newPriceTextSize, oldPriceTextSize; private RemoteImageView mItemCover; private TextView mItemTitle, mItemNewPrice, mItemOldPrice; private LinearLayout mPriceLayout, mRootLayout; public RecommendedItem (Context context) { super(context); init(context, null); } public RecommendedItem (Context context, AttributeSet attrs) { super(context, attrs); init(context, attrs); } @SuppressLint(NewApi) public RecommendedItem (Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(context, attrs); } private void init(Context context, AttributeSet attrs) { mContext = context; LayoutInflater.from(context).inflate(R.layout.v2_recommended_item, this, true); }}
定義各種需要的屬性
在values檔案夾下建立attrs.xml檔案,添加我們需要的View屬性。
然後我們就可以在XML檔案中引用這些屬性了,在RecommendedItem類的init方法中擷取我們在XML檔案中寫的這些屬性的值。
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RecommendedItem); this.titleTextSize = array.getDimension(R.styleable.RecommendedItem_title_textsize, 15); this.newPriceTextSize = array.getDimension(R.styleable.RecommendedItem_newPrice_textsize, 15);this.oldPriceTextSize = array.getDimension(R.styleable.RecommendedItem_oldPrice_textsize, 12);array.recycle(); // 一定要調用,否則這次的設定會對下次的使用造成影響Log.d(TAG, this.titleTextSize= + this.titleTextSize);Log.d(TAG, this.newPriceTextSize= + this.newPriceTextSize);Log.d(TAG, this.oldPriceTextSize= + this.oldPriceTextSize);
初始化View
@Overrideprotected void onFinishInflate() { super.onFinishInflate(); this.mItemCover = (RemoteImageView) this.findViewById(R.id.recommended_item_front_cover); this.mItemTitle = (TextView) this.findViewById(R.id.recommended_item_title); this.mItemNewPrice = (TextView) this.findViewById(R.id.recommended_item_newprice); this.mItemOldPrice = (TextView) this.findViewById(R.id.recommended_item_oldprice); this.mPriceLayout = (LinearLayout) this.findViewById(R.id.recommended_item_price_layout); this.mRootLayout = (LinearLayout) this.findViewById(R.id.recommended_item_root); this.mItemTitle.setTextSize(this.titleTextSize); this.mItemNewPrice.setTextSize(this.newPriceTextSize); this.mItemOldPrice.setTextSize(this.oldPriceTextSize);}
添加一些必要的介面方法
自訂的View給外部使用提供介面,動態修改它的屬性,實現我們想要的顯示效果。
// 設定點擊事件監聽器public void setOnClickListener(OnClickListener listener) { if(listener != null) { this.mRootLayout.setOnClickListener(listener); }}public void setItemCover(int resId) { this.mItemCover.setImageResource(resId);}public void setItemCover(String url) { this.mItemCover.setImageUrl(url);}public void setItemCover(Bitmap bitmap, boolean need2Recycle) { this.mItemCover.setImageBitmap(bitmap); if(need2Recycle) { if(bitmap != null) { bitmap = null; System.gc(); } }}public void loadItemCover(String remoteUrl) { UILManager.displayImage(remoteUrl, this.mItemCover, UILManager.optionsPicsPreview);}public void setItemTitle(String title) { this.mItemTitle.setText(title);}public String getItemTitle() { if(!TextUtils.isEmpty(this.mItemTitle.getText())) { return this.mItemTitle.getText().toString(); } return null;}public void setItemNewPrice(String newPrice) { this.mItemNewPrice.setText(String.format(mContext.getString(R.string.recommended_item_price_format), newPrice));}public void setItemOldPrice(String oldPrice) { this.mItemOldPrice.setText(String.format(mContext.getString(R.string.recommended_item_price_format), oldPrice)); this.mItemOldPrice.getPaint().setFlags(Paint.STRIKE_THRU_TEXT_FLAG);}public void setPriceLayoutVisible(boolean visible) { if(!visible) { this.mPriceLayout.setVisibility(View.GONE); } else { this.mPriceLayout.setVisibility(View.VISIBLE); }}public boolean isDataSet() { return isDataSet;}public void setDataSet(boolean isDataSet) { this.isDataSet = isDataSet; if(isDataSet && this.mPriceLayout.getVisibility() == View.GONE) this.mPriceLayout.setVisibility(View.VISIBLE);}public void clearView() { this.mItemCover.setImageResource(R.drawable.default_loading); this.mItemTitle.setText(null); this.mPriceLayout.setVisibility(View.GONE);}
自訂View完成
至此,我們根據UI設計圖實現的自訂View就完成,可以方便地在其他任何布局檔案中使用了。
自訂View的引用
實現