1. 程式人生 > >android 自定義View(二) 自定義屬性和帶滾動的View

android 自定義View(二) 自定義屬性和帶滾動的View

自定義View的屬性

  在上一章中講了那麼多,這一章開始就進行實戰了。首先來一發自定義View屬性的demo。
自定義View屬性的步驟分為以下3步。
(1) 新建一個attrs.xml檔案,在這個資原始檔中定義我們需要的屬性。
(2)新建一個自定義的View,對其中的的方法進行重寫。
(3)在layout中引用這個新的控制元件。
先進行第一步。在values檔案下新建一個attrs.xml檔案。

<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<resources
>
<attr name="testText" format="string"/> <attr name="testColor" format="color"/> <attr name="testSize" format="dimension"/> <attr name="testBackGroudColor" format="color"/> <declare-styleable name="CustomTitleView"> <attr name="testText"
/>
<attr name="testColor" /> <attr name="testSize" /> <attr name="testBackGroudColor"/> </declare-styleable> </resources>

這裡我們定義了一個屬性組,包含了文字,文字顏色,文字大小以及控制元件背景色,且規定了它們的型別分別為string ,color,dimension。
  然後在自定義的View中引用這些屬性。

public class TestView
extends View{
private String testText;//文字 private int testColor;//文字顏色 private int testSize;//文字大小 private int testBackGroudColor;//背景色 private Rect mBound; private Paint mPaint; public TestView(Context context) { this(context, null); } public TestView(Context context,AttributeSet attrs) { this(context, attrs, 0); } public TestView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); // TODO Auto-generated constructor stub //建構函式中引用屬性 TypedArray ta = context.getTheme().obtainStyledAttributes(attrs,R.styleable.CustomTitleView, defStyleAttr, 0); int n = ta.getIndexCount(); for (int i = 0; i < n; i++) { int attr = ta.getIndex(i); switch (attr) { case R.styleable.CustomTitleView_testText: testText = ta.getString(attr); break; case R.styleable.CustomTitleView_testColor: testColor = ta.getColor(attr, Color.GRAY); break; case R.styleable.CustomTitleView_testSize: testSize = ta.getDimensionPixelSize(attr, (int) TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 16, getResources().getDisplayMetrics())); break; case R.styleable.CustomTitleView_testBackGroudColor: testBackGroudColor = ta.getColor(attr, Color.BLACK); } } ta.recycle(); mPaint = new Paint(); mPaint.setTextSize(testSize); mBound = new Rect(); mPaint.getTextBounds(testText, 0, testText.length(), mBound); } protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); } protected void onDraw(Canvas canvas) { mPaint.setColor(testBackGroudColor); canvas.drawRect(0, 0, getMeasuredWidth(), getMeasuredHeight(), mPaint); mPaint.setColor(testColor); canvas.drawText(testText, getWidth() / 2 - mBound.width() / 2, getHeight() / 2 + mBound.height() / 2, mPaint); }

接下來進行最後一步,在佈局中引用自定義的View

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:custom="http://schemas.android.com/apk/res/com.example.myview"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.myview.MainActivity" >
   <com.example.myview.TestView 
        android:layout_width="200dp"
        android:layout_height="100dp"
        custom:testText="12345"
        custom:testColor="#ff0000"
        custom:testSize="40sp"
        custom:testBackGroudColor="#00ff00"/>
</RelativeLayout>

注意命名控制元件的引用xmlns:custom=”http://schemas.android.com/apk/res/com.example.myview”。
具體程式碼將傳到github上,效果可自行下載後檢視。

自定可以隨意拖動的滾動View

這個Demo中包含了View的滾動和點選事件。涉及到了View自定義中的onTouchEvent onMeasure等。
先初始化一個文字

    protected void init() {
        mPaint = new Paint();
        mPaint.setColor(Color.GREEN);
        mPaint.setTextSize(80);
        Rect rect = new Rect();
        mPaint.getTextBounds(text[0], 0, text[0].length(), rect);
        textWidth = rect.width();
        textHeight = rect.height();
        x = getLeft() + getPaddingLeft();
        startY = getTop() + textHeight + getPaddingTop() - 7;// 文字基線 需要調整
        Log.d("hk", "textHeight startY  = "+textHeight+" "+startY);
        endY = startY + textHeight + getPaddingBottom();
        Log.d("hk", "endY  getPaddingBottom() "+endY+" "+getPaddingBottom());
        nextStartY = getTop() - 7;
        firstY = startY;
        secondY = nextStartY;
    }

在對這個文字的大小進行測量

    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = measureWidth(widthMeasureSpec);
        int height = measureHeight(heightMeasureSpec);
        setMeasuredDimension(width, height);
    }
    private int measureHeight(int heightMeasureSpec) {
        int result = 0;
        int size = MeasureSpec.getSize(heightMeasureSpec);
        int mode = MeasureSpec.getMode(heightMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = (int) (getPaddingTop() + getPaddingBottom() + textHeight);
            if (mode == MeasureSpec.AT_MOST) {
                result = Math.min(result, size);
            }
        }
        return result;
    }

    private int measureWidth(int widthMeasureSpec) {
        int result = 0;
        int size = MeasureSpec.getSize(widthMeasureSpec);
        int mode = MeasureSpec.getMode(widthMeasureSpec);
        if (mode == MeasureSpec.EXACTLY) {
            result = size;
        } else {
            result = (int) (getPaddingLeft() + getPaddingRight() + textWidth);
            if (mode == MeasureSpec.AT_MOST) {
                result = Math.min(result, size);
            }
        }
        return result;
    }

最後在onDraw中讓文字進行滾動。
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d(“HK”, “onDraw”);
//啟動滾動
if (!isScrooll) {
mHandler.sendEmptyMessageDelayed(CHANGE_SPEECH, 2000);
isScrooll = true;
}

    canvas.drawText(text[0], x, startY, mPaint);
    canvas.drawText(text[1], x, nextStartY, mPaint);
    startY += speech;
    nextStartY += speech;

    //超出View的控制元件時
    if (startY > endY || nextStartY > endY) {
        if (startY > endY) {
            //第一次滾動過後交換值
            startY = secondY;
            nextStartY = firstY;
        } else if (nextStartY > endY) {
            //第二次滾動過後交換值
            startY = firstY;
            nextStartY = secondY;
        }
        speech = 0;
        isScrooll = false;
    }
    invalidate();//重新整理View,View的刷星又會呼叫到draw ,因此可以迴圈下去
}

為了使該控制元件能夠接受拖動事件,需要重寫onTouchEvent。

    public boolean onTouchEvent(MotionEvent event) {

        float x;
        float y;
        x = event.getRawX();
        y = event.getRawY();
        switch(event.getAction()) {
        case MotionEvent.ACTION_DOWN:

            Log.d("HK", "ACTION_DOWN"+x+" "+y);
            break;
        case MotionEvent.ACTION_MOVE:
            int lefttopx = (int) (x-textWidth/2);
            int lefttopy = (int) (y-textHeight/2-180);
            int rightbottomx = (int) (lefttopx+textWidth);
            int rightbottomy = (int) (lefttopy+textHeight);
            //if(Math.abs(rightbottomx-lefttopx)>50&&Math.abs(rightbottomy-lefttopy)>20)
            layout(lefttopx, lefttopy, rightbottomx, rightbottomy);//重新佈局
            break;
        case MotionEvent.ACTION_UP:
            Log.d("HK", "ACTION_UP");
            break;
        }
        return true;
    }

相關推薦

android 定義View() 定義屬性滾動View

自定義View的屬性   在上一章中講了那麼多,這一章開始就進行實戰了。首先來一發自定義View屬性的demo。 自定義View屬性的步驟分為以下3步。 (1) 新建一個attrs.xml檔案,在這個資原始檔中定義我們需要的屬性。 (2)新建一個自定義的

面試必問系列 建構函式,原型物件,例項之間的關係()例項屬性原型屬性

在學習建構函式,原型物件,例項之間的關係時,有一個特別容易混亂的點就是例項屬性和原型屬性建立例項之後,我們可以為例項物件繼續新增屬性,如果我們新增的屬性和原型物件中的屬性重名,那麼呼叫的時候,就會先在例項中查詢是否有這個屬性,如果有就直接取例項中的屬性,如果沒有就去原型物件查

Android模組化()——模組通訊模組間服務呼叫

上一篇《我所理解的Android模組化(一)》筆者講到了Android模組化的基本知識和模組化跳轉路由的基本用法,解決了模組化中跳轉的問題,下面就來講講如何實現模組化之間的通訊和跨模組方法呼叫。 模組通訊   有這樣一個場景,就是APP中的登入成功事件,需要在多

Android定義View定義屬性

在Android開發中經常會用到自定義View的情況,而在自定義View時,自定義屬性是必須用到的。 1、新建一個自定義View如CustomView 它的自定義屬性主要是通過declare-styleable標籤為其配置自定義屬性。具體做法是:在res/values/目錄下增加一個reso

HenCoder Android 定義 View 1-7:屬性動畫 Property Animation(進階篇)

這期是 HenCoder 自定義繪製的第 1-7 期:屬性動畫(進階篇) 簡介 上期的內容,對於大多數簡單的屬性動畫場景已經夠用了。這期的內容主要針對兩個方面: 針對特殊型別的屬性來做屬性動畫; 針對複雜的屬性關係來做屬性動畫。 TypeEvaluator

從零開始學Android定義View之動畫系列——屬性動畫(3)

屬性動畫對補間動畫進行了很大幅度的改進,之前補間動畫可以做到的屬性動畫也能做到,補間動畫做不到的現在屬性動畫也可以做到了。因此,今天我們就來學習一下屬性動畫的高階用法,看看如何實現一些補間動畫所無法實現的功能。 ValueAnimator的高階用法 補間

Android繪圖系列()——定義View繪製基本圖形

這個系列主要是介紹下Android自定義View和Android繪圖機制,自己能力有限,如果在介紹過程中有什麼錯誤,歡迎指正 前言 在上一篇Android繪圖系列(一)——自定義View基礎中我們瞭解自定義View相關的基本知識,不過,這些東西依舊還

Android定義View獲取定義屬性

首先扯點別的:今晚回家做了一個魚香肉絲,剛學的,出鍋以後,才想起沒有放豆瓣醬,也是沒誰了。不過吃起來還行,吃了三塊煎餅。 今天記錄一下自定義View的建構函式的使用,以及如何獲取自定義屬性。 先看一下自定義View 的建構函式 public class

Android 高手進階之定義View定義屬性進度的圓形進度條)

很多的時候,系統自帶的View滿足不了我們功能的需求,那麼我們就需要自己來自定義一個能滿足我們需求的View,自定義View我們需要先繼承View,新增類的構造方法,重寫父類View的一些方法,例如onDraw,為了我們自定義的View在一個專案中能夠重用,有時候我們需要自定

Android bc信用盤搭建定義behavior 實現上滑 隱藏底部view

退出 Y軸 log rect app sum string dsl oss 布局 <android.support.design.widget.CoordinatorLayout android:layout_width="match_parent"

Android高階進階之定義View

前言 在網上看到一張圖,花了些時間自己嘗試著寫了一個自定義View,裡面涉及到了自定義屬性、自定義View padding屬性的處理、畫筆(Paint)和畫布(Canvas)的使用、解析度適配問題、效能問題、屬性動畫等,覺得還是有些東西值的記錄一下的,效果圖如下: 自定義屬

android柱狀圖(定義view

  public class HistogramView extends View { private Paint mLinePaint; private Paint mGreenPaint; private Paint mTextPaint;

Android 定義柱狀圖及屬性動畫

前段時間公司專案中用到了統計圖,網上找了些資料和框架都不能滿足我的需求,沒辦法,只有自己寫了。 近來清閒,將其抽出一個demo了,歡迎大家交流指正。 效果圖先行 實現方案有兩個,一是自定義控制元件,二是使用屬性動畫。屬性動畫在api11以上版本才有,在11版本以下使用可以引入nin

android憤怒小鳥遊戲、定義View、掌上餐廳App、OpenGL定義氣泡、抖音電影濾鏡效果等原始碼

Android精選原始碼 精練的範圍選擇器,範圍和單位可以自定義 自定義View做的小鳥遊戲 android popwindow選擇商品規格顏色尺寸效果原始碼 實現Android帶有鋸齒背景的優惠樣式原始碼 android充值頁面效果原始碼 使用

定義View屬性

在自定義的View中,很多時候我們需要對View新增自定義屬性步驟如下: 1) 編寫xml檔案,定義屬性名稱與屬性資料型別 //attrs.xml <resources> <declare-styleable name="MyV

android 註解學習筆記: 元註解定義註解

首先看一個自定義的註解: 1、自定義註解 public @interface MyAnnotation { int age(); } 可見定義一個註解非常簡單,只需要使用@interface關鍵字來定義即可。 同時我們可以看到,註解的內部可以定義變

移動開發----Android模仿打字機效果的定義View實現

前言   在做splash介面的時候,需要做類似於打字機打字的效果,字一個一個地蹦出來,顯示每一個字都帶有打字的聲音。 效果演示 實現原理:   這個其實不難實現,通過一個定時器不斷呼叫TextView的setText就行了,在setTex

android定義View定義EditText(新增刪除功能)

           忙忙碌碌20天,新的專案終於接近尾聲了。今天公司召集幾個使用者體驗師和美工一起吐糟這20天做的這個新產品,對於產品提出了很多建議,這幾天就改介面了。在這個專案中大量的使用了EditText元件,並且添加了刪除功能。這裡面都是用RelativeLayou

android 定義view,在xml中引用內部類View

java.lang.ClassCastException: android.view.View cannot be cast to com.voice.VoiceFragment$AnimationView E/AndroidRuntime( 3543): at com.voice.VoiceFragme

Android定義控制元件 --- 定義屬性 列舉值(固定屬性值)

今天寫一個自定義控制元件,為了提高使用者使用效率,需要對一個屬性的所有可能屬性值進行列舉(即,只能選擇使用給出的屬性值) 查了很多資料,自己總結一下。 如何寫自定義控制元件就不在贅述了,網上很多大神寫的都很好,此處只說明這一種情況。 attrs.xml <?xml