日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

android自定义控件几种,Android 自定义View一个控件搞定多种水波纹涟漪扩散效果 - CSDN博客...

發布時間:2023/12/10 Android 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 android自定义控件几种,Android 自定义View一个控件搞定多种水波纹涟漪扩散效果 - CSDN博客... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

效果圖

實現思路

這個效果實現起來并不難,重要的是思路

此View滿足了多種水波紋漣漪擴散效果,這要求它能滿足很多的變化

根據上面的樣式,可以看出此View需要滿足以下變化

圓圈從中心可循環向外擴散

圓圈之間的擴散間距可以改變

可控制擴散圓的漸變度

圓圈可以是線條樣式或者實心樣式

圓圈擴散的速度可以控制

適配圓圈不同大小下的擴散效果

具體實現

創建自定義屬性

首先為View創建自定義的xml屬性

在工程的values目錄下新建attrs.xml文件

各個屬性的作用如下

cColor:View控件的顏色

cSpeed:向外擴散的速度

cDensity:圓形波紋擴散的間距

cIsFill:是否開啟填充模式,true為實心圓

cIsAlpha:是否開啟漸變效果,true為開啟

創建自定義View控件

新建RippleView類繼承View類,重寫它的三個構造方法,獲取用戶設置的屬性,同時指定默認值

public RippleView(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

// 獲取用戶配置屬性

TypedArray tya = context.obtainStyledAttributes(attrs, R.styleable.mRippleView);

mColor = tya.getColor(R.styleable.mRippleView_cColor, Color.BLUE);

mSpeed = tya.getInt(R.styleable.mRippleView_cSpeed, 1);

mDensity = tya.getInt(R.styleable.mRippleView_cDensity, 10);

mIsFill = tya.getBoolean(R.styleable.mRippleView_cIsFill, false);

mIsAlpha = tya.getBoolean(R.styleable.mRippleView_cIsAlpha, false);

tya.recycle();

init();

}

使用TypedArray讀取完自定義的屬性后一定要記得調用recycle方法釋放掉

重寫onMeasure

測量onMeasure,首先需要測量出View的寬和高,并指定View在wrap_content時的最小范圍,對于View繪制流程還不熟悉的同學,可以先去了解下具體的繪制流程

重寫onMeasure方法,其中我們要考慮當View的寬高被指定為wrap_content時的情況,如果我們不對wrap_content的情況進行處理,那么當使用者指定View的寬高為wrap_content時將無法正常顯示出View

@Override

protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

super.onMeasure(widthMeasureSpec, heightMeasureSpec);

int myWidthSpecMode = MeasureSpec.getMode(widthMeasureSpec);

int myWidthSpecSize = MeasureSpec.getSize(widthMeasureSpec);

int myHeightSpecMode = MeasureSpec.getMode(heightMeasureSpec);

int myHeightSpecSize = MeasureSpec.getSize(heightMeasureSpec);

// 獲取寬

if (myWidthSpecMode == MeasureSpec.EXACTLY) {

// match_parent/精確值

mWidth = myWidthSpecSize;

} else {

// wrap_content

mWidth = DensityUtil.dip2px(mContext, 120);

}

// 獲取高

if (myHeightSpecMode == MeasureSpec.EXACTLY) {

// match_parent/精確值

mHeight = myHeightSpecSize;

} else {

// wrap_content

mHeight = DensityUtil.dip2px(mContext, 120);

}

// 設置該view的寬高

setMeasuredDimension(mWidth, mHeight);

}

MeasureSpec的狀態分為三種EXACTLY、AT_MOST、UNSPECIFIED,這里只要單獨指定非精確值EXACTLY之外的情況就好了

本文中使用到的DensityUtil類,是為了將dp轉換為px來使用,以便適配不同的屏幕顯示效果

public static int dip2px(Context context, float dpValue) {

final float scale = context.getResources().getDisplayMetrics().density;

return (int) (dpValue * scale + 0.5f);

}

重寫onDraw

設計的整體思路如下圖所示

先要實現圓形向外擴散的效果

初始化第一個圓

這里的動畫效果本來是想使用ValueAnimator屬性動畫的數值發生器來實現,但是我們這里有很多的計算需求,所以最后還是選擇使用算法來實現,方便控制圓的一些參數

想要實現擴散的效果,這里思路是在每次更新View時動態改變圓的半徑,同時還需要給圓設置漸變度數,所以決定用一個類來保存圓的狀態,所有圓都存在一個List里

// 添加第一個圓圈

mRipples = new ArrayList<>();

Circle c = new Circle(0, 255);

mRipples.add(c);

傳入Circle類里的兩個參數,第一個0表示圓的初始寬度,第二個255表示初始透明度

添加新圓

要想實現不斷有圓向外擴散,就需要在第一個圓擴散到一定范圍時在圓心處再添加一個圓,這個的范圍可以由圓的半徑來控制,當List集合中最后一個圓的半徑增加到某個值mDensity時,新的圓就從圓心處創建出來

// 添加圓

if (mRipples.size() > 0) {

// 控制第二個圓出來的間距

if (mRipples.get(mRipples.size() - 1).width > DensityUtil.dip2px(mContext, mDensity)) {

mRipples.add(new Circle(0, 255));

}

}

刪除List中多余的圓

List中的圓存儲的數量不宜過多,多了內存消耗大,需要在當圓的半徑超過View的寬度時就刪掉這個圓

// 當圓超出View的寬度后刪除

if (c.width > mWidth / 2) {

mRipples.remove(i);

}

我們也可以在外切正方形的頂點處刪除這個圓,需要用到勾股定律來計算擴散圓到外切正方形頂點的位置

如上圖所示,得出計算公式為

// 使用勾股定律求得一個外切正方形中心點離頂點的距離

sqrtNumber = (int) (Math.sqrt(mWidth * mWidth + mHeight * mHeight) / 2);

這樣就需要修改刪除圓的位置了

if (c.width > sprtNumber) {

mRipples.remove(i);

}

控制擴散圓的漸變度

當圓在向View的邊緣擴散時,漸變度數的改變需要動態來計算,漸變的計算算法要適配不同的圓寬度大小,我們知道透明度是0~255之間的,0表示完全透明,255表示百分百不透明,計算的時候就是需要將這個數值等份分配到圓的寬度里

這里要區分一點,對于圓來說,寬度是由圓心從0開始向外遞增,而漸變度數則是由圓心從255開始向外遞減,當圓與最外圍的正方形內切時漸變度必須變為0,由此分析得知,公式如下

透明度 = 255 - 圓的寬度 * (255 / View寬度)

double alpha = 255 - c.width * (255 / ((double) mWidth / 2));

c.alpha = (int) alpha;

GitHub地址

總結

關于自定義View的總結部分在我的其它博客中已經寫過蠻多了,有興趣的可以去看看

做自定義View,思路很重要,當想到一種方法可以實現時,先不要著急的做出來,試著換一個角度再多思考一下還有沒有更好的實現方式

本例子還缺少一些控制邏輯代碼,將在之后添加上去并更新在GitHub中

總結

以上是生活随笔為你收集整理的android自定义控件几种,Android 自定义View一个控件搞定多种水波纹涟漪扩散效果 - CSDN博客...的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 色姑娘天天操 | 在线日韩三级 | 欧美日韩在线观看免费 | 国产欧美日韩专区发布 | 国产一区视频在线观看免费 | 国产精品伦一区二区三级古装电影 | 特级性生活片 | 亚洲专区av| 午夜久久久久久久久久影院 | 男人日女人在线观看 | 国产内射一区 | 亚洲午夜精选 | 最新中文字幕av专区 | 狠狠人妻久久久久久综合 | 久久婷婷五月综合色吧 | 一级黄色免费视频 | 国产精品自拍电影 | 日韩成人短视频 | 奇米影视首页 | 草色网 | 日韩免费一二三区 | 欧美精品观看 | 国产99精品视频 | 国产人妖在线观看 | 伊人久久av| 亚洲精品免费网站 | 国产精品人成在线观看免费 | 久久久艹 | 中文字幕网址在线 | 91网站永久免费看nba视频 | 麻豆亚洲 | 欧美大尺度做爰啪啪床戏明星 | 久久久久久黄色 | 老头糟蹋新婚少妇系列小说 | 噜噜噜亚洲色成人网站 | 91高跟黑色丝袜呻吟动态图 | 欧美性极品 | 少妇紧身牛仔裤裤啪啪 | 欧美熟妇精品一区二区蜜桃视频 | 欧美亚洲在线视频 | 欧美大片免费看 | 日韩在线一二 | 91男女视频 | 成人午夜福利视频 | 精品无码久久久久久久久果冻 | 正在播放经典国语对白 | 国产一区二区三区精品视频 | 精品无码久久久久成人漫画 | 啪啪啪一区二区 | 欧美一区免费 | 日本一区不卡视频 | 日韩成人免费观看 | 98超碰在线 | 成人一级黄色片 | 男生和女生靠逼视频 | 国产在线精品播放 | 国产精品社区 | 香蕉久热 | 黄色一级网址 | 亚洲一二三区在线 | 国产一级片免费观看 | 日韩精品欧美激情 | 男女网站在线观看 | 色丁香婷婷 | 亚洲精品www久久久 一级aaa毛片 | 黑色丝袜吻戏亲胸摸腿 | 95看片淫黄大片一级 | www日| 日本特级淫片 | 亚洲男人天堂网 | 色婷婷在线播放 | 成人免费网视频 | 色六月婷婷| 国产一级久久久 | 国产女人18毛片水18精品 | 欧美日韩色图 | 欧美日韩卡一卡二 | 久久久精品视频免费 | 噜噜噜久久,亚洲精品国产品 | 91精品国产色综合久久不卡电影 | 美国av毛片| 一级黄网| 国产深夜福利 | 日韩一区二区免费在线观看 | 免费黄色看片 | 日本一区二区在线免费 | 色偷偷伊人 | 欧美丰满熟妇xxxxx | 黄色视屏免费 | 中文字幕无码毛片免费看 | 中文字幕一区二区三区人妻不卡 | 国产精选视频 | 欧美精品一区二区三区三州 | 亚洲丝袜av | 深夜视频在线观看免费 | 手机av免费 | 亚洲一区二区动漫 | 国产午夜性春猛交ⅹxxx | 亚洲区av |