前言
近期從一個小公司辭職了见坑,決定復習下之前學習過的內(nèi)容嚷掠。所以發(fā)布一篇自定義控件的文章,加深自己的印象荞驴,也同時為以后再找工作做準備不皆。廢話不多說,現(xiàn)在開始熊楼。
自定義控件介紹
Android當中自定義控件的開發(fā)霹娄,Android中所有的控件都是繼承View類。以下圖片是各控件繼承關(guān)系圖
其實所謂的自定義控件其實就是繼承View類鲫骗,并且重寫里面的內(nèi)部方法犬耻。通常來說,自定義控件有三種方式:
1.自定義View: 繼承View执泰。
2.基于現(xiàn)有的組件:繼承View的派生類枕磁。
3.組合的方式:自定義控件中包含其他組件。
今天呢术吝,我們就來介紹一下組合的方式實現(xiàn)自定義View计济,其他兩種方式等待小編再學習學習之后再發(fā)表。
實踐
說再多的理論不如實踐來得實在排苍,一下是從網(wǎng)上下載的一張設計圖沦寂。
分析
如果我們要實現(xiàn)這種界面,看起來是挺簡單的淘衙,也不用怎么自定義传藏,但是相對于有部分人想偷懶的人來說(為了長遠方便發(fā)展)。還是自定義一下好一點,這樣毯侦,當我們再別的布局文件中還需要用到的話西壮,直接當控件使用就好。是不是很方便叫惊??
其實說白了呢做修,就是把下圖自定義成一個控件霍狰,之后用到的時候直接當控件使用就好。
實現(xiàn)的思路其實也挺簡單饰及,自定義一個組合的View蔗坯,線性布局橫向包裹,依次排列ImageView燎含、TextView宾濒、TextView、ImageView屏箍。廢話不多說绘梦,看下如何實現(xiàn)吧。
1.定義自定義控件布局(custom_item_view)
<?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">
<!-- 線性布局水平對齊包裹-->
<LinearLayout
android:id="@+id/setting_item"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#ffffff"
android:padding="5dp"
android:orientation="horizontal">
<!-- 自定義控件中第一個圖片-->
<ImageView
android:id="@+id/setting_item_logo"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
<!-- 自定義控件中標題-->
<TextView
android:id="@+id/setting_item_title"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="5dp"
android:gravity="center"
android:textColor="#000000"
android:textSize="18sp"/>
<!-- 為了實現(xiàn)赴魁,用一個TextView將后邊的控件顯示在右邊
也可以用RelativeLayout實現(xiàn)-->
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"/>
<!-- 自定義控件中概述-->
<TextView
android:id="@+id/setting_item_desc"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginRight="5dp"
android:gravity="center"
android:textColor="#999999"
android:textSize="15sp"/>
<!-- 自定義控件中第二個圖片-->
<ImageView
android:id="@+id/setting_item_more"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="5dp"/>
</LinearLayout>
<!-- 自定義控件中下劃線-->
<View
android:id="@+id/setting_item_line"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:background="#888888"/>
</LinearLayout>
2.新建一個attrs.XML文件設置自定義控件屬性
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomSettingItemView">
<!-- Item標題-->
<attr name="settingItemTitle" format="string"/>
<!-- Item描述-->
<attr name="settingItemDesc" format="string"/>
<!-- 第一張圖片-->
<attr name="settingLogoSrc" format="reference"/>
<!-- 第二張圖片-->
<attr name="settingMoreSrc" format="reference"/>
<!-- 下劃線顯示與否-->
<attr name="settingItemUnderLineVisibility" format="boolean"/>
</declare-styleable>
</resources>
3.繼承FrameLayout卸奉,復寫構(gòu)造函數(shù)
讀取布局文件中的屬性參數(shù)(見init方法):
如果在布局中傳入了自定義的參數(shù),可以在構(gòu)造函數(shù)中從AttributeSet讀取并設置給控件颖御。
package com.example.customview_setting_item.customView;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.example.customview_setting_item.R;
/**
* Create by 25497 on 2019/10/6
* The project name is CustomView-setting_item
* Leo Mark
*
* Desc: 自定義控件(繼承FrameLayout)
**/
public class CustomSettingItemView extends FrameLayout {
private Context mContext;
private View mainView;
private LinearLayout settingItem;
private ImageView settingItemLogo;//第一張圖片
private ImageView settingItemMore;//第二張圖片
private TextView settingItemTitle;//標題
private TextView settingItemDesc;//概述
private View settingItemUnderLine;//下劃線
private String settingItemTitleText;//標題內(nèi)容
private String settingItemDescText;//概述內(nèi)容
private int settingItemLogoSrc;//第一張圖片路徑
private int settingItemMoreSrc;//第二張圖片路徑
private boolean settingItemLineVisibility;//下劃線顯示與否判斷
public String getSettingItemTitleText() {
return settingItemTitleText;
}
public void setSettingItemTitleText(String settingItemTitleText) {
if (settingItemTitleText!=null){
this.settingItemTitleText = settingItemTitleText;
settingItemTitle.setText(settingItemTitleText);//將內(nèi)容設置進控件中
}
}
public String getSettingItemDescText() {
return settingItemDescText;
}
public void setSettingItemDescText(String settingItemDescText) {
if (settingItemDescText!=null) {
this.settingItemDescText = settingItemDescText;
settingItemDesc.setText(settingItemDescText);//將內(nèi)容設置進控件中
}
}
public int getSettingItemLogoSrc() {
return settingItemLogoSrc;
}
public void setSettingItemLogoSrc(int settingItemLogoSrc) {
if (settingItemLogoSrc!=10000) {
this.settingItemLogoSrc = settingItemLogoSrc;
settingItemLogo.setImageResource(settingItemLogoSrc);//將圖片地址設置進控件中
}
}
public int getSettingItemMoreSrc() {
return settingItemMoreSrc;
}
public void setSettingItemMoreSrc(int settingItemMoreSrc) {
if (settingItemMoreSrc!=10000) {
this.settingItemMoreSrc = settingItemMoreSrc;
settingItemMore.setImageResource(settingItemMoreSrc);//將圖片地址設置進控件中
}
}
public boolean getSettingItemLineVisibility() {
return settingItemLineVisibility;
}
public void setSettingItemLineSize(boolean settingItemLineVisibility) {
this.settingItemLineVisibility = settingItemLineVisibility;
//判斷是否顯示下劃線
if (settingItemLineVisibility){
settingItemUnderLine.setVisibility(VISIBLE);
}else{
settingItemUnderLine.setVisibility(INVISIBLE);
}
}
public CustomSettingItemView(@NonNull Context context) {
super(context);
}
public CustomSettingItemView(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
init(context,attrs);
}
public CustomSettingItemView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context,attrs);
}
public CustomSettingItemView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init(context,attrs);
}
/**
* 定義自定義控件中的屬性
* @param context
* @param attrs
*/
private void init(Context context, AttributeSet attrs) {
this.mContext=context;
LayoutInflater inflater= (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
mainView=inflater.inflate(R.layout.custom_setting_item_view,this,true);
initView(mainView);//初始布局中的控件
TypedArray typedArray=mContext.obtainStyledAttributes(attrs, R.styleable.CustomSettingItemView);
setSettingItemTitleText(typedArray.getString(R.styleable.CustomSettingItemView_settingItemTitle));
setSettingItemDescText(typedArray.getString(R.styleable.CustomSettingItemView_settingItemDesc));
setSettingItemLogoSrc(typedArray.getResourceId(R.styleable.CustomSettingItemView_settingLogoSrc,10000));
setSettingItemMoreSrc(typedArray.getResourceId(R.styleable.CustomSettingItemView_settingMoreSrc,10000));
setSettingItemLineSize(typedArray.getBoolean(R.styleable.CustomSettingItemView_settingItemUnderLineVisibility,true));
}
/**
* 初始化控件
* @param mainView
*/
private void initView(View mainView) {
settingItemTitle=mainView.findViewById(R.id.setting_item_title);
settingItemDesc=mainView.findViewById(R.id.setting_item_desc);
settingItemLogo=mainView.findViewById(R.id.setting_item_logo);
settingItemMore=mainView.findViewById(R.id.setting_item_more);
settingItemUnderLine=mainView.findViewById(R.id.setting_item_line);
}
}
4.修改主函數(shù)布局文件
創(chuàng)建主函數(shù)入口MainActivity,布局文件中榄棵,把剛剛自定義的當控件使用就好,也可代碼中動態(tài)設置潘拱,我這里就隨便找了之前使用過的圖片來展示疹鳄。
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical">
<com.example.customview_setting_item.customView.CustomSettingItemView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:settingItemTitle="測試標題1"
app:settingItemDesc="測試詳情1"
app:settingLogoSrc="@mipmap/soufa"
app:settingMoreSrc="@mipmap/more"/>
<com.example.customview_setting_item.customView.CustomSettingItemView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:settingItemTitle="測試標題2"
app:settingLogoSrc="@mipmap/soufa"
app:settingMoreSrc="@mipmap/more"/>
<com.example.customview_setting_item.customView.CustomSettingItemView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:settingItemTitle="測試標題3"
app:settingItemDesc="測試詳情3"
app:settingLogoSrc="@mipmap/soufa"
app:settingMoreSrc="@mipmap/more"/>
<com.example.customview_setting_item.customView.CustomSettingItemView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:settingItemTitle="測試標題4"
app:settingItemDesc="測試詳情4"
app:settingLogoSrc="@mipmap/soufa"
app:settingMoreSrc="@mipmap/more"
app:settingItemUnderLineVisibility="false"/>
<com.example.customview_setting_item.customView.CustomSettingItemView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:settingItemTitle="測試標題5"
app:settingItemDesc="測試詳情5"
app:settingLogoSrc="@mipmap/soufa"
app:settingMoreSrc="@mipmap/more"/>
<com.example.customview_setting_item.customView.CustomSettingItemView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:settingItemTitle="測試標題6"
app:settingItemDesc="測試詳情6"
app:settingLogoSrc="@mipmap/soufa"/>
<com.example.customview_setting_item.customView.CustomSettingItemView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:settingItemTitle="測試標題7"
app:settingItemDesc="測試詳情7"
app:settingLogoSrc="@mipmap/soufa"
app:settingMoreSrc="@mipmap/more"/>
</LinearLayout>
運行在虛擬機之后的效果圖
總結(jié)
以上是自定義控件的組合實現(xiàn),在實際開發(fā)中芦岂,肯定不是那么簡單瘪弓,但是萬變不離其中,只要我們懂思路方法盔腔,就不用管項目經(jīng)理啥子無理需求了杠茬。當然,這也只是簡單實現(xiàn)弛随,如果想要實現(xiàn)更多的效果瓢喉。可以通過前面寫的第一種自定義View,繼承View舀透、重寫組件的onMeasure栓票、onLayout、onDraw來實現(xiàn)。
好了走贪,關(guān)于自定義View的其中一種方式就是這樣子了佛猛,如果有錯誤,期待您批評改正坠狡。碼字不易继找,望您收藏、轉(zhuǎn)發(fā)逃沿、點贊婴渡。