<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Android仿《最美有物》笑臉點贊效果

          共 6259字,需瀏覽 13分鐘

           ·

          2021-05-18 18:33


          繼最美有物之后,又在餓了么上看到了類似的控件。果然需求這個東西是做不完的,以為功能做好就OK了嗎,不要停,這里還差一個玩出花來的點贊效果!

          直接上動圖,看看兩家的實現(xiàn)效果:


          最美有物




          餓了么



          這樣可愛的點贊特效,不得不給個好評啊, 有沒有!


          當(dāng)然光點贊好評是不行的,今天得自己動手?jǐn)]一個這樣的笑臉點贊控件。



          主要流程和實現(xiàn)分析


          以最美有物的點贊效果為模板(相較餓了么更豐富),從整體的操作流程來分析:


          點擊觸發(fā) :


          1. 顏色切換(選中黃,未選中白)


          2. 按比例拉伸(兩個笑臉同時升高,顯示點贊比例的高度)


          3. 展示數(shù)據(jù)文本(百分比數(shù)據(jù)顯示)


          4. 顯示選中部分的笑臉動畫(這一步與3文本數(shù)據(jù)同時進行,在拉伸至最高處停留后)


          5. 縮回至原始大小,保持選中狀態(tài)


          通過這個流程的分析,我們可以把主要的功能點劃分為以下兩類:


          1.動畫類 :臉部動畫,拉伸動畫


          2.控制類: 顏色切換,數(shù)據(jù)顯示,拉伸比例


          在自定義View的過程中,動畫特效是最吸引人,也是最復(fù)雜的部分,雖然現(xiàn)在有高效炫酷的矢量動畫庫供我們選擇, 但是基礎(chǔ)動畫的組合也是相當(dāng)有用的,重點是發(fā)揮想象力。


          其中,臉部動畫在解壓apk后找到相關(guān)圖片,不出所料是個幀動畫。


          而主要的難點就在于如何進行拉伸操作。對于將一個圓形從中間拉伸成長條...


          最開始想到的方案是拼接圖形,即通過圓形 + 矩形 + 圓形的方式疊加這個控件。通過調(diào)節(jié)中間矩形的高度,來控制拉伸操作。但是這種方式結(jié)構(gòu)略復(fù)雜,需要在一小塊地方擺上三個圖形,還要帶上最外層的笑臉動畫,還沒寫代碼就感覺應(yīng)該是性能低下的方案,另外一個致命的問題就是,不能有描邊!大家可以參考餓了么的實現(xiàn)效果,在有描邊的情況下,形狀拼接的方案明顯不可行。遂放棄。


          而最終采用的則是使用圓角矩形作為外層Layout背景,通過控制內(nèi)部笑臉的marginBottom,來動態(tài)的調(diào)節(jié)Layout的高度。這樣,即可以保持笑臉始終處于控件的上部,同時也能控制相對簡單的結(jié)構(gòu)。



          拉伸操作的實現(xiàn)


          首先我們先簡單的模擬下通過marginBottom控制拉伸的效果。

          在布局里設(shè)置一個LinearLayout ,里面只有一個ImageView。用一個seekBar來模擬效果。

          Layout:

           <LinearLayout        android:id="@+id/backGround"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:padding="10dp"        android:background="@drawable/yellow_background"        android:layout_above="@+id/seekBar"        android:layout_centerHorizontal="true">
          <ImageView android:id="@+id/smileFace" android:layout_width="40dp" android:layout_height="40dp" android:src="@drawable/like_1"/> </LinearLayout>


          這里L(fēng)inearlayout中設(shè)置了一個背景,是自定義的圓角矩形shape,通過調(diào)大圓角,使其顯示為一個正圓。


          Activity:

                      @Override            public void onProgressChanged(SeekBar seekBar, int i, boolean b) {                LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)smileFace.getLayoutParams();                layoutParams.bottomMargin = i*3;                smileFace.setLayoutParams(layoutParams);            }


          通過獲取SmileFace的LayoutParams,通過Seekbar設(shè)置其下邊距bottomMargin,來控制高度。


          效果如下所示:



          這樣拉伸的原理就很清楚了。

          我們需要在自定義控件中完成上述操作,并用屬性動畫替換掉seekBar。


          自定義控件的封裝


          子控件的布局


          考慮到實現(xiàn)目標(biāo)里有兩個并排的笑臉控件,這里采用繼承LinearLayout的方式,可以把兩個控件及中間的分割線直接擺放進去。


          首先初始化兩個臉部動畫的ImageView及動畫資源,以及兩個顯示點贊比例的數(shù)字及文本的TextView。


          在初始化的時候設(shè)置好相關(guān)參數(shù),提取出默認(rèn)值并提供方法設(shè)置相關(guān)參數(shù)。然后把百分比,文字,包含笑臉的Layout,都添加到另外一個Linearlayout中,然后再將喜歡不喜歡添加到當(dāng)前自定義控件中。

                  //初始化圖片        imageLike = new ImageView(getContext());        //添加動畫資源  獲得幀動畫        imageLike.setBackgroundResource(R.drawable.animation_like);        animLike = (AnimationDrawable) imageLike.getBackground();        //初始化文字        likeNum = new TextView(getContext());        likeNum.setText(like + "%");        likeNum.setTextColor(defalutTextColor);        TextPaint likeNumPaint = likeNum.getPaint();        likeNumPaint.setFakeBoldText(true);        likeNum.setTextSize(20f);        likeText = new TextView(getContext());        likeText.setText(defaultLike);        likeText.setTextColor(defalutTextColor);
          .....
          disAll.addView(disNum, params); disAll.addView(disText, params); disAll.addView(disBack, params); likeAll.addView(likeNum, params); likeAll.addView(likeText, params);        likeAll.addView(likeBack, params);


          這里同時還要注意隱藏文字,以及默認(rèn)設(shè)置為未選中狀態(tài)。這一段代碼雖然挺多,其實也只是在View中做了xml里的事情,了解了整體結(jié)構(gòu)后其實非常簡單,實際上直接寫好XML再加載也是沒問題的。


          整體流程和動畫分析


          控件的事件其實只有兩個點擊事件,需要注意的是動畫流程的控制。
          1.拉伸屬性動畫  》 2.表情幀動畫 》3.與2同時進行的平移動畫


          直接在控件設(shè)置onClickListener。點擊開始執(zhí)行拉伸動畫。并在動畫開始后限制點擊事件,流程結(jié)束后釋放。避免重復(fù)點擊動畫錯亂。同時給屬性動畫設(shè)置監(jiān)聽,在拉伸執(zhí)行完畢后,繼續(xù)執(zhí)行面部的動畫。


          通過屬性動畫,將喜歡不喜歡的數(shù)字比例設(shè)置為兩個笑臉的bottomMargin,這里由于Max是使用兩個數(shù)字和,顯示的高度會依據(jù)數(shù)字的大小有差別,也可以設(shè)置為一個固定值,完全暗戰(zhàn)比例來顯示高度,這個可以依據(jù)自己的數(shù)據(jù)源和需求修改。由于在屬性動畫中同時設(shè)置兩個高度,所以需要通過判斷限制高度,當(dāng)前magrin與達到數(shù)據(jù)要求時停止,從而有比例低的一方會停止拉伸。


          拉伸的屬性動畫,與之對應(yīng)還有一個縮回的動畫,如果有需要還可以加上插值器,優(yōu)化彈起的效果。

              //背景伸展動畫    public void animBack() {        //動畫執(zhí)行中不能點擊        imageDis.setClickable(false);        imageLike.setClickable(false);
          final int max = Math.max(like * 4, disLike * 4); animatorBack = ValueAnimator.ofInt(5, max); animatorBack.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int magrin = (int) animation.getAnimatedValue(); LayoutParams paramsLike = (LayoutParams) imageLike.getLayoutParams(); paramsLike.bottomMargin = magrin;
          if (magrin <= like * 4) { imageLike.setLayoutParams(paramsLike); } if (magrin <= disLike * 4) { imageDis.setLayoutParams(paramsLike); } } }); isClose = false; animatorBack.addListener(this); animatorBack.setDuration(500); animatorBack.start(); }


          拉伸動畫結(jié)束后,幀動畫與平移動畫共同構(gòu)成了面部的表情動畫,通過補間動畫的配合使面部表情更加生動。同時也是用補間動畫的結(jié)束監(jiān)聽來繼續(xù)執(zhí)行動畫恢復(fù)原始狀態(tài)。下圖的animLike為幀動畫,objectX,Y為對應(yīng)軸的平移動畫。


          拉伸和恢復(fù)動畫的結(jié)束監(jiān)聽,通過isClose區(qū)分.以及平移動畫。

              @Override    public void onAnimationEnd(Animator animation) {        //重置幀動畫        animDis.stop();        animLike.stop();
          //關(guān)閉時不執(zhí)行幀動畫 if (isClose) { //收回后可點擊 imageDis.setClickable(true); imageLike.setClickable(true); //隱藏文字 setVisibities(GONE); //恢復(fù)透明 setBackgroundColor(Color.TRANSPARENT); return; } isClose = true;
          if (type == 0) { animLike.start(); objectY(imageLike); } else { animDis.start(); objectX(imageDis); } }
          public void objectY(View view) { ObjectAnimator animator = ObjectAnimator.ofFloat(view, "translationY", -10.0f, 0.0f, 10.0f, 0.0f, -10.0f, 0.0f, 10.0f, 0); animator.setRepeatMode(ObjectAnimator.RESTART); //animator.setRepeatCount(1); animator.setDuration(1500); animator.start(); animator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { setBackUp(); //執(zhí)行回彈動畫 } }); }


          最終效果


          完整的動畫流程實現(xiàn)后,我們的控件就基本完成了。在XML中直接使用,并使用setNum設(shè)置數(shù)字,基本實現(xiàn)了最美有物的點贊控件效果,簡單的擼了一遍。看下最終效果圖吧。

                  smileView = (SmileView) findViewById(R.id.smileView);        smileView.setNum(60,40);



          源碼地址:

          https://github.com/zenglingchao/SmileView


          到這里就結(jié)束啦。

          瀏覽 61
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  黄色片网站视频看免费在线 | 国产AV网 | 天天干天天艹天天日 | 色婷婷在线视频精品免费 | 国产精品伊人 |