Android 自定義View 點贊效果

咱們的態度是:天天進步一點點,理想終會被實現。android

前言
週一又到了,是否是感受一個週末還沒過咋個都沒了呢?既來之則安之,咱們仍是來學習點有用的,因爲以前無心間看到了一個點讚的效果,感受多麼高大上的,因此想着本身也來實現一下。所以有了此文,若是文中有錯還望各位小夥伴指出出來,自定義View的大佬能夠跳過了,(^__^) 嘻嘻……git

咱們仍是先看看實現效果:github

接下來咱們看看實現方法。canvas

點贊效果實現
1.分析怎麼實現微信

分析:ide

咱們能夠將這個點贊效果能夠分爲兩個部分:佈局

點擊部分
咱們能夠經過attrs自定義的屬性,拿到圖片的Drawable,經過調用drawable.draw(canvas)方法直接畫出來。post

上方顯示的動畫部分
第二部分最開始我想到的是直接在上方畫一個TextView,而後設置屬性動畫
達到咱們的效果,後來思考這種效果最好不增長自身控件的大小,假如在上方直接添加TextView那麼必然怎麼整個控件的高度,不少這種點讚的效果是放在列表中,高度有限。因此我最後想的是使用PopupWindow來實現,而後設置屬性動畫。學習

自定義View部分
咱們須要定義的屬性有:動畫

<?xml version="1.0" encoding="utf-8"?>
<resources>
   <declare-styleable name="AgreeView">
       <!--動畫移動最終距離-->
       <attr name="distance" format="integer"/>
       <!--動畫起始位置-->
       <attr name="from_y" format="integer"/>
       <!--動畫開始透明度-->
       <attr name="from_alpha" format="float"/>
       <!--動畫結束透明度-->
       <attr name="to_alpha" format="float"/>
       <!--持續時間-->
       <attr name="duration" format="integer"/>
       <!--動畫顯示的文字-->
       <attr name="text" format="string"/>
       <!--動畫文字大小-->
       <attr name="text_size" format="integer"/>
       <!--動畫顏色-->
       <attr name="text_color" format="color"/>
       <!--點贊圖片-->
       <attr name="img" format="reference"/>
       <!--動畫圖片-->
       <attr name="animation_img" format="reference"/>
       <!--動畫選擇是圖片仍是文字-->
       <attr name="animation" format="enum">
           <enum name="text" value="0"/>
           <enum name="img" value="1"/>
       </attr>
   </declare-styleable>
</resources>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
2.咱們在構造方法中獲取對應屬性,而後初始化PopupWidow:

/**
    * 初始化popupWindow
    */
   private void initPopupWindow() {
       mPopupWindow = new PopupWindow();
       //PopupWindow建立相對佈局
       RelativeLayout layout = new RelativeLayout(mContext);
       //佈局參數
       RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
               ViewGroup.LayoutParams.WRAP_CONTENT);
       layoutParams.addRule(RelativeLayout.CENTER_HORIZONTAL);
       layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
       tvAnimation = new AppCompatTextView(mContext);
       tvAnimation.setIncludeFontPadding(false);
       tvAnimation.setTextSize(TypedValue.COMPLEX_UNIT_DIP, text_size);
       tvAnimation.setTextColor(text_color);
       if (animationMode == ANIMATION_MODE_TEXT) {
           tvAnimation.setText(text);
       } else {
           tvAnimation.setText("");
           tvAnimation.setBackgroundDrawable(animalDrawable);
       }
       tvAnimation.setLayoutParams(layoutParams);
       layout.addView(tvAnimation);
       mPopupWindow.setContentView(layout);

       //量測咱們的動畫的寬高
       int w = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
       int h = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
       tvAnimation.measure(w, h);
       mPopupWindow.setWidth(tvAnimation.getMeasuredWidth());
       Log.e(TAG, "distance==== " + distance);
       mPopupWindow.setHeight(distance + tvAnimation.getMeasuredHeight());
       mPopupWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
       mPopupWindow.setFocusable(false);
       mPopupWindow.setTouchable(false);
       mPopupWindow.setOutsideTouchable(false);
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
這裏面要注意的是咱們要計算PopupWidow的高度和寬度,咱們將 RelativeLayout 做爲ViewGroup,用 AppCompatTextView做爲動畫控件,若是是圖片則直接設置背景圖片。

3.設置咱們點贊View上方的動畫:

/**
    * 動畫組合
    */
   private void setPopAnimation() {
       mAnimationSet = new AnimationSet(true);
       TranslateAnimation translateAnim = new TranslateAnimation(0, 0, from_y, -to_y);
       AlphaAnimation alphaAnim = new AlphaAnimation(from_alpha, to_alpha);
       mAnimationSet.addAnimation(translateAnim);
       mAnimationSet.addAnimation(alphaAnim);
       mAnimationSet.setDuration(duration);
       mAnimationSet.setAnimationListener(new Animation.AnimationListener() {
           @Override
           public void onAnimationStart(Animation animation) {
           }

           @Override
           public void onAnimationEnd(Animation animation) {
               if (mPopupWindow != null && mPopupWindow.isShowing()) {
                   new Handler().post(new Runnable() {
                       @Override
                       public void run() {
                           mPopupWindow.dismiss();
                       }
                   });
               }
           }

           @Override
           public void onAnimationRepeat(Animation animation) {
           }
       });
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
4.設置咱們點贊圖片的動畫效果:

/**
    * 縮放動畫
    */
   private void setScaleAnimation() {
       ObjectAnimator scaleX = ObjectAnimator.ofFloat(this, "scaleX", 1f, 0.8f, 1.2f, 1f);
       ObjectAnimator scaleY = ObjectAnimator.ofFloat(this, "scaleY", 1f, 0.8f, 1.2f, 1f);
       scaleX.setDuration(duration);
       scaleY.setDuration(duration);
       scaleX.setInterpolator(new AccelerateDecelerateInterpolator());
       scaleY.setInterpolator(new AccelerateDecelerateInterpolator());
       AnimatorSet animatorSet = new AnimatorSet();
       animatorSet.play(scaleX).with(scaleY);
       animatorSet.start();
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
5.咱們onDraw()方法以前咱們還須要量測一下咱們控件的大小,假如咱們不量測寬高,咱們在XML中引用咱們的控件咱們本身設定一個寬高,比實際的圖片的寬高要大,最終顯示的圖片仍是原圖片大小,不會按照XML中設定的值放大或者縮小。

/**
    * 量測點擊控件的大小
    *
    * @param widthMeasureSpec
    * @param heightMeasureSpec
    */
   @Override
   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
       super.onMeasure(widthMeasureSpec, heightMeasureSpec);
       int width;
       int height;
       int w_mode = MeasureSpec.getMode(widthMeasureSpec);
       int w_size = MeasureSpec.getSize(widthMeasureSpec);

       int h_mode = MeasureSpec.getMode(heightMeasureSpec);
       int h_size = MeasureSpec.getSize(heightMeasureSpec);

       if (w_mode == MeasureSpec.AT_MOST || w_mode == MeasureSpec.UNSPECIFIED) {
           width = agreeDrawable.getIntrinsicWidth();
       } else {
           width = w_size;
       }

       if (h_mode == MeasureSpec.AT_MOST || h_mode == MeasureSpec.UNSPECIFIED) {
           height = agreeDrawable.getIntrinsicHeight();
       } else {
           height = h_size;
       }
       setMeasuredDimension(width, height);

       //根據量測的寬高,設置咱們畫的Drawable的大小
       @SuppressLint("DrawAllocation")
       Rect rect = new Rect(0, 0, width, height);
       agreeDrawable.setBounds(rect);
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
6.畫咱們的圖片:

@Override
   protected void onDraw(Canvas canvas) {
       //將咱們的Drawable畫到畫布
       agreeDrawable.draw(canvas);
   }
1
2
3
4
5
7.當咱們點擊圖片的時候觸發動畫:

@Override
   public void onClick(View v) {
       if (mPopupWindow != null && !mPopupWindow.isShowing()) {
           int offsetY = -getHeight() - mPopupWindow.getHeight();
           mPopupWindow.showAsDropDown(this, getWidth() / 2 - mPopupWindow.getWidth() / 2, offsetY);
           mPopupWindow.update();
           if (mAnimationSet == null) {
               setPopAnimation();
           }
           tvAnimation.startAnimation(mAnimationSet);
           setScaleAnimation();
           //外部點擊事件
           if (clickListener != null) {
               clickListener.onAgreeClick(v);
           }
       }
   }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
這裏自定義了一個View的點擊事件方法,供外部調用。

MainActivity中添加自定義控件和屬性

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   xmlns:agreeview="http://schemas.android.com/apk/res-auto"
   xmlns:tools="http://schemas.android.com/tools"
   android:layout_width="match_parent"
   android:layout_height="match_parent"
   tools:context="com.lt.agreeview.MainActivity">

   <com.lt.agreeview.AgreeView
       android:id="@+id/agreeView4"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       android:layout_marginBottom="8dp"
       android:layout_marginTop="8dp"
       agreeview:animation="text"
       agreeview:animation_img="@drawable/ic_favorite_black_24dp"
       agreeview:distance="100"
       agreeview:from_y="60"
       agreeview:layout_constraintBottom_toBottomOf="parent"
       agreeview:layout_constraintEnd_toStartOf="@+id/agreeView3"
       agreeview:layout_constraintHorizontal_bias="0.5"
       agreeview:layout_constraintStart_toStartOf="parent"
       agreeview:layout_constraintTop_toTopOf="parent"
       agreeview:text="我喜歡你+1"
       agreeview:text_color="@color/text_color">
   </com.lt.agreeview.AgreeView>

   <com.lt.agreeview.AgreeView
       android:id="@+id/agreeView3"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"
       agreeview:animation="img"
       agreeview:animation_img="@drawable/ic_grade_black_24dp"
       agreeview:distance="100"
       agreeview:from_y="60"
       agreeview:layout_constraintBottom_toBottomOf="@+id/agreeView4"
       agreeview:layout_constraintEnd_toEndOf="parent"
       agreeview:layout_constraintHorizontal_bias="0.5"
       agreeview:img="@drawable/ic_grade_black_24dp"
       agreeview:layout_constraintStart_toEndOf="@+id/agreeView4"
       agreeview:layout_constraintTop_toTopOf="@+id/agreeView4"
       agreeview:text_color="@color/text_color">
   </com.lt.agreeview.AgreeView>

   <android.support.constraint.Group
       android:id="@+id/group"
       android:layout_width="wrap_content"
       android:layout_height="wrap_content"/>

</android.support.constraint.ConstraintLayout>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
最終咱們的實現效果以下:

至此咱們的自定義點贊效果就完成了,源碼我已經上傳到Github上面,若是有須要的能夠自行下載Github(https://github.com/scorpioLt/AgreeView)

總結
其實自定義View並無想得那麼複雜,只要想通了原理,過程一步一步的寫,像這個點贊效果主要就分爲:點贊圖片的縮放、向上移動的屬性動畫;上方的動畫用PopupWindow實現,下方直接獲取Drawable畫到Canvas便可。

舒適提示:
我建立了一個技術交流羣,羣裏有各個行業的大佬都有,你們能夠在羣裏暢聊技術方面內容,以及文章推薦;若是有想加入的夥伴加我微信號【luotaosc】備註一下「加羣」 另外關注公衆號,還有一些我的收藏的視頻: 回覆「Android」 ,獲取Android視頻連接。 回覆「Java」 ,獲取Java視頻連接。 回覆「C++」 ,獲取C++視頻連接。 回覆「C」 ,獲取C視頻連接。 回覆「Python」 ,獲取Python視頻連接等等。

原創不易,若是以爲寫得好,掃碼關注一下點個贊,是我最大的動力。

關注我,必定會有意想不到的東西等你: 天天專一分享Android、JAVA乾貨
————————————————
版權聲明:本文爲CSDN博主「lt_sc」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處連接及本聲明。
原文連接:https://blog.csdn.net/qq_34560959/article/details/80649405

 

https://blog.csdn.net/qq_34560959/article/details/80649405

相關文章
相關標籤/搜索