├── .gitignore ├── .idea ├── codeStyles │ └── Project.xml ├── gradle.xml ├── misc.xml └── runConfigurations.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ ├── androidTest │ └── java │ │ └── com │ │ └── example │ │ └── customview │ │ └── ExampleInstrumentedTest.java │ ├── main │ ├── AndroidManifest.xml │ ├── java │ │ └── com │ │ │ └── example │ │ │ └── customview │ │ │ ├── JiKeLikeView.java │ │ │ ├── MainActivity.java │ │ │ └── SystemUtil.java │ └── res │ │ ├── drawable-v24 │ │ └── ic_launcher_foreground.xml │ │ ├── drawable-xhdpi │ │ ├── ic_message_like.png │ │ ├── ic_message_like_shining.png │ │ └── ic_message_unlike.png │ │ ├── drawable │ │ └── ic_launcher_background.xml │ │ ├── layout │ │ └── activity_main.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 │ │ ├── mipmap-xxxhdpi │ │ ├── ic_launcher.png │ │ └── ic_launcher_round.png │ │ └── values │ │ ├── attrs.xml │ │ ├── colors.xml │ │ ├── strings.xml │ │ └── styles.xml │ └── test │ └── java │ └── com │ └── example │ └── customview │ └── 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/caches/build_file_checksums.ser 5 | /.idea/libraries 6 | /.idea/modules.xml 7 | /.idea/workspace.xml 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild 12 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 15 | 16 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 18 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 17 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 28 5 | defaultConfig { 6 | applicationId "com.example.customview" 7 | minSdkVersion 15 8 | targetSdkVersion 28 9 | versionCode 1 10 | versionName "1.0" 11 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | implementation fileTree(dir: 'libs', include: ['*.jar']) 23 | implementation 'com.android.support:appcompat-v7:28.0.0' 24 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 25 | testImplementation 'junit:junit:4.12' 26 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 27 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 28 | } 29 | -------------------------------------------------------------------------------- /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/example/customview/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.example.customview; 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() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.example.customview", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/customview/JiKeLikeView.java: -------------------------------------------------------------------------------- 1 | package com.example.customview; 2 | 3 | import android.animation.AnimatorSet; 4 | import android.animation.ObjectAnimator; 5 | import android.content.Context; 6 | import android.content.res.Resources; 7 | import android.content.res.TypedArray; 8 | import android.graphics.Bitmap; 9 | import android.graphics.BitmapFactory; 10 | import android.graphics.Canvas; 11 | import android.graphics.Color; 12 | import android.graphics.Paint; 13 | import android.graphics.Path; 14 | import android.graphics.Rect; 15 | import android.support.annotation.Keep; 16 | import android.support.annotation.Nullable; 17 | import android.util.AttributeSet; 18 | import android.util.Log; 19 | import android.view.MotionEvent; 20 | import android.view.View; 21 | 22 | /** 23 | * Describe : 24 | * Created by Knight on 2018/12/19 25 | * 点滴之行,看世界 26 | **/ 27 | public class JiKeLikeView extends View { 28 | 29 | //点赞数量 30 | private int likeNumber; 31 | //文字上下移动的最大距离 32 | private int textMaxMove; 33 | //文字上下移动的距离 34 | private float textMoveDistance; 35 | //点亮的透明度 0位隐藏 255是出现 36 | private float shiningAlpha; 37 | //点亮的缩放系数 38 | private float shiningScale; 39 | //文字的透明度系数 40 | private float textAlpha; 41 | //动画播放时间 42 | private int duration = 250; 43 | //文字显示范围 44 | private Rect textRounds; 45 | //数字位数 46 | private float[] widths; 47 | 48 | //图像画笔 49 | private Paint bitmapPaint; 50 | //文字画笔 51 | private Paint textPaint; 52 | //之前的文字画笔 53 | private Paint oldTextPaint; 54 | //没有点赞的图像 55 | private Bitmap unLikeBitmap; 56 | //点赞后的图像 57 | private Bitmap likeBitmap; 58 | //点亮的图像 59 | private Bitmap shiningBitmap; 60 | 61 | //是否点赞 62 | private boolean isLike = false; 63 | //小手的缩放倍数 64 | private float handScale = 1.0f; 65 | //刚进入 数字不要加一 66 | private boolean isFirst; 67 | //圆形缩放系数 68 | private float shingCircleScale; 69 | //圆形透明度系数 70 | private float shingCircleAlpha; 71 | //圆画笔 72 | private Paint circlePaint; 73 | 74 | 75 | public JiKeLikeView(Context context) { 76 | this(context, null); 77 | } 78 | 79 | public JiKeLikeView(Context context, @Nullable AttributeSet attrs) { 80 | this(context, attrs, 0); 81 | } 82 | 83 | public JiKeLikeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { 84 | super(context, attrs, defStyleAttr); 85 | //获取attrs文件下配置属性 86 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.JiKeLikeView); 87 | //点赞数量 第一个参数就是属性集合里面的属性 固定格式R.styleable+自定义属性名字 88 | //第二个参数,如果没有设置这个属性,则会取设置的默认值 89 | likeNumber = typedArray.getInt(R.styleable.JiKeLikeView_like_number, 1999); 90 | //记得把TypedArray对象回收 91 | typedArray.recycle(); 92 | init(); 93 | } 94 | 95 | private void init() { 96 | //创建文本显示范围 97 | textRounds = new Rect(); 98 | //点赞数暂时8位 99 | widths = new float[8]; 100 | //Paint.ANTI_ALIAS_FLAG 属性是位图抗锯齿 101 | //bitmapPaint是图像画笔 102 | bitmapPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 103 | //这是绘制原来数字的画笔 加入没点赞之前是45 那么点赞后就是46 点赞是46 那么没点赞就是45 104 | textPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 105 | oldTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 106 | //文字颜色大小配置 颜色灰色 字体大小为14 107 | textPaint.setColor(Color.GRAY); 108 | textPaint.setTextSize(SystemUtil.sp2px(getContext(), 14)); 109 | oldTextPaint.setColor(Color.GRAY); 110 | oldTextPaint.setTextSize(SystemUtil.sp2px(getContext(), 14)); 111 | //圆画笔初始化 Paint.Style.STROKE只绘制图形轮廓 112 | circlePaint = new Paint(Paint.ANTI_ALIAS_FLAG); 113 | circlePaint.setColor(Color.RED); 114 | circlePaint.setStyle(Paint.Style.STROKE); 115 | //设置轮廓宽度 116 | circlePaint.setStrokeWidth(SystemUtil.dp2px(getContext(), 2)); 117 | //设置模糊效果 第一个参数是模糊半径,越大越模糊,第二个参数是阴影的横向偏移距离,正值向下偏移 负值向上偏移 118 | //第三个参数是纵向偏移距离,正值向下偏移,负值向上偏移 第四个参数是画笔的颜色 119 | circlePaint.setShadowLayer(SystemUtil.dp2px(getContext(), 1), SystemUtil.dp2px(getContext(), 1), SystemUtil.dp2px(getContext(), 1), Color.RED); 120 | 121 | } 122 | 123 | /** 124 | * 这个方法是在Activity resume的时候被调用的,Activity对应的window被添加的时候 125 | * 每个view只会调用一次,可以做一些初始化操作 126 | */ 127 | @Override 128 | protected void onAttachedToWindow() { 129 | super.onAttachedToWindow(); 130 | Resources resources = getResources(); 131 | //构造Bitmap对象,通过BitmapFactory工厂类的static Bitmap decodeResource根据给定的资源id解析成位图 132 | unLikeBitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_message_unlike); 133 | likeBitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_message_like); 134 | shiningBitmap = BitmapFactory.decodeResource(resources, R.drawable.ic_message_like_shining); 135 | } 136 | 137 | 138 | /** 139 | * 和onAttachedToWindow对应,在destroy view的时候调用 140 | */ 141 | @Override 142 | protected void onDetachedFromWindow() { 143 | super.onDetachedFromWindow(); 144 | //回收bitmap 145 | unLikeBitmap.recycle(); 146 | likeBitmap.recycle(); 147 | shiningBitmap.recycle(); 148 | } 149 | 150 | /** 151 | * 测量宽高 152 | * 这两个参数是由父视图经过计算后传递给子视图 153 | * @param widthMeasureSpec 宽度 154 | * @param heightMeasureSpec 高度 155 | */ 156 | @Override 157 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 158 | //MeasureSpec值由specMode和specSize共同组成,onMeasure两个参数的作用根据specMode的不同,有所区别。 159 | //当specMode为EXACTLY时,子视图的大小会根据specSize的大小来设置,对于布局参数中的match_parent或者精确大小值 160 | //当specMode为AT_MOST时,这两个参数只表示了子视图当前可以使用的最大空间大小,而子视图的实际大小不一定是specSize。所以我们自定义View时,重写onMeasure方法主要是在AT_MOST模式时,为子视图设置一个默认的大小,对于布局参数wrap_content。 161 | //高度默认是bitmap的高度加上下margin各10dp 162 | heightMeasureSpec = MeasureSpec.makeMeasureSpec(unLikeBitmap.getHeight() + SystemUtil.dp2px(getContext(), 20), MeasureSpec.EXACTLY); 163 | //宽度默认是bitmap的宽度加左右margin各10dp和文字宽度和文字右侧10dp likeNumber是文本数字 164 | String textnum = String.valueOf(likeNumber); 165 | //得到文本的宽度 166 | float textWidth = textPaint.measureText(textnum, 0, textnum.length()); 167 | //计算整个View的宽度 小手宽度 + 文本宽度 + 30px 168 | widthMeasureSpec = MeasureSpec.makeMeasureSpec(((int) (unLikeBitmap.getWidth() + textWidth + SystemUtil.dp2px(getContext(), 30))), MeasureSpec.EXACTLY); 169 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 170 | } 171 | 172 | 173 | @Override 174 | protected void onDraw(Canvas canvas) { 175 | super.onDraw(canvas); 176 | //获取正个View的高度 177 | int height = getHeight(); 178 | //取中心 179 | int centerY = height / 2; 180 | //小手根据有没有点赞进行改变 181 | Bitmap handBitmap = isLike ? likeBitmap : unLikeBitmap; 182 | //得到图像宽度 183 | int handBitmapWidth = handBitmap.getWidth(); 184 | //得到图像高度 185 | int handBitmapHeight = handBitmap.getHeight(); 186 | 187 | //画小手 188 | int handTop = (height - handBitmapHeight) / 2; 189 | //先保存画布的状态 190 | canvas.save(); 191 | //根据bitmap中心进行缩放 192 | canvas.scale(handScale, handScale, handBitmapWidth / 2, centerY); 193 | //画bitmap小手,第一个是参数对应的bitmap,第二个参数是左上角坐标,第三个参数上顶部坐标,第四个是画笔 194 | canvas.drawBitmap(handBitmap, SystemUtil.dp2px(getContext(), 10), handTop, bitmapPaint); 195 | //读取之前没有缩放画布的状态 196 | canvas.restore(); 197 | 198 | //画上面四点闪亮 199 | //先确定顶部 200 | int shiningTop = handTop - shiningBitmap.getHeight() + SystemUtil.dp2px(getContext(), 17); 201 | Log.d("ssd",shiningAlpha+""); 202 | //根据隐藏系数设置点亮的透明度 203 | bitmapPaint.setAlpha((int) (255 * shiningAlpha)); 204 | //保存画布状态 205 | canvas.save(); 206 | //画布根据点亮的缩放系数进行缩放 207 | canvas.scale(shiningScale, shiningScale, handBitmapWidth / 2, handTop); 208 | //画出点亮的bitmap 209 | //恢复画笔之前的状态 210 | canvas.restore(); 211 | //并且恢复画笔bitmapPaint透明度 212 | bitmapPaint.setAlpha(255); 213 | if(isLike){ 214 | canvas.drawBitmap(shiningBitmap, SystemUtil.dp2px(getContext(), 15), shiningTop, bitmapPaint); 215 | }else{ 216 | canvas.save(); 217 | //并且恢复画笔bitmapPaint透明度 218 | bitmapPaint.setAlpha(0); 219 | canvas.drawBitmap(shiningBitmap, SystemUtil.dp2px(getContext(), 15), shiningTop, bitmapPaint); 220 | canvas.restore(); 221 | //并且恢复画笔bitmapPaint透明度 222 | bitmapPaint.setAlpha(255); 223 | } 224 | 225 | //画文字 226 | String textValue = String.valueOf(likeNumber); 227 | //如果点赞了,之前的数值就是点赞数-1,如果取消点赞,那么之前数值(对比点赞后)就是现在显示的 228 | String textCancelValue; 229 | if (isLike) { 230 | textCancelValue = String.valueOf(likeNumber - 1); 231 | } else { 232 | if (isFirst) { 233 | textCancelValue = String.valueOf(likeNumber + 1); 234 | } else { 235 | isFirst = !isFirst; 236 | textCancelValue = String.valueOf(likeNumber); 237 | } 238 | } 239 | //文本的长度 240 | int textLength = textValue.length(); 241 | //获取绘制文字的坐标 getTextBounds 返回所有文本的联合边界 242 | textPaint.getTextBounds(textValue, 0, textValue.length(), textRounds); 243 | //确定X坐标 距离手差10dp 244 | int textX = handBitmapWidth + SystemUtil.dp2px(getContext(), 20); 245 | //确定Y坐标 距离 大图像的一半减去 文字区域高度的一半 即可得出 getTextBounds里的rect参数得到数值后, 246 | // 查看它的属性值 top、bottom会发现top是一个负数;bottom有时候是0,有时候是正数。结合第一点很容易理解,因为baseline坐标看成原点(0,0), 247 | // 那么相对位置top在它上面就是负数,bottom跟它重合就为0,在它下面就为负数。像小写字母j g y等,它们的bounds bottom都是正数, 248 | // 因为它们都有降部(在西文字体排印学中,降部指的是一个字体中,字母向下延伸超过基线的笔画部分)。 249 | int textY = height / 2 - (textRounds.top + textRounds.bottom) / 2; 250 | //绘制文字 这种情况针对不同位数变化 如 99 到100 999到10000 251 | if (textLength != textCancelValue.length() || textMaxMove == 0) { 252 | //第一个参数就是文字内容,第二个参数是文字的X坐标,第三个参数是文字的Y坐标,注意这个坐标 253 | //并不是文字的左上角 而是与左下角比较接近的位置 254 | //canvas.drawText(textValue, textX, textY, textPaint); 255 | //点赞 256 | if (isLike) { 257 | //圆的画笔根据设置的透明度进行变化 258 | circlePaint.setAlpha((int) (255 * shingCircleAlpha)); 259 | //画圆 260 | canvas.drawCircle(handBitmapWidth / 2 + SystemUtil.dp2px(getContext(), 10), handBitmapHeight / 2 + SystemUtil.dp2px(getContext(), 10), ((handBitmapHeight / 2 + SystemUtil.dp2px(getContext(), 2)) * shingCircleScale), circlePaint); 261 | //根据透明度进行变化 262 | oldTextPaint.setAlpha((int) (255 * (1 - textAlpha))); 263 | //绘制之前的数字 264 | canvas.drawText(textCancelValue, textX, textY - textMaxMove + textMoveDistance, oldTextPaint); 265 | //设置新数字的透明度 266 | textPaint.setAlpha((int) (255 * textAlpha)); 267 | //绘制新数字(点赞后或者取消点赞) 268 | canvas.drawText(textValue, textX, textY + textMoveDistance, textPaint); 269 | 270 | } else { 271 | oldTextPaint.setAlpha((int) (255 * (1 - textAlpha))); 272 | canvas.drawText(textCancelValue, textX, textY + textMaxMove + textMoveDistance, oldTextPaint); 273 | textPaint.setAlpha((int) (255 * textAlpha)); 274 | canvas.drawText(textValue, textX, textY + textMoveDistance, textPaint); 275 | } 276 | return; 277 | } 278 | //下面这种情况区别与99 999 9999这种 就是相同位数变化 279 | //把文字拆解成一个一个字符 就是获取字符串中每个字符的宽度,把结果填入参数widths 280 | //相当于measureText()的一个快捷方法,计算等价于对字符串中的每个字符分别调用measureText(),并把 281 | //它们的计算结果分别填入widths的不同元素 282 | textPaint.getTextWidths(textValue, widths); 283 | //将字符串转换为字符数组 284 | char[] chars = textValue.toCharArray(); 285 | char[] oldChars = textCancelValue.toCharArray(); 286 | 287 | for (int i = 0; i < chars.length; i++) { 288 | if (chars[i] == oldChars[i]) { 289 | textPaint.setAlpha(255); 290 | canvas.drawText(String.valueOf(chars[i]), textX, textY, textPaint); 291 | 292 | } else { 293 | //点赞 294 | if (isLike) { 295 | circlePaint.setAlpha((int) (255 * shingCircleAlpha)); 296 | canvas.drawCircle(handBitmapWidth / 2 + SystemUtil.dp2px(getContext(), 10), handBitmapHeight / 2 + SystemUtil.dp2px(getContext(), 10), ((handBitmapHeight / 2 + SystemUtil.dp2px(getContext(), 2)) * shingCircleScale), circlePaint); 297 | oldTextPaint.setAlpha((int) (255 * (1 - textAlpha))); 298 | canvas.drawText(String.valueOf(oldChars[i]), textX, textY - textMaxMove + textMoveDistance, oldTextPaint); 299 | textPaint.setAlpha((int) (255 * textAlpha)); 300 | canvas.drawText(String.valueOf(chars[i]), textX, textY + textMoveDistance, textPaint); 301 | } else { 302 | oldTextPaint.setAlpha((int) (255 * (1 - textAlpha))); 303 | canvas.drawText(String.valueOf(oldChars[i]), textX, textY + textMaxMove + textMoveDistance, oldTextPaint); 304 | textPaint.setAlpha((int) (255 * textAlpha)); 305 | canvas.drawText(String.valueOf(chars[i]), textX, textY + textMoveDistance, textPaint); 306 | } 307 | } 308 | //下一位数字x坐标要加上前一位的宽度 309 | textX += widths[i]; 310 | 311 | 312 | } 313 | 314 | } 315 | 316 | 317 | @Override 318 | public boolean onTouchEvent(MotionEvent event) { 319 | switch (event.getAction()) { 320 | case MotionEvent.ACTION_DOWN: 321 | 322 | jump(); 323 | 324 | break; 325 | } 326 | return super.onTouchEvent(event); 327 | } 328 | 329 | /** 330 | * 点赞事件触发 331 | */ 332 | private void jump() { 333 | isLike = !isLike; 334 | if (isLike) { 335 | ++likeNumber; 336 | setLikeNum(); 337 | //自定义属性 在ObjectAnimator中,是先根据属性值拼装成对应的set函数名字,比如下面handScale的拼装方法就是 338 | //将属性的第一个字母强制大写后与set拼接,所以就是setHandScale,然后通过反射找到对应控件的setHandScale(float handScale)函数 339 | //将当前数字值做为setHandScale(float handScale)的参数传入 set函数调用每隔十几毫秒就会被用一次 340 | //ObjectAnimator只负责把当前运动动画的数值传给set函数,set函数怎么来做就在里面写就行 341 | ObjectAnimator handScaleAnim = ObjectAnimator.ofFloat(this, "handScale", 1f, 0.8f, 1f); 342 | //设置动画时间 343 | handScaleAnim.setDuration(duration); 344 | 345 | //动画 点亮手指的四点 从0 - 1出现 346 | ObjectAnimator shingAlphaAnim = ObjectAnimator.ofFloat(this, "shingAlpha", 0f, 1f); 347 | // shingAlphaAnim.setDuration(duration); 348 | 349 | //放大 点亮手指的四点 350 | ObjectAnimator shingScaleAnim = ObjectAnimator.ofFloat(this, "shingScale", 0f, 1f); 351 | 352 | //画中心圆形有内到外扩散 353 | ObjectAnimator shingClicleAnim = ObjectAnimator.ofFloat(this, "shingCircleScale", 0.6f, 1f); 354 | //画出圆形有1到0消失 355 | ObjectAnimator shingCircleAlphaAnim = ObjectAnimator.ofFloat(this, "shingCircleAlpha", 0.3f, 0f); 356 | 357 | 358 | //动画集一起播放 359 | AnimatorSet animatorSet = new AnimatorSet(); 360 | animatorSet.playTogether(handScaleAnim, shingAlphaAnim, shingScaleAnim, shingClicleAnim, shingCircleAlphaAnim); 361 | animatorSet.start(); 362 | 363 | 364 | } else { 365 | //取消点赞 366 | --likeNumber; 367 | setLikeNum(); 368 | ObjectAnimator handScaleAnim = ObjectAnimator.ofFloat(this, "handScale", 1f, 0.8f, 1f); 369 | handScaleAnim.setDuration(duration); 370 | handScaleAnim.start(); 371 | 372 | //手指上的四点消失,透明度设置为0 373 | setShingAlpha(0); 374 | 375 | 376 | } 377 | } 378 | 379 | /** 380 | * 手指缩放方法 381 | * 382 | * @param handScale 383 | */ 384 | public void setHandScale(float handScale) { 385 | //传递缩放系数 386 | this.handScale = handScale; 387 | //请求重绘View树,即draw过程,视图发生大小没有变化就不会调用layout过程,并且重绘那些“需要重绘的”视图 388 | //如果是view就绘制该view,如果是ViewGroup,就绘制整个ViewGroup 389 | invalidate(); 390 | } 391 | 392 | 393 | /** 394 | * 手指上四点从0到1出现方法 395 | * 396 | * @param shingAlpha 397 | */ 398 | 399 | public void setShingAlpha(float shingAlpha) { 400 | this.shiningAlpha = shingAlpha; 401 | invalidate(); 402 | } 403 | 404 | /** 405 | * 手指上四点缩放方法 406 | * 407 | * @param shingScale 408 | */ 409 | @Keep 410 | public void setShingScale(float shingScale) { 411 | this.shiningScale = shingScale; 412 | invalidate(); 413 | } 414 | 415 | 416 | /** 417 | * 设置数字变化 418 | */ 419 | public void setLikeNum() { 420 | //开始移动的Y坐标 421 | float startY; 422 | //最大移动的高度 423 | textMaxMove = SystemUtil.dp2px(getContext(), 20); 424 | //如果点赞了 就下往上移 425 | if (isLike) { 426 | startY = textMaxMove; 427 | } else { 428 | startY = -textMaxMove; 429 | } 430 | ObjectAnimator textInAlphaAnim = ObjectAnimator.ofFloat(this, "textAlpha", 0f, 1f); 431 | textInAlphaAnim.setDuration(duration); 432 | ObjectAnimator textMoveAnim = ObjectAnimator.ofFloat(this, "textTranslate", startY, 0); 433 | textMoveAnim.setDuration(duration); 434 | 435 | 436 | AnimatorSet animatorSet = new AnimatorSet(); 437 | animatorSet.playTogether(textInAlphaAnim, textMoveAnim); 438 | animatorSet.start(); 439 | } 440 | 441 | 442 | /** 443 | * 设置数值透明度 444 | */ 445 | 446 | public void setTextAlpha(float textAlpha) { 447 | this.textAlpha = textAlpha; 448 | invalidate(); 449 | 450 | } 451 | 452 | /** 453 | * 设置数值移动 454 | */ 455 | 456 | public void setTextTranslate(float textTranslate) { 457 | textMoveDistance = textTranslate; 458 | invalidate(); 459 | } 460 | 461 | /** 462 | * 画出圆形波纹 463 | * 464 | * @param shingCircleScale 465 | */ 466 | public void setShingCircleScale(float shingCircleScale) { 467 | this.shingCircleScale = shingCircleScale; 468 | invalidate(); 469 | } 470 | 471 | /** 472 | * 圆形透明度设置 473 | * 474 | * @param shingCircleAlpha 475 | */ 476 | public void setShingCircleAlpha(float shingCircleAlpha) { 477 | this.shingCircleAlpha = shingCircleAlpha; 478 | invalidate(); 479 | 480 | } 481 | 482 | 483 | } 484 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/customview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.example.customview; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | 6 | public class MainActivity extends AppCompatActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_main); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /app/src/main/java/com/example/customview/SystemUtil.java: -------------------------------------------------------------------------------- 1 | package com.example.customview; 2 | 3 | import android.content.Context; 4 | import android.util.TypedValue; 5 | 6 | /** 7 | * Describe : 8 | * Created by Knight on 2018/12/22 9 | * 点滴之行,看世界 10 | **/ 11 | public class SystemUtil { 12 | /** 13 | * dp转px 14 | * 15 | * @param context 16 | * @param dpVal 17 | * @return 18 | */ 19 | public static int dp2px(Context context,float dpVal){ 20 | return (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,dpVal,context.getResources().getDisplayMetrics()); 21 | } 22 | 23 | /** 24 | * sp转px 25 | * @param context 26 | * @param spVal 27 | * @return 28 | * 29 | */ 30 | public static int sp2px(Context context,float spVal){ 31 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,spVal,context.getResources().getDisplayMetrics()); 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /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-xhdpi/ic_message_like.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/drawable-xhdpi/ic_message_like.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_message_like_shining.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/drawable-xhdpi/ic_message_like_shining.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/ic_message_unlike.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/drawable-xhdpi/ic_message_unlike.png -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 | 65 | 70 | 75 | 80 | 85 | 90 | 95 | 100 | 105 | 110 | 115 | 120 | 125 | 130 | 135 | 140 | 145 | 150 | 155 | 160 | 165 | 170 | 171 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 19 | 28 | 36 | 45 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CustomView 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/example/customview/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.example.customview; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | 5 | repositories { 6 | google() 7 | jcenter() 8 | } 9 | dependencies { 10 | classpath 'com.android.tools.build:gradle:3.2.1' 11 | 12 | 13 | // NOTE: Do not place your application dependencies here; they belong 14 | // in the individual module build.gradle files 15 | } 16 | } 17 | 18 | allprojects { 19 | repositories { 20 | google() 21 | jcenter() 22 | } 23 | } 24 | 25 | task clean(type: Delete) { 26 | delete rootProject.buildDir 27 | } 28 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | 15 | 16 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KnightAndroid/JikeLikeView/8e3c55f63c37987a636792768236b11a8211f99d/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-all.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app' 2 | --------------------------------------------------------------------------------