├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── chaychan │ │ └── redpacketanimdemo │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── chaychan │ │ │ └── redpacketanimdemo │ │ │ ├── CustomDialog.java │ │ │ ├── FrameAnimation.java │ │ │ ├── MainActivity.java │ │ │ ├── OnRedPacketDialogClickListener.java │ │ │ ├── RedPacketEntity.java │ │ │ └── RedPacketViewHolder.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ ├── activity_main.xml │ │ └── dialog_red_packet.xml │ │ ├── mipmap-anydpi-v26 │ │ ├── ic_launcher.xml │ │ └── ic_launcher_round.xml │ │ ├── mipmap-hdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-mdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ ├── mipmap-xxhdpi │ │ ├── ic_launcher.png │ │ ├── ic_launcher_round.png │ │ ├── icon_open_red_packet1.png │ │ ├── icon_open_red_packet10.png │ │ ├── icon_open_red_packet11.png │ │ ├── icon_open_red_packet2.png │ │ ├── icon_open_red_packet3.png │ │ ├── icon_open_red_packet4.png │ │ ├── icon_open_red_packet5.png │ │ ├── icon_open_red_packet6.png │ │ ├── icon_open_red_packet7.png │ │ ├── icon_open_red_packet8.png │ │ ├── icon_open_red_packet9.png │ │ ├── icon_red_packet_close.png │ │ └── red_packet_bg.png │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── chaychan │ └── redpacketanimdemo │ └── ExampleUnitTest.java ├── build.gradle ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | /.idea 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### 仿微信打开红包动画,详细请看博客 2 | 3 | [http://blog.csdn.net/chay_chan/article/details/79044579](http://blog.csdn.net/chay_chan/article/details/79044579 "http://blog.csdn.net/chay_chan/article/details/79044579") -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 26 5 | defaultConfig { 6 | applicationId "com.chaychan.redpacketanimdemo" 7 | minSdkVersion 16 8 | targetSdkVersion 26 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | 13 | javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } } 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | implementation fileTree(dir: 'libs', include: ['*.jar']) 25 | implementation 'com.android.support:appcompat-v7:27.0.2' 26 | implementation 'com.android.support.constraint:constraint-layout:1.0.2' 27 | testImplementation 'junit:junit:4.12' 28 | androidTestImplementation 'com.android.support.test:runner:1.0.1' 29 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1' 30 | 31 | implementation 'com.github.bumptech.glide:glide:4.5.0' 32 | annotationProcessor 'com.github.bumptech.glide:compiler:4.5.0' 33 | compile 'com.jakewharton:butterknife:7.0.1' 34 | } 35 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/chaychan/redpacketanimdemo/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.redpacketanimdemo; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() throws Exception { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.chaychan.redpacketanimdemo", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/redpacketanimdemo/CustomDialog.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.redpacketanimdemo; 2 | 3 | import android.app.Dialog; 4 | import android.content.Context; 5 | import android.view.Gravity; 6 | import android.view.View; 7 | import android.view.Window; 8 | import android.view.WindowManager; 9 | 10 | /* 11 | * 自定义圆角的dialog 12 | */ 13 | public class CustomDialog extends Dialog { 14 | 15 | private static int default_width = 160; //默认宽度 16 | 17 | private static int default_height = 120;//默认高度 18 | 19 | public CustomDialog(Context context, View layout, int style) { 20 | 21 | this(context, default_width, default_height, layout, style); 22 | 23 | } 24 | 25 | public CustomDialog(Context context, int width, int height, View layout, int style) { 26 | 27 | super(context, style); 28 | 29 | setContentView(layout); 30 | 31 | Window window = getWindow(); 32 | 33 | WindowManager.LayoutParams params = window.getAttributes(); 34 | 35 | params.gravity = Gravity.CENTER; 36 | 37 | window.setAttributes(params); 38 | } 39 | 40 | } -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/redpacketanimdemo/FrameAnimation.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.redpacketanimdemo; 2 | 3 | import android.widget.ImageView; 4 | 5 | /** 6 | * Created by Ansen on 2015/5/14 23:30. 7 | * 8 | * @E-mail: ansen360@126.com 9 | * @Blog: http://blog.csdn.net/qq_25804863 10 | * @Github: https://github.com/ansen360 11 | * @PROJECT_NAME: FrameAnimation 12 | * @PACKAGE_NAME: com.ansen.frameanimation.sample 13 | * @Description: TODO 14 | */ 15 | public class FrameAnimation { 16 | 17 | private boolean mIsRepeat; 18 | 19 | private AnimationListener mAnimationListener; 20 | 21 | private ImageView mImageView; 22 | 23 | private int[] mFrameRess; 24 | 25 | /** 26 | * 每帧动画的播放间隔数组 27 | */ 28 | private int[] mDurations; 29 | 30 | /** 31 | * 每帧动画的播放间隔 32 | */ 33 | private int mDuration; 34 | 35 | /** 36 | * 下一遍动画播放的延迟时间 37 | */ 38 | private int mDelay; 39 | 40 | private int mLastFrame; 41 | 42 | private boolean mNext; 43 | 44 | private boolean mPause; 45 | 46 | private int mCurrentSelect; 47 | 48 | private int mCurrentFrame; 49 | 50 | private static final int SELECTED_A = 1; 51 | 52 | private static final int SELECTED_B = 2; 53 | 54 | private static final int SELECTED_C = 3; 55 | 56 | private static final int SELECTED_D = 4; 57 | 58 | 59 | /** 60 | * @param iv 播放动画的控件 61 | * @param frameRes 播放的图片数组 62 | * @param duration 每帧动画的播放间隔(毫秒) 63 | * @param isRepeat 是否循环播放 64 | */ 65 | public FrameAnimation(ImageView iv, int[] frameRes, int duration, boolean isRepeat) { 66 | this.mImageView = iv; 67 | this.mFrameRess = frameRes; 68 | this.mDuration = duration; 69 | this.mLastFrame = frameRes.length - 1; 70 | this.mIsRepeat = isRepeat; 71 | play(0); 72 | } 73 | 74 | /** 75 | * @param iv 播放动画的控件 76 | * @param frameRess 播放的图片数组 77 | * @param durations 每帧动画的播放间隔(毫秒) 78 | * @param isRepeat 是否循环播放 79 | */ 80 | public FrameAnimation(ImageView iv, int[] frameRess, int[] durations, boolean isRepeat) { 81 | this.mImageView = iv; 82 | this.mFrameRess = frameRess; 83 | this.mDurations = durations; 84 | this.mLastFrame = frameRess.length - 1; 85 | this.mIsRepeat = isRepeat; 86 | playByDurations(0); 87 | } 88 | 89 | /** 90 | * 循环播放动画 91 | * 92 | * @param iv 播放动画的控件 93 | * @param frameRess 播放的图片数组 94 | * @param duration 每帧动画的播放间隔(毫秒) 95 | * @param delay 循环播放的时间间隔 96 | */ 97 | public FrameAnimation(ImageView iv, int[] frameRess, int duration, int delay) { 98 | this.mImageView = iv; 99 | this.mFrameRess = frameRess; 100 | this.mDuration = duration; 101 | this.mDelay = delay; 102 | this.mLastFrame = frameRess.length - 1; 103 | playAndDelay(0); 104 | } 105 | 106 | /** 107 | * 循环播放动画 108 | * 109 | * @param iv 播放动画的控件 110 | * @param frameRess 播放的图片数组 111 | * @param durations 每帧动画的播放间隔(毫秒) 112 | * @param delay 循环播放的时间间隔 113 | */ 114 | public FrameAnimation(ImageView iv, int[] frameRess, int[] durations, int delay) { 115 | this.mImageView = iv; 116 | this.mFrameRess = frameRess; 117 | this.mDurations = durations; 118 | this.mDelay = delay; 119 | this.mLastFrame = frameRess.length - 1; 120 | playByDurationsAndDelay(0); 121 | } 122 | 123 | private void playByDurationsAndDelay(final int i) { 124 | mImageView.postDelayed(new Runnable() { 125 | 126 | @Override 127 | public void run() { 128 | if (mPause) { // 暂停和播放需求 129 | mCurrentSelect = SELECTED_A; 130 | mCurrentFrame = i; 131 | return; 132 | } 133 | if (0 == i) { 134 | if (mAnimationListener != null) { 135 | mAnimationListener.onAnimationStart(); 136 | } 137 | } 138 | mImageView.setBackgroundResource(mFrameRess[i]); 139 | if (i == mLastFrame) { 140 | if (mAnimationListener != null) { 141 | mAnimationListener.onAnimationRepeat(); 142 | } 143 | mNext = true; 144 | playByDurationsAndDelay(0); 145 | } else { 146 | playByDurationsAndDelay(i + 1); 147 | } 148 | } 149 | }, mNext && mDelay > 0 ? mDelay : mDurations[i]); 150 | 151 | } 152 | 153 | private void playAndDelay(final int i) { 154 | mImageView.postDelayed(new Runnable() { 155 | 156 | @Override 157 | public void run() { 158 | if (mPause) { 159 | if (mPause) { 160 | mCurrentSelect = SELECTED_B; 161 | mCurrentFrame = i; 162 | return; 163 | } 164 | return; 165 | } 166 | mNext = false; 167 | if (0 == i) { 168 | if (mAnimationListener != null) { 169 | mAnimationListener.onAnimationStart(); 170 | } 171 | } 172 | mImageView.setBackgroundResource(mFrameRess[i]); 173 | if (i == mLastFrame) { 174 | if (mAnimationListener != null) { 175 | mAnimationListener.onAnimationRepeat(); 176 | } 177 | mNext = true; 178 | playAndDelay(0); 179 | } else { 180 | playAndDelay(i + 1); 181 | } 182 | } 183 | }, mNext && mDelay > 0 ? mDelay : mDuration); 184 | 185 | } 186 | 187 | private void playByDurations(final int i) { 188 | mImageView.postDelayed(new Runnable() { 189 | 190 | @Override 191 | public void run() { 192 | if (mPause) { 193 | if (mPause) { 194 | mCurrentSelect = SELECTED_C; 195 | mCurrentFrame = i; 196 | if (mAnimationListener != null) { 197 | mAnimationListener.onAnimationPause(); 198 | } 199 | return; 200 | } 201 | return; 202 | } 203 | if (0 == i) { 204 | if (mAnimationListener != null) { 205 | mAnimationListener.onAnimationStart(); 206 | } 207 | } 208 | mImageView.setBackgroundResource(mFrameRess[i]); 209 | if (i == mLastFrame) { 210 | if (mIsRepeat) { 211 | if (mAnimationListener != null) { 212 | mAnimationListener.onAnimationRepeat(); 213 | } 214 | playByDurations(0); 215 | } else { 216 | if (mAnimationListener != null) { 217 | mAnimationListener.onAnimationEnd(); 218 | } 219 | } 220 | } else { 221 | 222 | playByDurations(i + 1); 223 | } 224 | } 225 | }, mDurations[i]); 226 | 227 | } 228 | 229 | private void play(final int i) { 230 | mImageView.postDelayed(new Runnable() { 231 | 232 | @Override 233 | public void run() { 234 | if (mPause) { 235 | if (mPause) { 236 | mCurrentSelect = SELECTED_D; 237 | mCurrentFrame = i; 238 | 239 | if (mAnimationListener != null) { 240 | mAnimationListener.onAnimationPause(); 241 | } 242 | return; 243 | } 244 | return; 245 | } 246 | if (0 == i) { 247 | if (mAnimationListener != null) { 248 | mAnimationListener.onAnimationStart(); 249 | } 250 | } 251 | mImageView.setBackgroundResource(mFrameRess[i]); 252 | if (i == mLastFrame) { 253 | 254 | if (mIsRepeat) { 255 | if (mAnimationListener != null) { 256 | mAnimationListener.onAnimationRepeat(); 257 | } 258 | play(0); 259 | } else { 260 | if (mAnimationListener != null) { 261 | mAnimationListener.onAnimationEnd(); 262 | } 263 | } 264 | 265 | } else { 266 | 267 | play(i + 1); 268 | } 269 | } 270 | }, mDuration); 271 | } 272 | 273 | public static interface AnimationListener { 274 | 275 | /** 276 | *

Notifies the start of the animation.

277 | */ 278 | void onAnimationStart(); 279 | 280 | /** 281 | *

Notifies the end of the animation. This callback is not invoked 282 | * for animations with repeat count set to INFINITE.

283 | */ 284 | void onAnimationEnd(); 285 | 286 | /** 287 | *

Notifies the repetition of the animation.

288 | */ 289 | void onAnimationRepeat(); 290 | 291 | void onAnimationPause(); 292 | } 293 | 294 | /** 295 | *

Binds an animation listener to this animation. The animation listener 296 | * is notified of animation events such as the end of the animation or the 297 | * repetition of the animation.

298 | * 299 | * @param listener the animation listener to be notified 300 | */ 301 | public void setAnimationListener(AnimationListener listener) { 302 | this.mAnimationListener = listener; 303 | } 304 | 305 | public void release() { 306 | pauseAnimation(); 307 | } 308 | 309 | public void pauseAnimation() { 310 | this.mPause = true; 311 | } 312 | 313 | public boolean isPause() { 314 | return this.mPause; 315 | } 316 | 317 | public void restartAnimation() { 318 | if (mPause) { 319 | mPause = false; 320 | switch (mCurrentSelect) { 321 | case SELECTED_A: 322 | playByDurationsAndDelay(mCurrentFrame); 323 | break; 324 | case SELECTED_B: 325 | playAndDelay(mCurrentFrame); 326 | break; 327 | case SELECTED_C: 328 | playByDurations(mCurrentFrame); 329 | break; 330 | case SELECTED_D: 331 | play(mCurrentFrame); 332 | break; 333 | default: 334 | break; 335 | } 336 | } 337 | } 338 | 339 | } 340 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/redpacketanimdemo/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.redpacketanimdemo; 2 | 3 | import android.os.Bundle; 4 | import android.support.v7.app.AppCompatActivity; 5 | import android.view.View; 6 | 7 | public class MainActivity extends AppCompatActivity { 8 | 9 | private View mRedPacketDialogView; 10 | private RedPacketViewHolder mRedPacketViewHolder; 11 | private CustomDialog mRedPacketDialog; 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_main); 17 | } 18 | 19 | public void showDialog(View view){ 20 | RedPacketEntity entity = new RedPacketEntity("chaychan", "http://upload.51qianmai.com/20171205180511192.png", "大吉大利,今晚吃鸡"); 21 | showRedPacketDialog(entity); 22 | } 23 | 24 | public void showRedPacketDialog(RedPacketEntity entity) { 25 | if (mRedPacketDialogView == null) { 26 | mRedPacketDialogView = View.inflate(this, R.layout.dialog_red_packet, null); 27 | mRedPacketViewHolder = new RedPacketViewHolder(this, mRedPacketDialogView); 28 | mRedPacketDialog = new CustomDialog(this, mRedPacketDialogView, R.style.custom_dialog); 29 | mRedPacketDialog.setCancelable(false); 30 | } 31 | 32 | mRedPacketViewHolder.setData(entity); 33 | mRedPacketViewHolder.setOnRedPacketDialogClickListener(new OnRedPacketDialogClickListener() { 34 | @Override 35 | public void onCloseClick() { 36 | mRedPacketDialog.dismiss(); 37 | } 38 | 39 | @Override 40 | public void onOpenClick() { 41 | //领取红包,调用接口 42 | } 43 | }); 44 | 45 | mRedPacketDialog.show(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/redpacketanimdemo/OnRedPacketDialogClickListener.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.redpacketanimdemo; 2 | 3 | /** 4 | * @author ChayChan 5 | * @description: 红包点击的监听 6 | * @date 2017/11/27 17:36 7 | */ 8 | 9 | public interface OnRedPacketDialogClickListener { 10 | /** 11 | * 点击了关闭按钮 12 | */ 13 | void onCloseClick(); 14 | 15 | /** 16 | * 点击了打开红包的按钮 17 | */ 18 | void onOpenClick(); 19 | 20 | } 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/redpacketanimdemo/RedPacketEntity.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.redpacketanimdemo; 2 | 3 | /** 4 | * @author ChayChan 5 | * @description: 红包 6 | * @date 2017/11/28 14:23 7 | */ 8 | 9 | public class RedPacketEntity{ 10 | public String name; 11 | public String avatar; 12 | public String remark; 13 | 14 | public RedPacketEntity(String name, String avatar, String remark) { 15 | this.name = name; 16 | this.avatar = avatar; 17 | this.remark = remark; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/chaychan/redpacketanimdemo/RedPacketViewHolder.java: -------------------------------------------------------------------------------- 1 | package com.chaychan.redpacketanimdemo; 2 | 3 | import android.content.Context; 4 | import android.util.Log; 5 | import android.view.View; 6 | import android.widget.ImageView; 7 | import android.widget.TextView; 8 | 9 | import com.bumptech.glide.Glide; 10 | import com.bumptech.glide.request.RequestOptions; 11 | 12 | import butterknife.Bind; 13 | import butterknife.ButterKnife; 14 | import butterknife.OnClick; 15 | 16 | /** 17 | * @author ChayChan 18 | * @description: 红包弹框 19 | * @date 2017/11/27 15:12 20 | */ 21 | 22 | public class RedPacketViewHolder { 23 | 24 | @Bind(R.id.iv_close) 25 | ImageView mIvClose; 26 | 27 | @Bind(R.id.iv_avatar) 28 | ImageView mIvAvatar; 29 | 30 | @Bind(R.id.tv_name) 31 | TextView mTvName; 32 | 33 | @Bind(R.id.tv_msg) 34 | TextView mTvMsg; 35 | 36 | @Bind(R.id.iv_open) 37 | ImageView mIvOpen; 38 | 39 | private Context mContext; 40 | private OnRedPacketDialogClickListener mListener; 41 | 42 | private int[] mImgResIds = new int[]{ 43 | R.mipmap.icon_open_red_packet1, 44 | R.mipmap.icon_open_red_packet2, 45 | R.mipmap.icon_open_red_packet3, 46 | R.mipmap.icon_open_red_packet4, 47 | R.mipmap.icon_open_red_packet5, 48 | R.mipmap.icon_open_red_packet6, 49 | R.mipmap.icon_open_red_packet7, 50 | R.mipmap.icon_open_red_packet7, 51 | R.mipmap.icon_open_red_packet8, 52 | R.mipmap.icon_open_red_packet9, 53 | R.mipmap.icon_open_red_packet4, 54 | R.mipmap.icon_open_red_packet10, 55 | R.mipmap.icon_open_red_packet11, 56 | }; 57 | private FrameAnimation mFrameAnimation; 58 | 59 | public RedPacketViewHolder(Context context, View view) { 60 | mContext = context; 61 | ButterKnife.bind(this, view); 62 | } 63 | 64 | @OnClick({R.id.iv_close, R.id.iv_open}) 65 | public void onClick(View view) { 66 | switch (view.getId()) { 67 | case R.id.iv_close: 68 | stopAnim(); 69 | if (mListener != null) { 70 | mListener.onCloseClick(); 71 | } 72 | break; 73 | 74 | case R.id.iv_open: 75 | if (mFrameAnimation != null) { 76 | //如果正在转动,则直接返回 77 | return; 78 | } 79 | 80 | startAnim(); 81 | 82 | if (mListener != null) { 83 | mListener.onOpenClick(); 84 | } 85 | break; 86 | } 87 | } 88 | 89 | public void setData(RedPacketEntity entity) { 90 | RequestOptions options = new RequestOptions(); 91 | options.centerCrop() 92 | .circleCrop(); 93 | 94 | Glide.with(mContext) 95 | .load(entity.avatar) 96 | .apply(options) 97 | .into(mIvAvatar); 98 | 99 | mTvName.setText(entity.name); 100 | mTvMsg.setText(entity.remark); 101 | } 102 | 103 | public void startAnim() { 104 | mFrameAnimation = new FrameAnimation(mIvOpen, mImgResIds, 125, true); 105 | mFrameAnimation.setAnimationListener(new FrameAnimation.AnimationListener() { 106 | @Override 107 | public void onAnimationStart() { 108 | Log.i("", "start"); 109 | } 110 | 111 | @Override 112 | public void onAnimationEnd() { 113 | Log.i("", "end"); 114 | } 115 | 116 | @Override 117 | public void onAnimationRepeat() { 118 | Log.i("", "repeat"); 119 | } 120 | 121 | @Override 122 | public void onAnimationPause() { 123 | mIvOpen.setBackgroundResource(R.mipmap.icon_open_red_packet1); 124 | } 125 | }); 126 | } 127 | 128 | public void stopAnim() { 129 | if (mFrameAnimation != null) { 130 | mFrameAnimation.release(); 131 | mFrameAnimation = null; 132 | } 133 | } 134 | 135 | public void setOnRedPacketDialogClickListener(OnRedPacketDialogClickListener listener) { 136 | mListener = listener; 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 11 | 16 | 21 | 26 | 31 | 36 | 41 | 46 | 51 | 56 | 61 | 66 | 71 | 76 | 81 | 86 | 91 | 96 | 101 | 106 | 111 | 116 | 121 | 126 | 131 | 136 | 141 | 146 | 151 | 156 | 161 | 166 | 171 | 172 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 |