├── .gitignore ├── README.md ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── net │ │ └── arvin │ │ └── breatheview │ │ └── sample │ │ ├── MainActivity.java │ │ ├── SecondActivity.java │ │ └── ThirdActivity.java │ └── res │ ├── layout │ ├── activity_main.xml │ ├── activity_second.xml │ ├── activity_third.xml │ └── layout_scroll.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 │ ├── colors.xml │ ├── strings.xml │ └── styles.xml ├── breatheview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ └── java │ └── net │ └── arvin │ └── breatheview │ ├── BreatheView.java │ ├── CircleBreatheView.java │ └── RectBreatheView.java ├── build.gradle ├── gif └── bv_sample.gif ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | .gradle 4 | local.properties 5 | gradle.properties 6 | /.idea/workspace.xml 7 | /.idea/libraries 8 | .DS_Store 9 | /build 10 | /captures 11 | .externalNativeBuild -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 简介 2 | 3 | 这是一个自定义的转场动画实现方式,目前支持两种方式: 4 | 5 | * 圆形展开 6 | * 矩形展开 7 | 8 | 效果如下: 9 | 10 | ![](gif/bv_sample.gif) 11 | 12 | ## 使用 13 | 14 | ### 引用: 15 | 16 | 在根目录级的build.gradle中添加 17 | 18 | ``` 19 | allprojects { 20 | repositories { 21 | ... 22 | maven { url 'https://jitpack.io' } 23 | } 24 | } 25 | ``` 26 | 27 | 再在要使用的项目级的build.gradle中添加: 28 | 29 | ``` 30 | dependencies { 31 | compile 'com.github.arvinljw:BreatheView:v1.0.0' 32 | } 33 | ``` 34 | 35 | ### api介绍 36 | 37 | #### 1、打开界面动画 38 | 39 | ``` 40 | breatheView.startScaleBigger(); 41 | ``` 42 | 43 | #### 2、关闭界面动画 44 | 45 | ``` 46 | breatheView.startScaleSmaller(); 47 | ``` 48 | 49 | #### 3、设置背景颜色 50 | 51 | ``` 52 | breatheView.setBgColor(int color) 53 | ``` 54 | 55 | 简单介绍一下,这个动画是通过绘制,使用Xfermode实现的,先绘制背景部分,再绘制展开的部分,展开部分和背景重叠部分就变透明,这里设置的颜色就是这个背景颜色。 56 | 57 | #### 4、绘制的起始点 58 | 59 | 这里要分情况,目前提供了两种方式去展开: 60 | 61 | * CircleBreatheView 62 | 63 | 64 | ``` 65 | circleBreatheView.setDrawPoint(Point point) 66 | circleBreatheView.setDrawPoint(int x,int y) 67 | ``` 68 | 69 | * RectBreatheView 70 | 71 | ``` 72 | rectBreatheView.setDrawRect(Rect rect) 73 | rectBreatheView.setDrawRect(int left,int top,int right,int bottom) 74 | ``` 75 | 76 | *建议使用setDrawRect时,尽量保证水平或者垂直方向一边是占满屏幕的,因为目前没有分水平和垂直去分别计算* 77 | 78 | #### 5、使用技巧 79 | 80 | 可参照app中例子的代码。 81 | 82 | **重点**: 83 | 84 | 启动新的界面后,在startActivity后边加上一句 85 | 86 | ``` 87 | overridePendingTransition(0, 0); 88 | ``` 89 | 90 | 去掉系统转场动画,同理在关闭的时候,在finish后边也加上这一句。 91 | 92 | #### 6、扩展 93 | 94 | 可以自己继承BreatheView,参照RectBreatheView或者CircleBreatheView实现自己的自定义转场动画。 95 | 96 | ## 原理 97 | 98 | 99 | ``` 100 | mMode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); 101 | 102 | @Override 103 | protected void onDraw(Canvas canvas) { 104 | super.onDraw(canvas); 105 | 106 | int saveCount = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG); 107 | drawBg(canvas); 108 | mPaintSrc.setXfermode(mMode); 109 | drawBreathe(canvas); 110 | mPaintSrc.setXfermode(null); 111 | canvas.restoreToCount(saveCount); 112 | } 113 | ``` 114 | 115 | 如果知道Xfermode,那么一看上边的代码应该就明白一大半了,当然这只是其中重要的一步,还有一步就是使用属性动画,改变绘制BreatheView部分的大小,例如 116 | 117 | ``` 118 | public void setScale(int scale) { 119 | this.mScale = scale; 120 | postInvalidate(); 121 | } 122 | 123 | public int getScale() { 124 | return mScale; 125 | } 126 | 127 | protected void startScaleAnim(int start, int end) { 128 | final boolean isOpen = start < end; 129 | ObjectAnimator scale = ObjectAnimator.ofInt(this, "scale", start, end).setDuration(mDuration); 130 | scale.setInterpolator(new LinearInterpolator()); 131 | scale.addListener(new AnimatorListenerAdapter() { 132 | @Override 133 | public void onAnimationStart(Animator animation) { 134 | setVisibility(View.VISIBLE); 135 | } 136 | @Override 137 | public void onAnimationEnd(Animator animation) { 138 | canClose = isOpen; 139 | if (mAnimEndListener != null) { 140 | mAnimEndListener.onAnimEnd(isOpen); 141 | } 142 | } 143 | }); 144 | scale.start(); 145 | } 146 | 147 | protected void drawBg(Canvas canvas) { 148 | canvas.drawRect(mBgRect, mBgPaint); 149 | } 150 | 151 | @Override 152 | protected void drawBreathe(Canvas canvas) { 153 | canvas.drawCircle(mDrawPoint.x, mDrawPoint.y, mScale, mPaintBreathe); 154 | } 155 | ``` 156 | 157 | 核心代码就是这些,最重要就是通过属性动画,改变绘制的breathe部分的大小,并在onDraw时使用Xfermode实现。 158 | 159 | ## License 160 | 161 | ``` 162 | Copyright 2017 arvinljw 163 | 164 | Licensed under the Apache License, Version 2.0 (the "License"); 165 | you may not use this file except in compliance with the License. 166 | You may obtain a copy of the License at 167 | 168 | http://www.apache.org/licenses/LICENSE-2.0 169 | 170 | Unless required by applicable law or agreed to in writing, software 171 | distributed under the License is distributed on an "AS IS" BASIS, 172 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 173 | See the License for the specific language governing permissions and 174 | limitations under the License. 175 | ``` 176 | 177 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion 25 5 | buildToolsVersion "25.0.3" 6 | 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | } 21 | 22 | dependencies { 23 | compile fileTree(include: ['*.jar'], dir: 'libs') 24 | // compile project(':breatheview') 25 | compile 'com.github.arvinljw:BreatheView:v1.0.0' 26 | } 27 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/arvin/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /app/src/main/java/net/arvin/breatheview/sample/MainActivity.java: -------------------------------------------------------------------------------- 1 | package net.arvin.breatheview.sample; 2 | 3 | import android.content.Intent; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | 9 | public class MainActivity extends AppCompatActivity implements View.OnClickListener { 10 | public static final String BG_COLOR = "bg_color"; 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_main); 16 | 17 | findViewById(R.id.tv_to_next).setOnClickListener(this); 18 | findViewById(R.id.tv_to_third).setOnClickListener(this); 19 | } 20 | 21 | @Override 22 | public void onClick(View v) { 23 | Class clazz = SecondActivity.class; 24 | int bgColor = Color.WHITE; 25 | switch (v.getId()) { 26 | case R.id.tv_to_next: 27 | clazz = SecondActivity.class; 28 | break; 29 | case R.id.tv_to_third: 30 | clazz = ThirdActivity.class; 31 | break; 32 | } 33 | Intent intent = new Intent(MainActivity.this, clazz); 34 | intent.putExtra(BG_COLOR, bgColor); 35 | startActivity(intent); 36 | overridePendingTransition(0, 0); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /app/src/main/java/net/arvin/breatheview/sample/SecondActivity.java: -------------------------------------------------------------------------------- 1 | package net.arvin.breatheview.sample; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | import net.arvin.breatheview.BreatheView; 9 | import net.arvin.breatheview.CircleBreatheView; 10 | 11 | public class SecondActivity extends AppCompatActivity implements BreatheView.IAnimEndListener { 12 | 13 | private CircleBreatheView breatheView; 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_second); 19 | 20 | breatheView = (CircleBreatheView) findViewById(R.id.circleBreatheView); 21 | breatheView.startScaleBigger(); 22 | 23 | breatheView.setAnimEndListener(this); 24 | } 25 | 26 | @Override 27 | public void onBackPressed() { 28 | breatheView.setBgColor(getIntent().getIntExtra(MainActivity.BG_COLOR, Color.parseColor(BreatheView.BG_DEFAULT_COLOR))); 29 | breatheView.startScaleSmaller(); 30 | } 31 | 32 | @Override 33 | public void onAnimEnd(boolean isOpen) { 34 | if (!isOpen) { 35 | finish(); 36 | overridePendingTransition(0, 0); 37 | } else { 38 | breatheView.setVisibility(View.GONE); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /app/src/main/java/net/arvin/breatheview/sample/ThirdActivity.java: -------------------------------------------------------------------------------- 1 | package net.arvin.breatheview.sample; 2 | 3 | import android.graphics.Color; 4 | import android.os.Bundle; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.view.View; 7 | 8 | import net.arvin.breatheview.BreatheView; 9 | import net.arvin.breatheview.RectBreatheView; 10 | 11 | public class ThirdActivity extends AppCompatActivity implements BreatheView.IAnimEndListener { 12 | private RectBreatheView breatheView; 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_third); 18 | 19 | breatheView = (RectBreatheView) findViewById(R.id.rectBreatheView); 20 | breatheView.startScaleBigger(); 21 | 22 | breatheView.setAnimEndListener(this); 23 | } 24 | 25 | @Override 26 | public void onBackPressed() { 27 | breatheView.setBgColor(getIntent().getIntExtra(MainActivity.BG_COLOR, Color.parseColor(BreatheView.BG_DEFAULT_COLOR))); 28 | breatheView.startScaleSmaller(); 29 | } 30 | 31 | @Override 32 | public void onAnimEnd(boolean isOpen) { 33 | if (!isOpen) { 34 | finish(); 35 | overridePendingTransition(0, 0); 36 | } else { 37 | breatheView.setVisibility(View.GONE); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 10 | 11 | 19 | 20 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_second.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_third.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 15 | 16 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_scroll.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 11 | 12 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #3F51B5 4 | #303F9F 5 | #FF4081 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | BVSample 3 | 4 | 1、NBA(National Basketball Association)是美国男子职业篮球联赛的简称,于1946年6月6日在纽约成立,由北美三十支队伍组成的男子职业篮球联盟,美国四大职业体育联盟之一。 5 | \n2、其中诞生了威尔特·张伯伦、乔治·麦肯、迈克尔·乔丹、哈基姆·奥拉朱旺、沙奎尔·奥尼尔、科比·布莱恩特、勒布朗·詹姆斯、克莱德·德雷克斯勒、斯科蒂·皮蓬、卡里姆·阿布杜尔-贾巴尔、丹尼斯·罗德曼、蒂姆·邓肯、德怀恩·韦德、斯蒂芬·库里、阿伦·艾弗森、特雷西·麦克格雷迪、凯文·加内特、凯文·杜兰特、拉塞尔·威斯布鲁克、詹姆斯·哈登、凯里·欧文、姚明等球星,是世界上水平最高的篮球赛事。 6 | \n3、NBA的三十支球队分属两个联盟,分别是东部联盟和西部联盟,每个联盟由三个赛区组成,每个赛区有五支球队。NBA在每年的赛程开始之前会安排选秀与热身的季前赛,随后是常规赛,从每年的10月底开始,到次年4月中旬结束[1] ,而季后赛(NBA Playoffs)在每年4月下旬开始,在最后决出东西部分区冠军晋级总决赛,七局四胜者为当赛季总冠军,总决赛中表现最优秀的球员获得总决赛MVP荣誉,一般是得分最高者得FMVP,最有价值球员。此外,还有NBA全明星赛(All-star Game)作为一项表演性质的赛事存在,时间不定,为期三天,第一天是新星挑战赛,第二天为三分,扣篮,技巧大赛并各项目均有冠军产生,第三天是全明星正赛,由球迷票选的各东西部联盟球员参加。 7 | \n4、NBA(National Basketball Association)是美国男子职业篮球联赛的简称,于1946年6月6日在纽约成立,由北美三十支队伍组成的男子职业篮球联盟,美国四大职业体育联盟之一。 8 | \n5、其中诞生了威尔特·张伯伦、乔治·麦肯、迈克尔·乔丹、哈基姆·奥拉朱旺、沙奎尔·奥尼尔、科比·布莱恩特、勒布朗·詹姆斯、克莱德·德雷克斯勒、斯科蒂·皮蓬、卡里姆·阿布杜尔-贾巴尔、丹尼斯·罗德曼、蒂姆·邓肯、德怀恩·韦德、斯蒂芬·库里、阿伦·艾弗森、特雷西·麦克格雷迪、凯文·加内特、凯文·杜兰特、拉塞尔·威斯布鲁克、詹姆斯·哈登、凯里·欧文、姚明等球星,是世界上水平最高的篮球赛事。 9 | \n6、NBA的三十支球队分属两个联盟,分别是东部联盟和西部联盟,每个联盟由三个赛区组成,每个赛区有五支球队。NBA在每年的赛程开始之前会安排选秀与热身的季前赛,随后是常规赛,从每年的10月底开始,到次年4月中旬结束[1] ,而季后赛(NBA Playoffs)在每年4月下旬开始,在最后决出东西部分区冠军晋级总决赛,七局四胜者为当赛季总冠军,总决赛中表现最优秀的球员获得总决赛MVP荣誉,一般是得分最高者得FMVP,最有价值球员。此外,还有NBA全明星赛(All-star Game)作为一项表演性质的赛事存在,时间不定,为期三天,第一天是新星挑战赛,第二天为三分,扣篮,技巧大赛并各项目均有冠军产生,第三天是全明星正赛,由球迷票选的各东西部联盟球员参加。 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /breatheview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /breatheview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | 4 | android { 5 | compileSdkVersion 25 6 | buildToolsVersion "25.0.3" 7 | defaultConfig { 8 | minSdkVersion 14 9 | targetSdkVersion 25 10 | versionCode 1 11 | versionName "1.0" 12 | } 13 | buildTypes { 14 | release { 15 | minifyEnabled false 16 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 17 | } 18 | } 19 | } 20 | 21 | dependencies { 22 | compile fileTree(dir: 'libs', include: ['*.jar']) 23 | compile 'com.android.support:appcompat-v7:25.3.1' 24 | } 25 | 26 | group='com.github.arvinljw' 27 | -------------------------------------------------------------------------------- /breatheview/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # By default, the flags in this file are appended to flags specified 3 | # in /Users/arvin/Library/Android/sdk/tools/proguard/proguard-android.txt 4 | # You can edit the include path and order by changing the proguardFiles 5 | # directive in build.gradle. 6 | # 7 | # For more details, see 8 | # http://developer.android.com/guide/developing/tools/proguard.html 9 | 10 | # Add any project specific keep options here: 11 | 12 | # If your project uses WebView with JS, uncomment the following 13 | # and specify the fully qualified class name to the JavaScript interface 14 | # class: 15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 16 | # public *; 17 | #} 18 | 19 | # Uncomment this to preserve the line number information for 20 | # debugging stack traces. 21 | #-keepattributes SourceFile,LineNumberTable 22 | 23 | # If you keep the line number information, uncomment this to 24 | # hide the original source file name. 25 | #-renamesourcefileattribute SourceFile 26 | -------------------------------------------------------------------------------- /breatheview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /breatheview/src/main/java/net/arvin/breatheview/BreatheView.java: -------------------------------------------------------------------------------- 1 | package net.arvin.breatheview; 2 | 3 | import android.animation.Animator; 4 | import android.animation.AnimatorListenerAdapter; 5 | import android.animation.ObjectAnimator; 6 | import android.content.Context; 7 | import android.graphics.Canvas; 8 | import android.graphics.Color; 9 | import android.graphics.Paint; 10 | import android.graphics.PorterDuff; 11 | import android.graphics.PorterDuffXfermode; 12 | import android.graphics.RectF; 13 | import android.support.annotation.Keep; 14 | import android.util.AttributeSet; 15 | import android.util.DisplayMetrics; 16 | import android.view.View; 17 | import android.view.animation.LinearInterpolator; 18 | 19 | /** 20 | * Created by arvinljw on 17/6/20 16:20 21 | * Function: 22 | * Desc: 23 | */ 24 | public abstract class BreatheView extends View { 25 | public static final int ANIM_DEFAULT_DURATION = 500; 26 | public static final String BG_DEFAULT_COLOR = "#cccccc"; 27 | 28 | protected int mScreenWidth; 29 | protected int mScreenHeight; 30 | 31 | protected Paint mBgPaint; 32 | private RectF mBgRect; 33 | 34 | protected Paint mPaintBreathe; 35 | protected PorterDuffXfermode mMode; 36 | 37 | protected int mScale; 38 | protected int mMaxScale; 39 | protected int mMinScale; 40 | 41 | protected long mDuration = ANIM_DEFAULT_DURATION; 42 | 43 | protected IAnimEndListener mAnimEndListener; 44 | protected boolean canClose; 45 | 46 | public BreatheView(Context context) { 47 | this(context, null); 48 | } 49 | 50 | public BreatheView(Context context, AttributeSet attrs) { 51 | this(context, attrs, 0); 52 | } 53 | 54 | public BreatheView(Context context, AttributeSet attrs, int defStyleAttr) { 55 | super(context, attrs, defStyleAttr); 56 | init(); 57 | } 58 | 59 | protected void init() { 60 | mBgPaint = new Paint(); 61 | mBgPaint.setAntiAlias(true); 62 | mBgPaint.setColor(Color.parseColor(BG_DEFAULT_COLOR)); 63 | 64 | mBgRect = new RectF(0, 0, getScreenWidth(), getScreenHeight()); 65 | 66 | mMode = new PorterDuffXfermode(PorterDuff.Mode.DST_OUT); 67 | 68 | mScale = 0; 69 | mMinScale = 0; 70 | 71 | mPaintBreathe = new Paint(); 72 | mPaintBreathe.setAntiAlias(true); 73 | 74 | mScreenWidth = getScreenWidth(); 75 | mScreenHeight = getScreenHeight(); 76 | 77 | setClickable(true); 78 | } 79 | 80 | @Override 81 | protected void onDraw(Canvas canvas) { 82 | super.onDraw(canvas); 83 | 84 | int saveCount = canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG); 85 | drawBg(canvas); 86 | mPaintBreathe.setXfermode(mMode); 87 | drawBreathe(canvas); 88 | mPaintBreathe.setXfermode(null); 89 | canvas.restoreToCount(saveCount); 90 | } 91 | 92 | protected void drawBg(Canvas canvas) { 93 | canvas.drawRect(mBgRect, mBgPaint); 94 | } 95 | 96 | public void setScale(int scale) { 97 | this.mScale = scale; 98 | postInvalidate(); 99 | } 100 | 101 | public int getScale() { 102 | return mScale; 103 | } 104 | 105 | /** 106 | * 打开 107 | */ 108 | public void startScaleBigger() { 109 | calculateMaxScale(); 110 | startScaleAnim(mMinScale, mMaxScale); 111 | } 112 | 113 | /** 114 | * 关闭 115 | */ 116 | public void startScaleSmaller() { 117 | calculateMaxScale(); 118 | boolean isOpen = mMaxScale < mMinScale; 119 | if (!isOpen && !canClose) { 120 | return; 121 | } 122 | startScaleAnim(mMaxScale, mMinScale); 123 | } 124 | 125 | protected void startScaleAnim(int start, int end) { 126 | final boolean isOpen = start < end; 127 | ObjectAnimator scale = ObjectAnimator.ofInt(this, "scale", start, end).setDuration(mDuration); 128 | scale.setInterpolator(new LinearInterpolator()); 129 | scale.addListener(new AnimatorListenerAdapter() { 130 | @Override 131 | public void onAnimationStart(Animator animation) { 132 | setVisibility(View.VISIBLE); 133 | } 134 | 135 | @Override 136 | public void onAnimationEnd(Animator animation) { 137 | canClose = isOpen; 138 | if (mAnimEndListener != null) { 139 | mAnimEndListener.onAnimEnd(isOpen); 140 | } 141 | } 142 | }); 143 | scale.start(); 144 | } 145 | 146 | protected void calculateMaxScale() { 147 | mMaxScale = (int) Math.ceil(Math.sqrt(mScreenWidth * mScreenWidth + mScreenHeight * mScreenHeight)); 148 | } 149 | 150 | public void setAnimEndListener(IAnimEndListener animEndListener) { 151 | this.mAnimEndListener = animEndListener; 152 | } 153 | 154 | /** 155 | * @param color 背景颜色 156 | */ 157 | public void setBgColor(int color) { 158 | mBgPaint.setColor(color); 159 | } 160 | 161 | protected DisplayMetrics getScreenDisplay() { 162 | return getResources().getDisplayMetrics(); 163 | } 164 | 165 | public int getScreenWidth() { 166 | return getScreenDisplay().widthPixels; 167 | } 168 | 169 | public int getScreenHeight() { 170 | return getScreenDisplay().heightPixels; 171 | } 172 | 173 | protected int dp2px(float dp) { 174 | return (int) (dp * getScreenDisplay().density + 0.5f); 175 | } 176 | 177 | protected int sp2px(float sp) { 178 | return (int) (sp * getScreenDisplay().scaledDensity + 0.5f); 179 | } 180 | 181 | protected abstract void drawBreathe(Canvas canvas); 182 | 183 | public interface IAnimEndListener { 184 | void onAnimEnd(boolean isOpen); 185 | } 186 | } 187 | -------------------------------------------------------------------------------- /breatheview/src/main/java/net/arvin/breatheview/CircleBreatheView.java: -------------------------------------------------------------------------------- 1 | package net.arvin.breatheview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Point; 6 | import android.util.AttributeSet; 7 | 8 | /** 9 | * Created by arvinljw on 17/7/24 16:37 10 | * Function: 11 | * Desc: 12 | */ 13 | public class CircleBreatheView extends BreatheView { 14 | private Point mDrawPoint; 15 | 16 | public CircleBreatheView(Context context) { 17 | super(context); 18 | } 19 | 20 | public CircleBreatheView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | } 23 | 24 | public CircleBreatheView(Context context, AttributeSet attrs, int defStyleAttr) { 25 | super(context, attrs, defStyleAttr); 26 | } 27 | 28 | @Override 29 | protected void init() { 30 | super.init(); 31 | 32 | mDrawPoint = new Point(); 33 | } 34 | 35 | @Override 36 | protected void drawBreathe(Canvas canvas) { 37 | canvas.drawCircle(mDrawPoint.x, mDrawPoint.y, mScale, mPaintBreathe); 38 | } 39 | 40 | @Override 41 | protected void calculateMaxScale() { 42 | int width = mScreenWidth - mDrawPoint.x; 43 | width = width < mDrawPoint.x ? mDrawPoint.x : width; 44 | 45 | int height = mScreenHeight - mDrawPoint.y; 46 | height = height < mDrawPoint.y ? mDrawPoint.y : height; 47 | 48 | mMaxScale = (int) Math.ceil(Math.sqrt(width * width + height * height)); 49 | } 50 | 51 | /** 52 | * @param drawPoint 设置绘制的展开的点,若是收回时则是终点 53 | */ 54 | public void setDrawPoint(Point drawPoint) { 55 | this.mDrawPoint = drawPoint; 56 | } 57 | 58 | /** 59 | * 设置绘制的展开的点,若是收回时则是终点 60 | * 61 | * @param x x坐标 62 | * @param y y坐标 63 | */ 64 | public void setDrawPoint(int x, int y) { 65 | this.mDrawPoint.x = x; 66 | this.mDrawPoint.y = y; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /breatheview/src/main/java/net/arvin/breatheview/RectBreatheView.java: -------------------------------------------------------------------------------- 1 | package net.arvin.breatheview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Rect; 6 | import android.support.annotation.Keep; 7 | import android.util.AttributeSet; 8 | 9 | /** 10 | * Created by arvinljw on 17/7/24 16:37 11 | * Function: 12 | * Desc: 13 | */ 14 | public class RectBreatheView extends BreatheView { 15 | private Rect mDrawRect; 16 | 17 | private Rect mBreatheRect; 18 | 19 | public RectBreatheView(Context context) { 20 | super(context); 21 | } 22 | 23 | public RectBreatheView(Context context, AttributeSet attrs) { 24 | super(context, attrs); 25 | } 26 | 27 | public RectBreatheView(Context context, AttributeSet attrs, int defStyleAttr) { 28 | super(context, attrs, defStyleAttr); 29 | } 30 | 31 | @Override 32 | protected void init() { 33 | super.init(); 34 | 35 | mDrawRect = new Rect(0, mScreenHeight / 2, mScreenWidth, mScreenHeight / 2); 36 | 37 | mBreatheRect = new Rect(0, 0, 0, 0); 38 | 39 | mDuration = 400; 40 | } 41 | 42 | public void setScale(int scale) { 43 | this.mScale = scale; 44 | 45 | int left = mDrawRect.left - mScale; 46 | mBreatheRect.left = left < 0 ? 0 : left; 47 | 48 | int right = mDrawRect.right + mScale; 49 | mBreatheRect.right = right > mScreenWidth ? mScreenWidth : right; 50 | 51 | int top = mDrawRect.top - mScale; 52 | mBreatheRect.top = top < 0 ? 0 : top; 53 | 54 | int bottom = mDrawRect.bottom + mScale; 55 | mBreatheRect.bottom = bottom > mScreenHeight ? mScreenHeight : bottom; 56 | 57 | postInvalidate(); 58 | } 59 | 60 | @Override 61 | protected void drawBreathe(Canvas canvas) { 62 | canvas.drawRect(mBreatheRect, mPaintBreathe); 63 | } 64 | 65 | @Override 66 | protected void calculateMaxScale() { 67 | int scaleX = mDrawRect.left < mScreenWidth - mDrawRect.right ? mScreenWidth - mDrawRect.right : mDrawRect.left; 68 | 69 | int scaleY = mDrawRect.top < mScreenHeight - mDrawRect.bottom ? mScreenHeight - mDrawRect.bottom : mDrawRect.top; 70 | 71 | mMaxScale = Math.max(scaleX, scaleY); 72 | } 73 | 74 | /** 75 | * @param drawRect 设置绘制的展开的矩形,若是收回时则是结束的矩形 76 | */ 77 | public void setDrawRect(Rect drawRect) { 78 | this.mDrawRect = drawRect; 79 | } 80 | 81 | public void setDrawRect(int left, int top, int right, int bottom) { 82 | this.mDrawRect.left = left; 83 | this.mDrawRect.top = top; 84 | this.mDrawRect.right = right; 85 | this.mDrawRect.bottom = bottom; 86 | } 87 | } 88 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.3.3' 9 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.5' 10 | 11 | // NOTE: Do not place your application dependencies here; they belong 12 | // in the individual module build.gradle files 13 | } 14 | } 15 | 16 | allprojects { 17 | repositories { 18 | jcenter() 19 | maven { url 'https://jitpack.io' } 20 | } 21 | } 22 | 23 | task clean(type: Delete) { 24 | delete rootProject.buildDir 25 | } 26 | -------------------------------------------------------------------------------- /gif/bv_sample.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/gif/bv_sample.gif -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/arvinljw/BreatheView/ec3e5769aa10669dcf67ad69fb086b22e6bc545f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Sun Jul 23 14:34:09 CST 2017 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip 7 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 10 | DEFAULT_JVM_OPTS="" 11 | 12 | APP_NAME="Gradle" 13 | APP_BASE_NAME=`basename "$0"` 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set APP_HOME 46 | # Resolve links: $0 may be a link 47 | PRG="$0" 48 | # Need this for relative symlinks. 49 | while [ -h "$PRG" ] ; do 50 | ls=`ls -ld "$PRG"` 51 | link=`expr "$ls" : '.*-> \(.*\)$'` 52 | if expr "$link" : '/.*' > /dev/null; then 53 | PRG="$link" 54 | else 55 | PRG=`dirname "$PRG"`"/$link" 56 | fi 57 | done 58 | SAVED="`pwd`" 59 | cd "`dirname \"$PRG\"`/" >/dev/null 60 | APP_HOME="`pwd -P`" 61 | cd "$SAVED" >/dev/null 62 | 63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 64 | 65 | # Determine the Java command to use to start the JVM. 66 | if [ -n "$JAVA_HOME" ] ; then 67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 68 | # IBM's JDK on AIX uses strange locations for the executables 69 | JAVACMD="$JAVA_HOME/jre/sh/java" 70 | else 71 | JAVACMD="$JAVA_HOME/bin/java" 72 | fi 73 | if [ ! -x "$JAVACMD" ] ; then 74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 75 | 76 | Please set the JAVA_HOME variable in your environment to match the 77 | location of your Java installation." 78 | fi 79 | else 80 | JAVACMD="java" 81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 82 | 83 | Please set the JAVA_HOME variable in your environment to match the 84 | location of your Java installation." 85 | fi 86 | 87 | # Increase the maximum file descriptors if we can. 88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 89 | MAX_FD_LIMIT=`ulimit -H -n` 90 | if [ $? -eq 0 ] ; then 91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 92 | MAX_FD="$MAX_FD_LIMIT" 93 | fi 94 | ulimit -n $MAX_FD 95 | if [ $? -ne 0 ] ; then 96 | warn "Could not set maximum file descriptor limit: $MAX_FD" 97 | fi 98 | else 99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 100 | fi 101 | fi 102 | 103 | # For Darwin, add options to specify how the application appears in the dock 104 | if $darwin; then 105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 106 | fi 107 | 108 | # For Cygwin, switch paths to Windows format before running java 109 | if $cygwin ; then 110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 112 | JAVACMD=`cygpath --unix "$JAVACMD"` 113 | 114 | # We build the pattern for arguments to be converted via cygpath 115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 116 | SEP="" 117 | for dir in $ROOTDIRSRAW ; do 118 | ROOTDIRS="$ROOTDIRS$SEP$dir" 119 | SEP="|" 120 | done 121 | OURCYGPATTERN="(^($ROOTDIRS))" 122 | # Add a user-defined pattern to the cygpath arguments 123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 125 | fi 126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 127 | i=0 128 | for arg in "$@" ; do 129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 131 | 132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 134 | else 135 | eval `echo args$i`="\"$arg\"" 136 | fi 137 | i=$((i+1)) 138 | done 139 | case $i in 140 | (0) set -- ;; 141 | (1) set -- "$args0" ;; 142 | (2) set -- "$args0" "$args1" ;; 143 | (3) set -- "$args0" "$args1" "$args2" ;; 144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 150 | esac 151 | fi 152 | 153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules 154 | function splitJvmOpts() { 155 | JVM_OPTS=("$@") 156 | } 157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS 158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME" 159 | 160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@" 161 | -------------------------------------------------------------------------------- /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 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 12 | set DEFAULT_JVM_OPTS= 13 | 14 | set DIRNAME=%~dp0 15 | if "%DIRNAME%" == "" set DIRNAME=. 16 | set APP_BASE_NAME=%~n0 17 | set APP_HOME=%DIRNAME% 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 Windowz variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | if "%@eval[2+2]" == "4" goto 4NT_args 53 | 54 | :win9xME_args 55 | @rem Slurp the command line arguments. 56 | set CMD_LINE_ARGS= 57 | set _SKIP=2 58 | 59 | :win9xME_args_slurp 60 | if "x%~1" == "x" goto execute 61 | 62 | set CMD_LINE_ARGS=%* 63 | goto execute 64 | 65 | :4NT_args 66 | @rem Get arguments from the 4NT Shell from JP Software 67 | set CMD_LINE_ARGS=%$ 68 | 69 | :execute 70 | @rem Setup the command line 71 | 72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 73 | 74 | @rem Execute Gradle 75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 76 | 77 | :end 78 | @rem End local scope for the variables with windows NT shell 79 | if "%ERRORLEVEL%"=="0" goto mainEnd 80 | 81 | :fail 82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 83 | rem the _cmd.exe /c_ return code! 84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 85 | exit /b 1 86 | 87 | :mainEnd 88 | if "%OS%"=="Windows_NT" endlocal 89 | 90 | :omega 91 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':breatheview', ':app' 2 | --------------------------------------------------------------------------------