Android開發(fā)小知識3—自定義View

前言

當android系統(tǒng)的UI不能滿足我們的設計或需求時术瓮,我們就需要自定義view來實現(xiàn)我們的目的雕擂,今天打算總結一下自定義view的幾種常見方式。在此之前产徊,學習了http://www.cnblogs.com/jiayongji/p/5560806.html 昂勒。受益良多,本文有參考其中的內(nèi)容舟铜。

三種方式

自定義控件的實現(xiàn)有三種方式:組合控件戈盈、自繪控件和繼承控件。下面將分別對這三種方式進行介紹谆刨。

組合控件

組合控件塘娶,即將本有的控件組合起來使用,形成新的控件痊夭。下面給大家介紹一種標題組合控件刁岸。

1、布局文件她我,可以在這個地方將控件組合起來使用虹曙,形成新的控件。

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="55dp"
    android:background="#808080"
    android:orientation="horizontal">

    <ImageView
        android:id="@+id/back"
        android:layout_width="30dp"
        android:layout_height="30dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:src="@drawable/back" />

    <TextView
        android:id="@+id/title_text"
        android:layout_width="0dp"
        android:layout_height="30dp"
        android:layout_marginLeft="10dp"
        android:layout_marginTop="10dp"
        android:layout_weight="1"
        android:ellipsize="end"
        android:gravity="center_vertical"
        android:maxLines="1"
        android:textColor="#ffffff"
        android:textSize="18dp"
        android:textStyle="bold"
        tools:text="TITLE" />

    <TextView
        android:id="@+id/right_text"
        android:layout_width="wrap_content"
        android:layout_height="30dp"
        android:layout_marginRight="10dp"
        android:layout_marginTop="10dp"
        android:gravity="center_vertical"
        android:textColor="#ffffff"
        android:textSize="14dp"
        android:textStyle="bold"
        tools:text="編輯" />
</LinearLayout>

2番舆、創(chuàng)建一個類CustomTitleView 根吁,繼承自RelativeLayout:

import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
 
public class CustomTitleView extends RelativeLayout {

    private ImageView back;
    private TextView title;
    private TextView rightText;
    private TitleListener listener;

    public CustomTitleView(Context context) {
        this(context, null);
    }

    public CustomTitleView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomTitleView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        View.inflate(context, R.layout.view_title, this);
        initView();
        setEvent();
    }

    public void setTitleData(String titleText) {
        title.setText(titleText);
    }

    public void setListener(TitleListener listener) {
        this.listener = listener;
    }

    private void initView() {
        back = (ImageView) findViewById(R.id.back);
        title = (TextView) findViewById(R.id.title_text);
        rightText = (TextView) findViewById(R.id.right_text);

    }

    private void setEvent() {
        back.setOnClickListener(v -> listener.onBack());
        rightText.setOnClickListener(v -> listener.onRight());
    }

    public interface TitleListener {
        void onBack();

        void onRight();
    }
}

3、以上合蔽,我們的組合控件View就已經(jīng)完成,使用也很方便介返,如下:

 title = (CustomTitleView) findViewById(R.id.title);
        title.setTitleData("TEST");
        title.setListener(new CustomTitleView.TitleListener() {
            @Override
            public void onBack() {
                finish();
            }

            @Override
            public void onRight() {
                //no-op
            }
        });

4拴事、運行效果如下:


組合控件

繼承控件

繼承控件就是沃斤,繼承已有的控件,保留需要的功能刃宵,引入新的特性衡瓶。這種自定義方法是最常見,使用最廣泛的牲证。比如說自定義Dialog等哮针。

1、創(chuàng)建dialog的布局文件

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageView
        android:id="@+id/background_image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/transparent_half"
        android:scaleType="fitXY" />

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:layout_marginLeft="@dimen/margin40"
        android:layout_marginRight="@dimen/margin40"
        android:background="@drawable/shape_frame_gray_background_white">

        <TextView
            android:id="@+id/dialog_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_marginEnd="@dimen/margin10"
            android:layout_marginStart="@dimen/margin10"
            android:layout_marginTop="@dimen/margin20"
            android:gravity="center"
            android:textColor="@color/dark_gray"
            android:textSize="@dimen/text_size17"
            tools:text="Logout" />

        <TextView
            android:id="@+id/dialog_content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_below="@+id/dialog_title"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="@dimen/margin30"
            android:layout_marginEnd="@dimen/margin10"
            android:layout_marginStart="@dimen/margin10"
            android:layout_marginTop="@dimen/margin30"
            android:gravity="center"
            android:textColor="@color/dark_gray"
            android:textSize="@dimen/text_size13"
            tools:text="Are you sure you want to log out?" />

        <View
            android:id="@+id/line_transverse"
            android:layout_width="match_parent"
            android:layout_height="@dimen/height1"
            android:layout_below="@+id/dialog_content"
            android:background="@color/gray_dialog" />

        <RelativeLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_below="@+id/line_transverse">

            <Button
                android:id="@+id/right_button"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentEnd="true"
                android:layout_toEndOf="@+id/line_vertical"
                android:background="@color/transparent"
                android:text="@string/dialog_yes"
                android:textAllCaps="false"
                android:textColor="@color/blue"
                android:textSize="@dimen/text_size17" />

            <View
                android:id="@+id/line_vertical"
                android:layout_width="@dimen/height1"
                android:layout_height="@dimen/layout_height54"
                android:layout_centerInParent="true"
                android:background="@color/gray_dialog" />

            <Button
                android:id="@+id/left_button"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_toStartOf="@+id/line_vertical"
                android:background="@color/transparent"
                android:text="@string/dialog_no"
                android:textAllCaps="false"
                android:textColor="@color/blue"
                android:textSize="@dimen/text_size17" />
        </RelativeLayout>
    </RelativeLayout>
</RelativeLayout>

2坦袍、創(chuàng)建CustomDialog類十厢,繼承自Dialog,并實現(xiàn)需要的一些接口捂齐。

public class LikeIosDialog extends Dialog {

    public LikeIosDialog(Context context, int theme) {
        super(context, theme);
    }

    public void onDismiss() {
        if (isShowing()) {
            dismiss();
        }
    }

    public static class Builder {
        private Button leftButton;
        private Button rightButton;
        private TextView dialogTitle;
        private TextView dialogContent;
        private View lineVertical;

        private String message;
        private String title;
        private String leftButtonText;
        private String rightButtonText;
        private View.OnClickListener leftButtonClickListener;
        private View.OnClickListener rightButtonClickListener;
        private boolean isSingle = false;

        private View layout;
        private LikeIosDialog dialog;

        public Builder(Context context) {
            dialog = new LikeIosDialog(context, R.style.Dialog);
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            layout = inflater.inflate(R.layout.layout_dialog, null);
            dialog.addContentView(layout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
            dialog.setContentView(layout);
            dialog.setCancelable(true);
            dialog.setCanceledOnTouchOutside(false);
        }

        public LikeIosDialog createDialog() {
            initView();
            setText();
            setEvent();
            return dialog;
        }

        private void initView() {
            leftButton = (Button) layout.findViewById(R.id.left_button);
            rightButton = (Button) layout.findViewById(R.id.right_button);
            dialogContent = (TextView) layout.findViewById(R.id.dialog_content);
            dialogTitle = (TextView) layout.findViewById(R.id.dialog_title);
            lineVertical = layout.findViewById(R.id.line_vertical);
        }

        private void setText() {
            if (isSingle) {
                leftButton.setVisibility(View.GONE);
                lineVertical.setVisibility(View.GONE);
            } else {
                leftButton.setVisibility(View.VISIBLE);
                lineVertical.setVisibility(View.VISIBLE);
            }
            dialogContent.setText(message);
            leftButton.setText(leftButtonText);
            rightButton.setText(rightButtonText);
            dialogTitle.setText(title);
        }

        private void setEvent() {
            leftButton.setOnClickListener(leftButtonClickListener);
            rightButton.setOnClickListener(rightButtonClickListener);
        }

        public Builder setMessage(String message) {
            this.message = message;
            return this;
        }

        public Builder setTitle(String title) {
            this.title = title;
            return this;
        }

        public Builder setLeftButton(String leftButtonText, View.OnClickListener leftButtonClickListener) {
            this.leftButtonText = leftButtonText;
            this.leftButtonClickListener = leftButtonClickListener;
            return this;
        }

        public Builder setRightButton(String rightButtonText, View.OnClickListener rightButtonClickListener) {
            this.rightButtonText = rightButtonText;
            this.rightButtonClickListener = rightButtonClickListener;
            return this;
        }

        public Builder isSingleButton(boolean isSingleButton) {
            this.isSingle = isSingleButton;
            return this;
        }

        public Builder setSingleButton(String rightButtonText, View.OnClickListener rightButtonClickListener) {
            this.rightButtonText = rightButtonText;
            this.rightButtonClickListener = rightButtonClickListener;
            return this;
        }
    }

    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (keyCode == KeyEvent.KEYCODE_BACK) {
            dismiss();
        }
        return super.onKeyDown(keyCode, event);
    }
}

3蛮放、使用

private BukkaDialog.Builder deleteDialogBuilder;
private BukkaDialog deleteDialog;
 
deleteDialogBuilder = new BukkaDialog.Builder(this);
deleteDialog = deleteDialogBuilder
                .setTitle(getString(R.string.dialog_title))
                .setMessage(getString(R.string.dialog_content))
                .isSingleButton(false)
                .setRightButton(getString(R.string.ok), v1 -> {
                   //TODO something
                    deleteDialog.onDismiss();
                })
                .setLeftButton(getString(R.string.cancel), v12 -> deleteDialog.onDismiss())
                .createDialog();
        deleteDialog.show();

4、運行效果如下:


繼承控件

自繪控件

自繪控件的內(nèi)容都是自己繪制出來的奠宜,在View的onDraw方法中完成繪制包颁。在自定義View中,難度最大压真,但是效果最好的一種方法娩嚼,下面就實現(xiàn)一個簡單圓圈的畫法。

1滴肿、創(chuàng)建CounterView類岳悟,繼承自View,同時可以實現(xiàn)OnClickListener等接口:

package com.monoqn.widgets;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.Display;
import android.view.View;
import android.view.WindowManager;

public class CounterView extends View {

    private Paint mPaint;
    private Context mContext;
    private int screenWidth;
    private int screenHeight;

    public CounterView(Context context) {
        super(context, null);
        init();
    }

    public CounterView(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
        init();
    }

    private void init() {
        mPaint = new Paint();
        mPaint.setAntiAlias(true);
        mPaint.setColor(Color.RED);

        mPaint.setStyle(Paint.Style.STROKE);

        mPaint.setStrokeWidth(20);

        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        Display display = wm.getDefaultDisplay();
        screenWidth = display.getWidth();
        screenHeight = display.getHeight();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        canvas.drawCircle(screenWidth / 2, screenHeight / 2, 50, mPaint);
    }
}

2嘴高、在activity_main.xml中引入該自定義布局:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:orientation="vertical">

    <com.monoqn.widgets.CounterView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />
</FrameLayout>

3竿音、運行效果如下:


自繪控件

小結

自定義view的內(nèi)容到這里就結束了,相信對于簡單的自定義view大家都可以簡單的應對了拴驮。當然學習是無止境的春瞬,希望大家可以不斷地探索學習,其中還有很多東西值得大家學習套啤。下一期我想和大家分享的是:深度探索Activity宽气!

原文鏈接:
[http://www.reibang.com/p/61d338b30c4d)

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市潜沦,隨后出現(xiàn)的幾起案子萄涯,更是在濱河造成了極大的恐慌,老刑警劉巖唆鸡,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件涝影,死亡現(xiàn)場離奇詭異,居然都是意外死亡争占,警方通過查閱死者的電腦和手機燃逻,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進店門序目,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人伯襟,你說我怎么就攤上這事猿涨。” “怎么了姆怪?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵叛赚,是天一觀的道長。 經(jīng)常有香客問我稽揭,道長俺附,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任淀衣,我火速辦了婚禮昙读,結果婚禮上,老公的妹妹穿的比我還像新娘膨桥。我一直安慰自己蛮浑,他們只是感情好,可當我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布只嚣。 她就那樣靜靜地躺著沮稚,像睡著了一般。 火紅的嫁衣襯著肌膚如雪册舞。 梳的紋絲不亂的頭發(fā)上蕴掏,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天,我揣著相機與錄音调鲸,去河邊找鬼盛杰。 笑死,一個胖子當著我的面吹牛藐石,可吹牛的內(nèi)容都是我干的即供。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼于微,長吁一口氣:“原來是場噩夢啊……” “哼逗嫡!你這毒婦竟也來了?” 一聲冷哼從身側響起株依,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤驱证,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后恋腕,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抹锄,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了伙单。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呆万。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖车份,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情牡彻,我是刑警寧澤扫沼,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站庄吼,受9級特大地震影響缎除,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜总寻,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一器罐、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渐行,春花似錦轰坊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蕴忆,卻和暖如春颤芬,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背套鹅。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工站蝠, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人卓鹿。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓菱魔,卻偏偏與公主長得像,于是被迫代替她去往敵國和親减牺。 傳聞我的和親對象是個殘疾皇子豌习,可洞房花燭夜當晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容