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

Android開發(fā)仿映客送禮物效果

 更新時間:2016年09月20日 11:56:27   作者:XK_Captain  
這篇文章主要介紹了Android開發(fā)仿映客送禮物效果的實現(xiàn)代碼,本文介紹的非常詳細(xì),具有參考借鑒價值,感興趣的朋友一起學(xué)習(xí)吧

這里寫鏈接內(nèi)容仿映客送小禮物的特效,順便復(fù)習(xí)一下屬性動畫,話不多說先看效果圖。

效果圖

需求分析

可以看到整個動畫有幾部分組成,那我們就把每個部分拆分出來各個擊破。

1.要顯示那些內(nèi)容以及內(nèi)容間的位置關(guān)系?

可以看到我們要顯示用戶頭像,昵稱,禮物圖標(biāo)以及數(shù)量。所以這里我選擇用FrameLayout來作為根布局。

2.需要哪些動畫以及動畫的執(zhí)行順序?

a.首先是整體從左到右飛入并有一個回彈(translationX + OvershootInterpolator)

b.然后是禮物從左到右飛入而且是一個帶減速效果的(translationX + DecelerateInterpolator)

c.禮物數(shù)量依次累加同時伴隨著縮放(scale+repeat)

d.后面的粒子效果(幀動畫)

e.整體向上平移并且逐漸消失(translationY + alpha)

3.送禮的區(qū)域有兩塊(A,B),如何分配?

因為用戶送禮的數(shù)量不固定,所以動畫持續(xù)的時間也不一定。但是我們希望這兩塊區(qū)域能得到充分的使用,即我們需要一個隊列存放這些禮物實例,A和B誰空閑,就分配給誰處理。

4.以上所有內(nèi)容是否使用原生的空間就能實現(xiàn)?

正如上面的分析,我們有時操作整體,有時操作局部。這時我們最好能自定義一個布局繼承FrameLayout,其實也就是封裝一層,這樣我們就可以很好的控制整個布局。除此之外,還有我們注意到禮物數(shù)量是帶描邊的,貌似需要我們自定義實現(xiàn)了。

功能實現(xiàn)

需求分析完了,接下來我們說說功能的實現(xiàn)。

首先來打我們的整體布局。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:id="@+id/animation_person_rl"
android:layout_width="wrap_content"
android:layout_height="39dp"
android:layout_gravity="left"
android:layout_marginTop="22dp"
android:background="@drawable/bg_giftlayout">
<ImageView
android:id="@+id/gift_userheader_iv"
android:layout_width="39dp"
android:layout_height="39dp"
android:layout_margin="3dp"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:src="@mipmap/ember" />
<TextView
android:id="@+id/gift_usernickname_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="6dp"
android:layout_marginTop="4dp"
android:layout_toRightOf="@id/gift_userheader_iv"
android:text="庫日天"
android:textColor="#ffffff"
android:textSize="12sp" />
<TextView
android:id="@+id/gift_usersign_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/gift_usernickname_tv"
android:layout_below="@id/gift_usernickname_tv"
android:layout_marginTop="4dp"
android:ellipsize="end"
android:text="送一個超級無敵"
android:textColor="#ffea79"
android:textSize="11sp" />
<ImageView
android:id="@+id/animation_gift"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/gift_usersign_tv"
android:background="@mipmap/diamond2x" />
</RelativeLayout>
<ImageView
android:id="@+id/animation_light"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="120dp"
android:src="@drawable/light_star_anim" />
<com.example.work.animationdemo.StrokeTextView
android:id="@+id/animation_num"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="185dp"
android:layout_marginTop="12dp"
android:text="x 1"
android:textColor="#0076ff"
android:textSize="24sp"
app:innnerColor="#ffffff"
app:outerColor="#0076ff" />
</FrameLayout>

這里比較簡單不多說了,重點看下StrokeTextView,帶描邊的textview,其實就是重寫了ondraw方法先繪制外層,在繪制內(nèi)層。

@Override
protected void onDraw(Canvas canvas) {
if (m_bDrawSideLine) {
// 描外層
setTextColorUseReflection(mOuterColor);
m_TextPaint.setStrokeWidth(5);
m_TextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
super.onDraw(canvas);
// 描內(nèi)層,恢復(fù)原先的畫筆
setTextColorUseReflection(mInnerColor);
m_TextPaint.setStrokeWidth(0);
m_TextPaint.setStyle(Paint.Style.FILL_AND_STROKE);
}
super.onDraw(canvas);
}
/**
* 使用反射的方法進(jìn)行字體顏色的設(shè)置
* @param color
*/
private void setTextColorUseReflection(int color) {
Field textColorField;
try {
textColorField = TextView.class.getDeclaredField("mCurTextColor");
textColorField.setAccessible(true);
textColorField.set(this, color);
textColorField.setAccessible(false);
} catch (NoSuchFieldException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
m_TextPaint.setColor(color);
}

定義禮物的實體類

public class GiftSendModel {
private int giftCount;
private String userAvatarRes;
private String nickname;
private String sig;
private int giftRes;
private String gift_id;
private int star;
public GiftSendModel(int giftCount) {
this.giftCount = giftCount;
}
public int getGiftCount() {
return giftCount;
}
public void setGiftCount(int giftCount) {
this.giftCount = giftCount;
}
......

封裝整體布局

public class GiftFrameLayout extends FrameLayout {
private LayoutInflater mInflater;
RelativeLayout anim_rl;
ImageView anim_gift, anim_light, anim_header;
TextView anim_nickname, anim_sign;
StrokeTextView anim_num;
/**
* 禮物數(shù)量的起始值
*/
int starNum = 1;
int repeatCount = 0;
private boolean isShowing = false;
public GiftFrameLayout(Context context) {
this(context, null);
}
public GiftFrameLayout(Context context, AttributeSet attrs) {
super(context, attrs);
mInflater = LayoutInflater.from(context);
initView();
}
private void initView() {
View view = mInflater.inflate(R.layout.animation, this, false);
anim_rl = (RelativeLayout) view.findViewById(R.id.animation_person_rl);
anim_gift = (ImageView) view.findViewById(R.id.animation_gift);
anim_light = (ImageView) view.findViewById(R.id.animation_light);
anim_num = (StrokeTextView) view.findViewById(R.id.animation_num);
anim_header = (ImageView) view.findViewById(R.id.gift_userheader_iv);
anim_nickname = (TextView) view.findViewById(R.id.gift_usernickname_tv);
anim_sign = (TextView) view.findViewById(R.id.gift_usersign_tv);
this.addView(view);
}
public void hideView() {
anim_gift.setVisibility(INVISIBLE);
anim_light.setVisibility(INVISIBLE);
anim_num.setVisibility(INVISIBLE);
}
public void setModel(GiftSendModel model){
if (0!=model.getGiftCount()) {
this.repeatCount = model.getGiftCount();
}
if (!TextUtils.isEmpty(model.getNickname())) {
anim_nickname.setText(model.getNickname());
}
if (!TextUtils.isEmpty(model.getSig())) {
anim_sign.setText(model.getSig());
}
}
public boolean isShowing(){
return isShowing;
}
public AnimatorSet startAnimation( final int repeatCount) {
hideView();
//布局飛入
ObjectAnimator flyFromLtoR = GiftAnimationUtil.createFlyFromLtoR(anim_rl, -getWidth(), 0, 400,new OvershootInterpolator());
flyFromLtoR.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
super.onAnimationStart(animation);
GiftFrameLayout.this.setVisibility(View.VISIBLE);
GiftFrameLayout.this.setAlpha(1f);
isShowing = true;
anim_num.setText("x " + 1);
Log.i("TAG", "flyFromLtoR A start");
}
});
//禮物飛入
ObjectAnimator flyFromLtoR2 = GiftAnimationUtil.createFlyFromLtoR(anim_gift, -getWidth(), 0, 400,new DecelerateInterpolator());
flyFromLtoR2.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
anim_gift.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animator animation) {
GiftAnimationUtil.startAnimationDrawable(anim_light);
anim_num.setVisibility(View.VISIBLE);
}
});
//數(shù)量增加
ObjectAnimator scaleGiftNum = GiftAnimationUtil.scaleGiftNum(anim_num, repeatCount);
scaleGiftNum.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationRepeat(Animator animation) {
anim_num.setText("x " + (++starNum));
}
});
//向上漸變消失
ObjectAnimator fadeAnimator = GiftAnimationUtil.createFadeAnimator(GiftFrameLayout.this, 0, -100, 300, 400);
fadeAnimator.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
GiftFrameLayout.this.setVisibility(View.INVISIBLE);
}
});
// 復(fù)原
ObjectAnimator fadeAnimator2 = GiftAnimationUtil.createFadeAnimator(GiftFrameLayout.this, 100, 0, 20, 0);
AnimatorSet animatorSet = GiftAnimationUtil.startAnimation(flyFromLtoR, flyFromLtoR2, scaleGiftNum, fadeAnimator, fadeAnimator2);
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
starNum = 1;
isShowing = false;
}
});
return animatorSet;

我們將所有的動畫方法都寫到了GiftAnimationUtil中便于管理

public class GiftAnimationUtil {
/**
* @param target
* @param star 動畫起始坐標(biāo)
* @param end 動畫終止坐標(biāo)
* @param duration 持續(xù)時間
* @return
* 創(chuàng)建一個從左到右的飛入動畫
* 禮物飛入動畫
*/
public static ObjectAnimator createFlyFromLtoR(final View target, float star, float end, int duration, TimeInterpolator interpolator) {
//1.個人信息先飛出來
ObjectAnimator anim1 = ObjectAnimator.ofFloat(target, "translationX",
star, end);
anim1.setInterpolator(interpolator);
anim1.setDuration(duration);
return anim1;
}
/**
* @param target
* @return
* 播放幀動畫
*/
public static AnimationDrawable startAnimationDrawable(ImageView target){
AnimationDrawable animationDrawable = (AnimationDrawable) target.getDrawable();
if(animationDrawable!=null) {
target.setVisibility(View.VISIBLE);
animationDrawable.start();
}
return animationDrawable;
}
/**
* @param target
* @param drawable
* 設(shè)置幀動畫
*/
public static void setAnimationDrawable(ImageView target, AnimationDrawable drawable){
target.setBackground(drawable);
}
/**
* @param target
* @param num
* @return
* 送禮數(shù)字變化
*/
public static ObjectAnimator scaleGiftNum(final TextView target , int num){
PropertyValuesHolder anim4 = PropertyValuesHolder.ofFloat("scaleX",
1.7f, 0.8f,1f);
PropertyValuesHolder anim5 = PropertyValuesHolder.ofFloat("scaleY",
1.7f, 0.8f,1f);
PropertyValuesHolder anim6 = PropertyValuesHolder.ofFloat("alpha",
1.0f, 0f,1f);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(target, anim4, anim5, anim6).setDuration(480);
animator.setRepeatCount(num);
return animator;
}
/**
* @param target
* @param star
* @param end
* @param duration
* @param startDelay
* @return
* 向上飛 淡出
*/
public static ObjectAnimator createFadeAnimator(final View target, float star, float end, int duration, int startDelay){
PropertyValuesHolder translationY = PropertyValuesHolder.ofFloat("translationY", star,end);
PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", 1.0f,0f);
ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(target, translationY, alpha);
animator.setStartDelay(startDelay);
animator.setDuration(duration);
return animator;
}
/**
* @param animators
* @return
* 按順序播放動畫
*/
public static AnimatorSet startAnimation(ObjectAnimator animator1, ObjectAnimator animator2, ObjectAnimator animator3, ObjectAnimator animator4, ObjectAnimator animator5){
AnimatorSet animSet = new AnimatorSet();
// animSet.playSequentially(animators);
animSet.play(animator1).before(animator2);
animSet.play(animator3).after(animator2);
animSet.play(animator4).after(animator3);
animSet.play(animator5).after(animator4);
animSet.start();
return animSet;
}
}

所有的動畫效果均是用屬性動畫完成,其中不僅有單個的動畫,還有組合動畫。屬性動畫用起來方面而且功能十分強(qiáng)大!

最后看下MainActivity中的實現(xiàn)

public class MainActivity extends AppCompatActivity {
private GiftFrameLayout giftFrameLayout1;
private GiftFrameLayout giftFrameLayout2;
List<GiftSendModel> giftSendModelList = new ArrayList<GiftSendModel>();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
giftFrameLayout1 = (GiftFrameLayout) findViewById(R.id.gift_layout1);
giftFrameLayout2 = (GiftFrameLayout) findViewById(R.id.gift_layout2);
findViewById(R.id.action).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
starGiftAnimation(createGiftSendModel());
}
});
}
private GiftSendModel createGiftSendModel(){
return new GiftSendModel((int)(Math.random()*10));
}
private void starGiftAnimation(GiftSendModel model){
if (!giftFrameLayout1.isShowing()) {
sendGiftAnimation(giftFrameLayout1,model);
}else if(!giftFrameLayout2.isShowing()){
sendGiftAnimation(giftFrameLayout2,model);
}else{
giftSendModelList.add(model);
}
}
private void sendGiftAnimation(final GiftFrameLayout view, GiftSendModel model){
view.setModel(model);
AnimatorSet animatorSet = view.startAnimation(model.getGiftCount());
animatorSet.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
synchronized (giftSendModelList) {
if (giftSendModelList.size() > 0) {
view.startAnimation(giftSendModelList.get(giftSendModelList.size() - 1).getGiftCount());
giftSendModelList.remove(giftSendModelList.size() - 1);
}
}
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}

其中關(guān)于緩存區(qū)的策略大家可以根據(jù)實際需求進(jìn)行定制。

以上所述是小編給大家介紹的Android開發(fā)仿映客送禮物效果,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!

相關(guān)文章

  • Android?懸浮窗開發(fā)示例((動態(tài)權(quán)限請求?|?前臺服務(wù)和通知?|?懸浮窗創(chuàng)建?)

    Android?懸浮窗開發(fā)示例((動態(tài)權(quán)限請求?|?前臺服務(wù)和通知?|?懸浮窗創(chuàng)建?)

    本文介紹了Android懸浮窗的實現(xiàn)效果,包括動態(tài)權(quán)限請求、前臺服務(wù)和通知的使用,懸浮窗權(quán)限需要動態(tài)申請并引導(dǎo)用戶手動開啟,前臺服務(wù)用于保證懸浮窗的持續(xù)存活,支持Android不同版本的兼容性,文章還提供了啟動前臺服務(wù)、創(chuàng)建通知和懸浮窗的代碼示例,感興趣的朋友一起看看吧
    2025-02-02
  • 解析Android框架之Volley源碼

    解析Android框架之Volley源碼

    我們知道Volley是在2013年Google I/O大會上推出了一個新的網(wǎng)絡(luò)通信框架,他的設(shè)計目的就是為了那些請求數(shù)據(jù)量不是特別大,但是又是特別頻繁的網(wǎng)絡(luò)操作非常適合。但是對于數(shù)據(jù)量較大的請求,比如說下載一個較大的文件,Volley可能相比于其他的框架,就有點不足了。
    2021-06-06
  • Android實現(xiàn)歌詞滾動效果

    Android實現(xiàn)歌詞滾動效果

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)歌詞滾動效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-11-11
  • Android Activity 橫豎屏切換的生命周期

    Android Activity 橫豎屏切換的生命周期

    這篇文章主要介紹了Android Activity 橫豎屏切換的生命周期的相關(guān)資料,需要的朋友可以參考下
    2016-04-04
  • Android實現(xiàn)無限循環(huán)滾動彈幕的代碼示例

    Android實現(xiàn)無限循環(huán)滾動彈幕的代碼示例

    這篇文章主要介紹了android實現(xiàn)無限循環(huán)滾動的彈幕
    ,文中通過代碼示例講解的非常詳細(xì),對大家實現(xiàn)循環(huán)彈幕有一定的幫助,需要的朋友可以參考下
    2024-08-08
  • Android實現(xiàn)視頻的畫中畫功能

    Android實現(xiàn)視頻的畫中畫功能

    手機(jī)觀看視頻的時候,有些工作需要溝通,或者參與搶購活動,同時為了不錯過視頻精彩片段,會選擇畫中畫模式,這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)視頻的畫中畫功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • Android studio 快捷鍵大全

    Android studio 快捷鍵大全

    android studio使用教程,主要為大家介紹的是android studio快捷鍵,如果我們掌握了一些常用快捷鍵,那么在使用android studio的過程中會達(dá)到事半功倍的效果哦
    2016-01-01
  • android 實現(xiàn)在照片上繪制涂鴉的方法

    android 實現(xiàn)在照片上繪制涂鴉的方法

    今天小編就為大家分享一篇android 實現(xiàn)在照片上繪制涂鴉的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-10-10
  • Android Studio實現(xiàn)簡單的QQ登錄界面的示例代碼

    Android Studio實現(xiàn)簡單的QQ登錄界面的示例代碼

    這篇文章主要介紹了Android Studio實現(xiàn)簡單的QQ登錄界面的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06
  • Android實現(xiàn)掃雷小游戲

    Android實現(xiàn)掃雷小游戲

    這篇文章主要為大家詳細(xì)介紹了Android實現(xiàn)掃雷小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-11-11

最新評論

香河县| 新建县| 扎兰屯市| 天柱县| 加查县| 阆中市| 龙山县| 禹城市| 五常市| 绥棱县| 翼城县| 定日县| 沂水县| 潞城市| 犍为县| 光泽县| 东辽县| 城固县| 金门县| 浮山县| 炉霍县| 南京市| 安龙县| 翁牛特旗| 左贡县| 桦川县| 攀枝花市| 呼玛县| 桂东县| 尼勒克县| 筠连县| 榆社县| 梓潼县| 南投县| 宣恩县| 大荔县| 泰来县| 德州市| 清镇市| 城固县| 和静县|