1. 程式人生 > >Android自定義view-打造酷炫的字型滑動高亮控制元件

Android自定義view-打造酷炫的字型滑動高亮控制元件

前言:

相信很多時候開發會遇到類似於音樂歌詞同步,播放到哪句歌詞的哪個詞時會逐漸高亮,這樣的描述還是不夠準確,iPhone的滑動解鎖的那種效果,相信很多人都會熟悉吧。今天,我們的首要任務就是開發一個類似於這種效果的安卓控制元件,以便在以後的專案中直接使用,看起來高大上有木有。其實也不用害怕,需要我們分析和撰寫的內容並不多,廢話不多說,開始我們今天的教程吧。

正文:


在開始講解之前,需要準備的知識點有:

  1. 必要的安卓基礎
  2. 安卓view 的執行流程
  3. Android畫筆的LinearGradient線性渲染
好了,其實對於以上知識點不瞭解也沒有關係,要是都瞭解了,就沒有必要寫這篇文章了。 問題一:為什麼要有必要的安卓基礎呢?
如果對繼承,重寫元件沒有必要的瞭解,這篇文章是看不下去的。 問題二:安卓的view執行流程是什麼呢?
  • 執行構造方法
  • onFinishInflate
  • onSizeChanged
  • onDraw
  • ....
問題三:LinearGradient的線性渲染需要了解哪些內容呢? LinearGradient有兩個建構函式:
public LinearGradient(float x0, float y0, float x1, float y1, int[] colors, float[] positions,Shader.TileMode tile) 
引數:
float x0: 漸變起始點x座標
float y0:漸變起始點y座標
float x1:漸變結束點x座標
float y1:漸變結束點y座標
int[] colors:顏色 的int 陣列
float[] positions: 相對位置的顏色陣列,可為null,  若為null,可為null,顏色沿漸變線均勻分佈
Shader.TileMode tile: 渲染器平鋪模式


public LinearGradient(float x0, float y0, float x1, float y1, int color0, int color1,Shader.TileMode tile)
float x0: 漸變起始點x座標
float y0:漸變起始點y座標
float x1:漸變結束點x座標
float y1:漸變結束點y座標
int color0: 起始漸變色
int color1: 結束漸變色
Shader.TileMode tile: 渲染器平鋪模式
Shader.TileMode有3種引數可供選擇,分別為CLAMP、REPEAT和MIRROR:
CLAMP的作用是如果渲染器超出原始邊界範圍,則會複製邊緣顏色對超出範圍的區域進行著色
REPEAT的作用是在橫向和縱向上以平鋪的形式重複渲染點陣圖
MIRROR的作用是在橫向和縱向上以映象的方式重複渲染點陣圖
知識準備已經完成了,開始動手擼程式碼了。吐舌頭
Step1:繼承TextView
public class HightLightTextView extends TextView 
Step2:重寫三個構造方法,當然根據需要,重寫一個兩個引數的構造方法也行。我複寫三個是為了以後能夠使用自定義屬性。
	// 構造方法
	public HightLightTextView(Context context) {
		this(context, null);
	}

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

	public HightLightTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

Step3:在onSizeChanged方法中初始化引數。
/**
	 * view的呼叫過程:構造方法->onFinishInflate->onSizeChanged->onDraw
	 */
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		// 獲取view的寬度,初始化畫筆等初始屬性
		if (mTextViewWidth == 0) {
			mTextViewWidth = getMeasuredWidth();
			// 如果寬度大於0的話,則初始化
			if (mTextViewWidth > 0) {
				// 初始化畫筆
				mPaint = getPaint();
				// 線性渲染
				mLinearGradient = new LinearGradient(-mTextViewWidth, 0, 0, 0, new int[] { 0X55FFFFFF, 0XFFFFFFFF, 0X55FFFFFF }, new float[] { 0, 0.5f, 1 }, TileMode.CLAMP);
				mPaint.setShader(mLinearGradient);
				matrix = new Matrix();
			}
		}
	}

這裡有個細節,就是畫筆的獲取,我們不是new出來的,而是通過getPaint()獲取父類中的畫筆,所以接下來的onDraw中沒有用到paint,不要懷疑程式碼有問題哦。大笑 至於LinearGradient的每個引數對照我們的知識準備應該不難理解各種引數對應的意思。那麼,還剩下一個問題,這裡的mTextViewWidth為什麼是負的,喏,其實我們的matrix的移動是從-mTextViewWidth<=translate<=mTextViewWidth,可能還是不能理解吧。我們到下面畫個圖解釋一下就清楚了。 Step4:在onDraw中繪製view
@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (isAnimateOn && matrix != null) {
			mTranslateX += mTextViewWidth / 10;
			// 如果移動的距離大於兩倍的寬度,則重新開始移動
			if (mTranslateX > 2 * mTextViewWidth) {
				mTranslateX = -mTextViewWidth;
			}
			// 平移matrix
			matrix.setTranslate(mTranslateX, 0);
			// 設定線性變化的matrix
			mLinearGradient.setLocalMatrix(matrix);
			// 延遲100ms重繪
			postInvalidateDelayed(100);
		}
	}


其實我們移動的就是藍色的matrix,移動了兩倍的textview之後,再重置matrix,然後就postInvalidateDelayed繪製我們的view。okay了,看到這裡應該很熟悉怎麼去寫這樣的一個效果了吧。如果你覺得滑動慢,改變一些重繪的時間,如果你覺得顏色需要改變,那就設定對外的介面,或者直接修改view裡的顏色即可,至於擴充套件,留給大家擴充套件了。 這裡貼上view 的全部程式碼以及如何使用: HightLightTextView.java
package com.beyole.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Shader.TileMode;
import android.util.AttributeSet;
import android.widget.TextView;

public class HightLightTextView extends TextView {

	// 儲存view的寬度
	private int mTextViewWidth = 0;
	// 畫筆
	private Paint mPaint;
	// 線性渲染
	private LinearGradient mLinearGradient;
	// 儲存變換的matrix
	private Matrix matrix;
	// 移動距離
	private int mTranslateX = 0;
	// 是否開啟動畫
	private boolean isAnimateOn = true;

	// 構造方法
	public HightLightTextView(Context context) {
		this(context, null);
	}

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

	public HightLightTextView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	/**
	 * view的呼叫過程:構造方法->onFinishInflate->onSizeChanged->onDraw
	 */
	@Override
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);
		// 獲取view的寬度,初始化畫筆等初始屬性
		if (mTextViewWidth == 0) {
			mTextViewWidth = getMeasuredWidth();
			// 如果寬度大於0的話,則初始化
			if (mTextViewWidth > 0) {
				// 初始化畫筆
				mPaint = getPaint();
				// 線性渲染
				mLinearGradient = new LinearGradient(-mTextViewWidth, 0, 0, 0, new int[] { 0X55FFFFFF, 0XFFFFFFFF, 0X55FFFFFF }, new float[] { 0, 0.5f, 1 }, TileMode.CLAMP);
				mPaint.setShader(mLinearGradient);
				matrix = new Matrix();
			}
		}
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);
		if (isAnimateOn && matrix != null) {
			mTranslateX += mTextViewWidth / 10;
			// 如果移動的距離大於兩倍的寬度,則重新開始移動
			if (mTranslateX > 2 * mTextViewWidth) {
				mTranslateX = -mTextViewWidth;
			}
			// 平移matrix
			matrix.setTranslate(mTranslateX, 0);
			// 設定線性變化的matrix
			mLinearGradient.setLocalMatrix(matrix);
			// 延遲100ms重繪
			postInvalidateDelayed(100);
		}
	}

}

activity_main.xml:
<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"
    android:background="@drawable/demo"
     >

    <com.beyole.view.HightLightTextView
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="10dip"
        android:textSize="22sp"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="滑動解鎖" />

</RelativeLayout>

好了,教程到此為止結束了。

相關推薦

Android定義view-打造字型滑動控制元件

前言: 相信很多時候開發會遇到類似於音樂歌詞同步,播放到哪句歌詞的哪個詞時會逐漸高亮,這樣的描述還是不夠準確,iPhone的滑動解鎖的那種效果,相信很多人都會熟悉吧。今天,我們的首要任務就是開發一個類似於這種效果的安卓控制元件,以便在以後的專案中直接使用,看起來高大上有木有

Android 定義View實現動態按鈕

普通按鈕也就那麼幾種樣式,看著都審美疲勞,先放效果圖,演示Demo+原始碼在最後面 你會不會以為這個按鈕是集結了很多動畫的產物,我告訴你,並沒有。所有的實現都是基於自定義View,採用最底層的onDraw一點一點的畫出來的。沒有采用一丁點的動畫。雖然演示時間很短,但是要

android定義view-打造圓形ImageView(一)

package com.beyole.view; import com.beyole.roundimageview.R; import android.content.Context; import android.content.res.TypedArray; import android.graphi

android定義view-打造圓形ImageView(四)終結篇

package com.beyole.view; import java.lang.ref.WeakReference; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitm

android定義view-打造圓形ImageView(二)

package com.beyole.view; import java.lang.ref.WeakReference; import android.content.Context; import android.content.res.TypedArray; import android.graphi

android定義View打造自己的專屬控制元件——風車控制元件

Android 自定義View——打造自己的專屬控制元件 前段時間看到一個天氣應用,介面做的很好看。裡面一個風車轉動動畫和一個日出日落的動畫挺有意思的,於是自己也照著他的介面做了一個。 先看一下介面 自定義View一般有兩種情況 繼承自原有控制元件

Android定義View,實現全屏滑動的DrawerLayout

    對與DrawerLayout大家應該用過,是Google官方推出的一種抽屜式導航控制元件。開啟左右兩邊選單的方式是從手機屏 幕的邊緣處滑動來觸發,不過總有些**的需求要讓它可以全屏滑動觸發選單,網上也有一些解決辦法,無非就是用 setDrawerLeftE

Android定義View之實現簡單的球體進度球

前言 最近一直在研究自定義view,正好專案中有一個根據下載進度來實現球體進度的需求,所以自己寫了個進度球,程式碼非常簡單。先看下效果: 效果還是非常不錯的。 準備知識 要實現上面的效果我們只要掌握兩個知識點就好了,一個是Handler機制,用於發訊息重新整理我們的進度球,一個是clip

Android定義View實現的主題切換動畫(仿安客戶端)

前兩日偶然看到了一個很炫酷的動畫效果: 判斷它是不是用的ValueAnimator, 如果是的話, 我們可以在設定-開發者選項裡面設定 “動畫時長縮放”來改變動畫時長. 所以這次我們通過設定這個選項, 把動畫速度降低之後, 很快就看出了其中的奧妙

Android定義view(一),打造絢麗的驗證碼

前言:我相信信念的力量,信念可以支撐起一個人,一個名族,一個國家。正如“人沒有夢想和鹹魚有什麼區別”一樣,我有信念,有理想,所以我正在努力向著夢想前進~。 自定義view,如果是我,我首先要看到自定義view的效果圖,然後再想想怎麼實現這種效果或功能,所以先貼

android定義view實現字型變色

上次看了鴻洋的部落格,其中有一篇部落格實現的是字型逐漸變色的效果,不過其使用的是clipRect實現的,今天給大家帶來另一種實現方式,通過XferMode來實現。先看效果吧。 先說下實現原理:我們首先繪製當前顯示的文字內容,然後設定xfermode的值為P

手把手教你打造一個心電圖效果View Android定義View

大家好,看我像不像蘑菇…因為我在學校呆的發黴了。 思而不學則殆 麗麗說得對,我有奇怪的疑問,大都是思而不學造成的,在我書讀不夠的情況下想太多,大多等於白想,所以革命沒成功,同志仍需努力。 好了廢話不說了,由於布總要做一個心電圖的玩意,所以做來練練手

Android 定義View

wid declare created odi lex getwidth 實現 tdi led   最近在看鴻洋大神的博客,在看到自定義部分View部分時,想到之前案子中經常會要用到"圖片 + 文字"這類控件,如下圖所示: 之前的做法是在布局文件中,將一個Imag

Android定義view詳解

this boolean mar 處理 都是 並且 jdk text 命名 從繼承開始 懂點面向對象語言知識的都知道:封裝,繼承和多態,這是面向對象的三個基本特征,所以在自定義View的時候,最簡單的方法就是繼承現有的View 通過上面這段代碼,我定義了一個Ske

Android -- 定義view實現keep歡迎頁倒計時效果

super onfinish -m use new getc awt ttr alt 1,最近打開keep的app的時候,發現它的歡迎頁面的倒計時效果還不錯,所以打算自己來寫寫,然後就有了這篇文章。 2,還是老規矩,先看一下我們今天實現的效果   相較於我們常見的倒計時

Android定義View效果目錄

class 重寫 自定義 textview 居中 url 冒泡 and 雷達圖 1、絢麗的loading動效的實現 2、Android自定義View:進度條+冒泡文本 3、Android雷達圖(蜘蛛網圖) 4、Android文本閃爍 5、Android繪制圓形進度條 6、重

Android定義View——實現水波紋效果類似剩余流量球

string 三個點 pre ber block span 初始化 move 理解 最近突然手癢就想搞個貝塞爾曲線做個水波紋效果玩玩,終於功夫不負有心人最後實現了想要的效果,一起來看下吧: 效果圖鎮樓 一:先一步一步來分解一下實現的過程 需要繪制一個正弦曲線(sin

Android 定義 View 知識點

移動 encode swe em1 red 鋸齒 枚舉類 map() tex 根據 Hencoder 提供的知識點,進行學習和總結。 三個要點: 布局 繪制 觸摸反饋 繪制 自定義繪制:由自己實現繪制過程 常用繪制方法 onDraw(Canvas canvas) 繪制

Android定義view與activity的傳值

重復 轉動 自定義 activit 廣播 內部 代碼 view 等待 昨晚在寫團隊項目的時候,遇到一個問題,直到今天早上才解決。。。即在自定義view“轉盤”結束轉動後獲取結果的處理中,我是想吧值傳到activity中的一個textview中的,但我的自定義view類不是a

Android 定義View - 助記詞

UI今天給了個需求,把亂序的單詞拼成一句話,如下圖: 本來計劃是用ViewGroup+TextView寫的,突然腦子抽了想用paint來畫(寫完就後悔了-.-) 先看一下完成後的效果 前期的思路是這樣的: 1.測量每個單詞的高度和寬度,計算出所有單詞排列後的高*2,就是view