最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android自定義ViewGroup實(shí)現(xiàn)絢麗的仿支付寶咻一咻雷達(dá)脈沖效果

 更新時(shí)間:2016年10月17日 09:56:25   投稿:mrr  
這篇文章主要介紹了Android自定義ViewGroup實(shí)現(xiàn)絢麗的仿支付寶咻一咻雷達(dá)脈沖效果的相關(guān)資料,需要的朋友可以參考下

去年春節(jié)的時(shí)候支付寶推行的集福娃活動(dòng)著實(shí)火的不能再火了,更給力的是春晚又可以全民參與咻一咻集福娃活動(dòng),集齊五福就可平分億元大紅包,只可惜沒有敬業(yè)?!菚r(shí)候在家沒事寫了個(gè)咻一咻插件,只要到了咻一咻的時(shí)間點(diǎn)插件就可以自動(dòng)的點(diǎn)擊咻一咻來咻紅包,當(dāng)時(shí)只是純粹練習(xí)這部分技術(shù)代碼沒有公開,后續(xù)計(jì)劃寫篇關(guān)于插件這方面的文章,扯遠(yuǎn)了(*^__^*) ……我們知道在支付寶的咻一咻頁面有個(gè)雷達(dá)擴(kuò)散的動(dòng)畫效果,當(dāng)時(shí)感覺動(dòng)畫效果非常棒,于是私下嘗試著實(shí)現(xiàn)了類似的效果,后來在github發(fā)現(xiàn)有大神也寫有類似效果,于是讀了一下大神的代碼發(fā)現(xiàn)我們的核心思想都是一樣的,只是細(xì)節(jié)不同,然后我就擇其善者而從之,把兩份代碼整合了一下......整合之后的運(yùn)行效果如下所示:

開始講解實(shí)現(xiàn)之前我們先分析一下支付寶的咻一咻效果,進(jìn)入支付寶咻一咻頁面后點(diǎn)擊了咻一咻按鈕,屏幕上先出現(xiàn)一個(gè)圓在不斷的進(jìn)行放大操作,在該圓進(jìn)行放大操作的同時(shí)其透明度也在由大到小進(jìn)行變化,接著該圓沒有消失之前又會(huì)出現(xiàn)新的圓也在進(jìn)行同樣的動(dòng)畫操作……通過觀察我們發(fā)現(xiàn)這些圓都是按照固定的時(shí)間間隔在依次的執(zhí)行放大和透明度漸變的動(dòng)畫操作,所以要實(shí)現(xiàn)同樣的效果,首先要有一個(gè)ViewGroup,然后給這個(gè)ViewGroup添加固定數(shù)量的子View,最后讓這些子View執(zhí)行放大和透明度漸變動(dòng)畫就可以實(shí)現(xiàn)該效果了。清楚了這個(gè)大綱流程,實(shí)現(xiàn)起來就好辦了。

首先定義我們的ViewGroup,由于該ViewGroup僅僅是添加固定數(shù)量的子View,然后讓這些子View執(zhí)行一系列動(dòng)畫,所以可以直接繼承FrameLayout,代碼如下所示:

public class RadarLayout extends FrameLayout { 
public RadarLayout(Context context) { 
super(context); 
} 
public RadarLayout(Context context, AttributeSet attrs) { 
super(context, attrs); 
} 
public RadarLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
super(context, attrs, defStyleAttr); 
} 
}

我們?yōu)樽约旱倪菀贿菪Ч丶∶麨镽adarLayout,radar為雷達(dá)的意思,RadarLayout就表示在不斷的進(jìn)行掃描的意思。通過前邊的分析我們知道RadarLayout是由固定數(shù)量的子View組成的,因此RadarLayout需要有表示子View數(shù)量的屬性并且該屬性外界可訪問可修改;由于子View的執(zhí)行動(dòng)畫是放縮和透明度漸變同時(shí)進(jìn)行的,所以RadarLayout需要用動(dòng)畫集來組裝各個(gè)動(dòng)畫;由于動(dòng)畫執(zhí)行時(shí)需要知道執(zhí)行時(shí)間所以RadarLayout需要有表示執(zhí)行時(shí)間的屬性并且該屬性外界可訪問可修改;由于RadarLayout的動(dòng)畫效果是子View來執(zhí)行的,在咻一咻頁面是個(gè)圓,所以需要定義子View并畫在屏幕上,而畫在屏幕上需要有畫筆,畫筆需要有顏色,還需要知道畫在哪,所以可定義我們的RadarLayout定義如下所示:

public class RadarLayout extends FrameLayout { 
public static final int INFINITE = 0; 
private static final int DEFAULT_COUNT = 4; 
private static final int DEFAULT_COLOR = Color.rgb(0, 116, 193); 
private static final int DEFAULT_DURATION = 7000; 
private static final int DEFAULT_REPEAT = INFINITE; 
private static final int DEFAULT_STROKE_WIDTH = 2; 
private int mCount; 
private int mDuration; 
private int mRepeat; 
private AnimatorSet mAnimatorSet; 
private Paint mPaint; 
private int mColor; 
private float mRadius; 
private float mCenterX; 
private float mCenterY; 
private int mStrokeWidth; 
private boolean mIsStarted; 
private boolean mUseRing; 
public RadarLayout(Context context) { 
super(context); 
initGlobalparams(); 
} 
public RadarLayout(Context context, AttributeSet attrs) { 
super(context, attrs); 
initGlobalparams(); 
} 
public RadarLayout(Context context, AttributeSet attrs, int defStyleAttr) { 
super(context, attrs, defStyleAttr); 
initGlobalparams(); 
} 
private void initGlobalparams() { 
mColor = DEFAULT_COLOR; 
mCount = DEFAULT_COUNT; 
mDuration = DEFAULT_DURATION; 
mRepeat = DEFAULT_REPEAT; 
mUseRing = false; 
mStrokeWidth = dip2px(DEFAULT_STROKE_WIDTH); 
build(); 
} 
public synchronized void start() { 
if (mAnimatorSet == null || mIsStarted) { 
return; 
} 
mAnimatorSet.start(); 
} 
public synchronized void stop() { 
if (mAnimatorSet == null || !mIsStarted) { 
return; 
} 
mAnimatorSet.end(); 
} 
public synchronized boolean isStarted() { 
return (mAnimatorSet != null && mIsStarted); 
} 
public int getCount() { 
return mCount; 
} 
public int getDuration() { 
return mDuration; 
} 
public void setCount(int count) { 
if (count < 0) { 
throw new IllegalArgumentException("Count cannot be negative"); 
} 
if (count != mCount) { 
mCount = count; 
reset(); 
invalidate(); 
} 
} 
public void setDuration(int millis) { 
if (millis < 0) { 
throw new IllegalArgumentException("Duration cannot be negative"); 
} 
if (millis != mDuration) { 
mDuration = millis; 
reset(); 
invalidate(); 
} 
} 
public void setColor(int color) { 
if (mColor != color) { 
mColor = color; 
reset(); 
invalidate(); 
} 
} 
public void setUseRing(boolean useRing) { 
if (mUseRing != useRing) { 
mUseRing = useRing; 
reset(); 
invalidate(); 
} 
} 
@Override 
public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 
super.onMeasure(widthMeasureSpec, heightMeasureSpec); 
int width = getMeasuredWidth() - getPaddingLeft() - getPaddingRight(); 
int height = getMeasuredHeight() - getPaddingTop() - getPaddingBottom(); 
// 確定圓的圓點(diǎn)坐標(biāo)及半徑 
mCenterX = width * 0.5f; 
mCenterY = height * 0.5f; 
mRadius = Math.min(width, height) * 0.5f; 
} 
private void clear() { 
stop(); 
removeAllViews(); 
} 
private void build() { 
LayoutParams params = new LayoutParams(MATCH_PARENT, MATCH_PARENT); 
int repeatCount = (mRepeat == INFINITE) ? ObjectAnimator.INFINITE : mRepeat; 
List<Animator> animators = new ArrayList<Animator>(); 
for (int index = 0; index < mCount; index++) { 
RadarView radarView = new RadarView(getContext()); 
radarView.setScaleX(0); 
radarView.setScaleY(0); 
radarView.setAlpha(1); 
addView(radarView, index, params); 
// 計(jì)算時(shí)間間隔 
long delay = index * mDuration / mCount; 
// 屬性動(dòng)畫 
animators.add(create(radarView, "scaleX", repeatCount, delay, 0, 1)); 
animators.add(create(radarView, "scaleY", repeatCount, delay, 0, 1)); 
animators.add(create(radarView, "alpha", repeatCount, delay, 1, 0)); 
} 
mAnimatorSet = new AnimatorSet(); 
mAnimatorSet.playTogether(animators); 
mAnimatorSet.setInterpolator(new LinearInterpolator()); 
mAnimatorSet.setDuration(mDuration); 
mAnimatorSet.addListener(mAnimatorListener); 
} 
private ObjectAnimator create(View target, String propertyName, int repeatCount, long delay, float from, float to) { 
ObjectAnimator animator = ObjectAnimator.ofFloat(target, propertyName, from, to); 
animator.setRepeatCount(repeatCount); 
animator.setRepeatMode(ObjectAnimator.RESTART); 
animator.setStartDelay(delay); 
return animator; 
} 
private void reset() { 
boolean isStarted = isStarted(); 
clear(); 
build(); 
if (isStarted) { 
start(); 
} 
} 
private class RadarView extends View { 
public RadarView(Context context) { 
super(context); 
} 
@Override 
protected void onDraw(Canvas canvas) { 
if (null == mPaint) { 
mPaint = new Paint(); 
mPaint.setColor(mColor); 
mPaint.setAntiAlias(true); 
// 注意Style的用法,【STROKE:畫環(huán)】【FILL:畫圓】 
mPaint.setStyle(mUseRing ? Style.STROKE : Style.FILL); 
mPaint.setStrokeWidth(mUseRing ? mStrokeWidth : 0); 
} 
// 畫圓或環(huán) 
canvas.drawCircle(mCenterX, mCenterY, mUseRing ? mRadius - mStrokeWidth : mRadius, mPaint); 
} 
} 
private int dip2px(float dpValue) { 
final float scale = getResources().getDisplayMetrics().density; 
return (int) (dpValue * scale + 0.5f); 
} 
private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() { 
@Override 
public void onAnimationStart(Animator animator) { 
mIsStarted = true; 
} 
@Override 
public void onAnimationEnd(Animator animator) { 
mIsStarted = false; 
} 
@Override 
public void onAnimationCancel(Animator animator) { 
mIsStarted = false; 
} 
@Override 
public void onAnimationRepeat(Animator animator) { 
} 
}; 
}

我們的RadarLayout已經(jīng)完成了,代碼很簡單,相信小伙伴們都看的懂,需要注意屬性mUseRing的含義,當(dāng)mUserRing為true時(shí)表示使用環(huán)形雷達(dá)脈沖,否則使用圓形雷達(dá)脈沖。其次是屬性動(dòng)畫的使用,如果有不明白的請(qǐng)自行查閱,這里就不再多多介紹了。接下來編寫我們的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: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.llew.wb.MainActivity" > 
<View 
android:id="@+id/holder" 
android:layout_width="@dimen/activity_horizontal_margin" 
android:layout_height="10dp" 
android:layout_centerHorizontal="true" /> 
<com.llew.wb.RadarLayout 
android:id="@+id/radarlayout1" 
android:layout_width="match_parent" 
android:layout_height="150dp" 
android:layout_toLeftOf="@id/holder" 
android:background="#bbaacc" > 
</com.llew.wb.RadarLayout> 
<com.llew.wb.RadarLayout 
android:id="@+id/radarlayout2" 
android:layout_width="match_parent" 
android:layout_height="150dp" 
android:layout_toRightOf="@id/holder" 
android:background="#bbaacc" > 
</com.llew.wb.RadarLayout> 
<com.llew.wb.RadarLayout 
android:id="@+id/radarlayout3" 
android:layout_width="match_parent" 
android:layout_height="150dp" 
android:layout_below="@id/radarlayout1" 
android:layout_marginTop="@dimen/activity_horizontal_margin" 
android:layout_toLeftOf="@id/holder" 
android:background="#bbaacc" > 
</com.llew.wb.RadarLayout> 
<com.llew.wb.RadarLayout 
android:id="@+id/radarlayout4" 
android:layout_width="match_parent" 
android:layout_height="150dp" 
android:layout_below="@id/radarlayout1" 
android:layout_marginTop="@dimen/activity_horizontal_margin" 
android:layout_toRightOf="@id/holder" 
android:background="#bbaacc" > 
</com.llew.wb.RadarLayout> 
<Button 
android:layout_width="100dp" 
android:layout_height="wrap_content" 
android:layout_alignParentBottom="true" 
android:layout_centerHorizontal="true" 
android:layout_marginBottom="20dp" 
android:onClick="start" 
android:text="開始" /> 
</RelativeLayout>

在activity_main.xml布局中我們添加了4個(gè)RadarLayout,目的是對(duì)比他們的差異,接下編寫我們的MainActivity,代碼如下:

public class MainActivity extends Activity { 
private RadarLayout layout1; 
private RadarLayout layout2; 
private RadarLayout layout3; 
private RadarLayout layout4; 
@Override 
protected void onCreate(Bundle savedInstanceState) { 
super.onCreate(savedInstanceState); 
setContentView(R.layout.activity_main); 
layout1 = (RadarLayout) findViewById(R.id.radarlayout1); 
layout2 = (RadarLayout) findViewById(R.id.radarlayout2); 
layout2.setUseRing(true); 
layout2.setCount(2); 
layout3 = (RadarLayout) findViewById(R.id.radarlayout3); 
layout3.setUseRing(false); 
layout3.setColor(Color.RED); 
layout4 = (RadarLayout) findViewById(R.id.radarlayout4); 
layout4.setCount(7); 
layout4.setColor(Color.BLUE); 
layout4.setUseRing(true); 
} 
public void start(View view) { 
layout1.start(); 
layout2.start(); 
layout3.start(); 
layout4.start(); 
} 
}

在MainActivity中我們設(shè)置了layout1為默認(rèn)值效果,layout2設(shè)置了使用環(huán)形效果并且設(shè)置了數(shù)量為2個(gè);layout3設(shè)置為使用圓形并設(shè)置圓形的顏色為紅色,layout3我們設(shè)置了使用環(huán)形,設(shè)置了環(huán)形數(shù)量為7個(gè)并設(shè)置顏色給藍(lán)色。當(dāng)點(diǎn)擊了開始按鈕后,我們打開每一個(gè)RadarLayout的動(dòng)畫,運(yùn)行效果如下所示:

運(yùn)行效果看起來還不錯(cuò),基本上實(shí)現(xiàn)了仿支付的咻一咻的雷達(dá)脈沖效果,主要原理就是利用了屬性動(dòng)畫并把這些屬性動(dòng)畫集合起來一塊播放即可。需要注意的是如果想在低版本兼容屬性動(dòng)畫可以使用Jake Wharton大神開源的著名動(dòng)畫兼容庫NineOldAndroids,最后感謝收看(*^__^*) ……

以上所述是小編給大家介紹的Android自定義ViewGroup實(shí)現(xiàn)絢麗的仿支付寶咻一咻雷達(dá)脈沖效果,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!

相關(guān)文章

  • 詳解如何使用Android Studio開發(fā)Gradle插件

    詳解如何使用Android Studio開發(fā)Gradle插件

    這篇文章主要介紹了詳解如何使用Android Studio開發(fā)Gradle插件,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-10-10
  • Flutter進(jìn)階之實(shí)現(xiàn)動(dòng)畫效果(十)

    Flutter進(jìn)階之實(shí)現(xiàn)動(dòng)畫效果(十)

    這篇文章主要為大家詳細(xì)介紹了Flutter進(jìn)階之實(shí)現(xiàn)動(dòng)畫效果的第十篇,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • android使用gesturedetector手勢識(shí)別示例分享

    android使用gesturedetector手勢識(shí)別示例分享

    這篇文章主要介紹了android使用手勢識(shí)別的方法,介紹了單擊觸摸屏觸發(fā)的事件和雙擊事件的使用等方法,大家參考使用吧
    2014-01-01
  • Android SQLite操作之大數(shù)據(jù)處理與同時(shí)讀寫方法

    Android SQLite操作之大數(shù)據(jù)處理與同時(shí)讀寫方法

    這篇文章主要介紹了Android SQLite操作之大數(shù)據(jù)處理與同時(shí)讀寫方法,實(shí)例分析了Android操作SQLite時(shí)基于事務(wù)的數(shù)據(jù)緩存與批量插入技巧,以及同時(shí)讀寫的相關(guān)實(shí)現(xiàn)方法與注意事項(xiàng),需要的朋友可以參考下
    2016-07-07
  • 獲取微信uin的方法

    獲取微信uin的方法

    本篇文章給大家講述了如何最快速的獲取微信uin的方法,對(duì)此有需要的朋友可以學(xué)習(xí)下。
    2018-05-05
  • Android徹底清除APP數(shù)據(jù)的兩種方案總結(jié)

    Android徹底清除APP數(shù)據(jù)的兩種方案總結(jié)

    大家在用Android手機(jī)的時(shí)候肯定都遇到過內(nèi)存剩余空間越來越小的情況,所以下面這篇文章主要給大家介紹了關(guān)于Android徹底清除APP數(shù)據(jù)的兩種方案,需要的朋友可以參考下
    2021-11-11
  • sweet alert dialog 在android studio應(yīng)用問題說明詳解

    sweet alert dialog 在android studio應(yīng)用問題說明詳解

    這篇文章主要介紹了sweet alert dialog 在android studio應(yīng)用問題說明詳解的相關(guān)資料,本文圖文并茂介紹的非常詳細(xì),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-09-09
  • Android 實(shí)現(xiàn)加載大圖片的方法

    Android 實(shí)現(xiàn)加載大圖片的方法

    對(duì)于超大的圖片,如果不縮放的話,容易導(dǎo)致內(nèi)存溢出。而經(jīng)過處理后,無論多大的圖片,都能夠在手機(jī)屏幕上加載出來,不會(huì)導(dǎo)致內(nèi)存溢出。本文將對(duì)Android 加載大圖片的實(shí)現(xiàn)方法進(jìn)行介紹,下面跟著小編一起來看下吧
    2017-04-04
  • Android圖片加載案例分享

    Android圖片加載案例分享

    這篇文章主要為大家分享了Android圖片加載的實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-05-05
  • Android 微信搖一搖功能實(shí)現(xiàn)詳細(xì)介紹

    Android 微信搖一搖功能實(shí)現(xiàn)詳細(xì)介紹

    這篇文章主要介紹了Android 微信搖一搖功能實(shí)現(xiàn)詳細(xì)介紹的相關(guān)資料,并附實(shí)例代碼及實(shí)現(xiàn)微信搖一搖的思路,需要的朋友可以參考下
    2016-11-11

最新評(píng)論

平遥县| 神池县| 通渭县| 田阳县| 福安市| 玉屏| 永康市| 德保县| 福建省| 肃宁县| 稻城县| 江华| 张家港市| 溧阳市| 于都县| 会泽县| 德清县| 禹州市| 达尔| 溆浦县| 安顺市| 尼勒克县| 黄陵县| 汝州市| 九龙坡区| 团风县| 阳高县| 邢台市| 宜君县| 喀什市| 南宁市| 简阳市| 仙居县| 黄大仙区| 房山区| 富阳市| 吉隆县| 易门县| 湘阴县| 龙游县| 高陵县|