├── .gitignore ├── README.md ├── apk └── sample.apk ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── aries │ │ └── radiusview │ │ ├── BaseActivity.java │ │ └── MainActivity.java │ └── res │ ├── drawable │ └── ic_logo.xml │ ├── layout │ ├── activity_main.xml │ └── layout_title_bar.xml │ ├── mipmap-hdpi │ └── ic_launcher.png │ ├── mipmap-mdpi │ └── ic_launcher.png │ ├── mipmap-xhdpi │ └── ic_launcher.png │ ├── mipmap-xxhdpi │ └── ic_launcher.png │ ├── mipmap-xxxhdpi │ └── ic_launcher.png │ ├── values-w820dp │ └── dimens.xml │ └── values │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── build.gradle ├── buildConfig.gradle ├── gradle.properties ├── library ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── aries │ │ └── ui │ │ └── view │ │ └── radius │ │ ├── RadiusEditText.java │ │ ├── RadiusFrameLayout.java │ │ ├── RadiusLinearLayout.java │ │ ├── RadiusRelativeLayout.java │ │ ├── RadiusTextView.java │ │ └── RadiusViewDelegate.java │ └── res │ └── values │ └── attrs.xml ├── screenshot └── 00.gif └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | /RadiusView.iml 2 | /.gradle 3 | /.idea 4 | /build 5 | /library 6 | /local.properties 7 | /gradlew.bat 8 | /gradlew 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RadiusView 2 | -------------------------- 3 | ## 简介: 4 | 5 | 一个用于需要圆角矩形框背景的TextView或Layout的情况,减少直接使用时引入的shape资源文件,包括RadiusTextView,RadiusEditText,RadiusLinearLayout,RadiusRelativeLayout,RadiusFrameLayout,RadiusCheckBox,RadiusRadioButton,主要有圆角控制、默认背景(边框线)、按下背景(边框线)、不可点击背景(边框线)、选择selected背景(边框线)、选中checked背景(边框线);全圆角、四角单独设置圆角功能,使用方式参照layout_main. 6 | 7 | **说明1.1.0以后版本UIWidget维护,不再做版本更新** 8 | 9 | 更全常见UI库参看 [UIWidget](https://github.com/AriesHoo/UIWidget) 10 | 11 | [[Sample PC Download]](https://github.com/AriesHoo/RadiusView/blob/master/apk/sample.apk) 12 | 13 | [[Sample Mobile Download]](http://fir.im/r84v) 14 | 15 | ![](https://github.com/AriesHoo/UIWidget/blob/master/apk/qr.png) 16 | 17 | **Gradle集成** 18 | 19 | ``` 20 | allprojects { 21 | repositories { 22 | ... 23 | maven { url "https://jitpack.io" } 24 | } 25 | } 26 | ``` 27 | 28 | ``` 29 | dependencies { 30 | //compile 'com.github.AriesHoo:RadiusView:1.1.0' 31 | compile 'com.github.AriesHoo:RadiusView:${LATEST_VERSION}' 32 | } 33 | ``` 34 | 35 | ## 录屏预览 36 | 37 | ![](https://github.com/AriesHoo/RadiusView/blob/master/screenshot/00.gif) 38 | 39 | ## 鸣谢 40 | 41 | [FlycoRoundView](https://github.com/H07000223/FlycoRoundView) 42 | 43 | -------------------------------------------------------------------------------- /apk/sample.apk: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AriesHoo/RadiusView/c065ed49f5e9aa998ebbe6a60099b69db18db869/apk/sample.apk -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | apply plugin: 'com.neenbedankt.android-apt' 3 | android { 4 | def ext = rootProject.ext 5 | compileSdkVersion ext.compileSdkVersion 6 | buildToolsVersion ext.buildToolsVersion 7 | defaultConfig { 8 | applicationId "com.aries.radiusview" 9 | minSdkVersion ext.minSdkVersion 10 | targetSdkVersion ext.targetSdkVersion 11 | versionCode 1 12 | versionName "1.1.0" 13 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 14 | } 15 | buildTypes { 16 | release { 17 | minifyEnabled false 18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 19 | } 20 | } 21 | } 22 | 23 | dependencies { 24 | compile fileTree(dir: 'libs', include: ['*.jar']) 25 | def supportVersion = rootProject.ext.supportVersion 26 | compile 'com.android.support:appcompat-v7:'.concat(supportVersion) 27 | apt 'com.jakewharton:butterknife-compiler:8.4.0' 28 | compile project(':library') 29 | compile 'com.jakewharton:butterknife:8.7.0' 30 | 31 | compile 'com.github.AriesHoo:TitleBarView:1.3.0' 32 | } 33 | -------------------------------------------------------------------------------- /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 D:\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 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /app/src/main/java/com/aries/radiusview/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.aries.radiusview; 2 | 3 | import android.app.Activity; 4 | import android.os.Bundle; 5 | import android.support.annotation.LayoutRes; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.view.View; 8 | import android.view.ViewGroup; 9 | 10 | import com.aries.ui.view.title.StatusBarUtil; 11 | import com.aries.ui.view.title.TitleBarView; 12 | 13 | import butterknife.ButterKnife; 14 | import butterknife.Unbinder; 15 | 16 | /** 17 | * Created: AriesHoo on 2017/7/3 16:04 18 | * Function: title 基类 19 | * Desc: 20 | */ 21 | 22 | public abstract class BaseActivity extends AppCompatActivity { 23 | 24 | protected TitleBarView titleBar; 25 | protected Activity mContext; 26 | protected boolean mIsFirstShow = true; 27 | private Unbinder mUnBinder; 28 | protected int type = 0; 29 | protected boolean isWhite = true; 30 | 31 | protected abstract void setTitleBar(); 32 | 33 | protected boolean isShowLine() { 34 | return true; 35 | } 36 | 37 | @LayoutRes 38 | protected abstract int getLayout(); 39 | 40 | protected void loadData() { 41 | } 42 | 43 | protected void beforeSetView() { 44 | } 45 | 46 | protected void beforeInitView() { 47 | } 48 | 49 | protected abstract void initView(Bundle var1); 50 | 51 | @Override 52 | protected void onCreate(Bundle savedInstanceState) { 53 | super.onCreate(savedInstanceState); 54 | this.mContext = this; 55 | this.beforeSetView(); 56 | this.setContentView(this.getLayout()); 57 | mUnBinder = ButterKnife.bind(this); 58 | initTitle(); 59 | this.beforeInitView(); 60 | this.initView(savedInstanceState); 61 | } 62 | 63 | protected void initTitle() { 64 | titleBar = (TitleBarView) findViewById(R.id.titleBar); 65 | if (titleBar == null) { 66 | return; 67 | } 68 | type = StatusBarUtil.StatusBarLightMode(mContext); 69 | if (type <= 0) {//无法设置白底黑字 70 | //titleBar.setStatusAlpha(102);//5.0 半透明模式alpha-102 71 | titleBar.setImmersible(mContext,true,false); 72 | } 73 | titleBar.setTitleMainText(mContext.getClass().getSimpleName()); 74 | setTitleBar(); 75 | titleBar.setOnLeftTextClickListener(new View.OnClickListener() { 76 | @Override 77 | public void onClick(View v) { 78 | onBackPressed(); 79 | } 80 | }); 81 | setTitleLine(isShowLine()); 82 | } 83 | 84 | public void setTitleLine(boolean enable) { 85 | titleBar.setDividerVisible(enable); 86 | } 87 | 88 | public View getRootView() { 89 | return ((ViewGroup) findViewById(android.R.id.content)).getChildAt(0); 90 | } 91 | 92 | @Override 93 | protected void onDestroy() { 94 | super.onDestroy(); 95 | mUnBinder.unbind(); 96 | } 97 | 98 | protected void onResume() { 99 | if (this.mIsFirstShow) { 100 | this.mIsFirstShow = false; 101 | this.loadData(); 102 | } 103 | 104 | super.onResume(); 105 | } 106 | 107 | } 108 | -------------------------------------------------------------------------------- /app/src/main/java/com/aries/radiusview/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.aries.radiusview; 2 | 3 | import android.os.Bundle; 4 | 5 | /** 6 | * Created: AriesHoo on 2017/7/19 10:53 7 | * Function: RadiusView示例 8 | * Desc: 9 | */ 10 | public class MainActivity extends BaseActivity { 11 | 12 | 13 | @Override 14 | protected void setTitleBar() { 15 | titleBar.setTitleMainText("RadiusView"); 16 | } 17 | 18 | @Override 19 | protected int getLayout() { 20 | return R.layout.activity_main; 21 | } 22 | 23 | @Override 24 | protected void initView(Bundle var1) { 25 | 26 | } 27 | 28 | 29 | } 30 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_logo.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 16 | 17 | 23 | 24 | 30 | 31 | 49 | 50 | 68 | 69 | 70 | 91 | 92 | 109 | 110 | 128 | 129 | 146 | 147 | 154 | 155 | 167 | 168 | 182 | 183 | 184 | 191 | 192 | 204 | 205 | 217 | 218 | 219 | 227 | 228 | 234 | 235 | 236 | 250 | 251 | 256 | 257 | 263 | 264 | 265 | 277 | 278 | 285 | 286 | 294 | 295 | 296 | 307 | 308 | 313 | 314 | 321 | 322 | 323 | 324 | -------------------------------------------------------------------------------- /app/src/main/res/layout/layout_title_bar.xml: -------------------------------------------------------------------------------- 1 | 2 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AriesHoo/RadiusView/c065ed49f5e9aa998ebbe6a60099b69db18db869/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AriesHoo/RadiusView/c065ed49f5e9aa998ebbe6a60099b69db18db869/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AriesHoo/RadiusView/c065ed49f5e9aa998ebbe6a60099b69db18db869/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AriesHoo/RadiusView/c065ed49f5e9aa998ebbe6a60099b69db18db869/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AriesHoo/RadiusView/c065ed49f5e9aa998ebbe6a60099b69db18db869/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/values-w820dp/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 64dp 6 | 7 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #FFFFFF 4 | #FFFFFF 5 | #393939 6 | 7 | #DCDCDC 8 | #f8f8f8 9 | #FFFFFF 10 | #333333 11 | #636363 12 | #ffffff 13 | #dcdcdc 14 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 16dp 4 | 16dp 5 | 14dp 6 | 0.5dp 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | RadiusView 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 | apply from: 'buildConfig.gradle' 3 | buildscript { 4 | repositories { 5 | jcenter() 6 | } 7 | dependencies { 8 | classpath 'com.android.tools.build:gradle:2.2.3' 9 | classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8' 10 | classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1' 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 | -------------------------------------------------------------------------------- /buildConfig.gradle: -------------------------------------------------------------------------------- 1 | ext{ 2 | compileSdkVersion = 25 3 | buildToolsVersion = "25.0.2" 4 | 5 | minSdkVersion = 14 6 | targetSdkVersion = 25 7 | 8 | supportVersion = "25.1.1" 9 | } -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | 3 | # IDE (e.g. Android Studio) users: 4 | # Gradle settings configured through the IDE *will override* 5 | # any settings specified in this file. 6 | 7 | # For more details on how to configure your build environment visit 8 | # http://www.gradle.org/docs/current/userguide/build_environment.html 9 | 10 | # Specifies the JVM arguments used for the daemon process. 11 | # The setting is particularly useful for tweaking memory settings. 12 | org.gradle.jvmargs=-Xmx1536m 13 | 14 | # When configured, Gradle will run in incubating parallel mode. 15 | # This option should only be used with decoupled projects. More details, visit 16 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 17 | # org.gradle.parallel=true 18 | -------------------------------------------------------------------------------- /library/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /library/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | 4 | android { 5 | compileSdkVersion 23 6 | buildToolsVersion "23.0.2" 7 | 8 | defaultConfig { 9 | minSdkVersion 8 10 | targetSdkVersion 23 11 | versionCode 1 12 | versionName "1.0.0" 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(dir: 'libs', include: ['*.jar']) 24 | } 25 | -------------------------------------------------------------------------------- /library/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/lihui/work/AndroidStudio/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 | -------------------------------------------------------------------------------- /library/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /library/src/main/java/com/aries/ui/view/radius/RadiusEditText.java: -------------------------------------------------------------------------------- 1 | package com.aries.ui.view.radius; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.EditText; 6 | 7 | /** 8 | * Created: AriesHoo on 2017-02-13 16:10 9 | * Function:用于需要圆角矩形框背景的EditText的情况,减少直接使用TextView时引入的shape资源文件 10 | * Desc: 11 | */ 12 | public class RadiusEditText extends EditText { 13 | private RadiusViewDelegate delegate; 14 | 15 | public RadiusEditText(Context context) { 16 | this(context, null); 17 | } 18 | 19 | public RadiusEditText(Context context, AttributeSet attrs) { 20 | this(context, attrs, 0); 21 | } 22 | 23 | public RadiusEditText(Context context, AttributeSet attrs, int defStyleAttr) { 24 | super(context, attrs, defStyleAttr); 25 | delegate = new RadiusViewDelegate(this, context, attrs); 26 | setFocusableInTouchMode(true); 27 | } 28 | 29 | /** 30 | * use delegate to set attr 31 | */ 32 | public RadiusViewDelegate getDelegate() { 33 | return delegate; 34 | } 35 | 36 | @Override 37 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 38 | if (delegate.getWidthHeightEqualEnable() && getWidth() > 0 && getHeight() > 0) { 39 | int max = Math.max(getWidth(), getHeight()); 40 | int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); 41 | super.onMeasure(measureSpec, measureSpec); 42 | return; 43 | } 44 | 45 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 46 | } 47 | 48 | @Override 49 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 50 | super.onLayout(changed, left, top, right, bottom); 51 | if (delegate.getRadiusHalfHeightEnable()) { 52 | delegate.setRadius(getHeight() / 2); 53 | } else { 54 | delegate.setBgSelector(); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /library/src/main/java/com/aries/ui/view/radius/RadiusFrameLayout.java: -------------------------------------------------------------------------------- 1 | package com.aries.ui.view.radius; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.FrameLayout; 6 | 7 | /** 8 | * Created: AriesHoo on 2017-02-10 14:24 9 | * Function:用于需要圆角矩形框背景的FrameLayout的情况,减少直接使用FrameLayout时引入的shape资源文件 10 | * Desc: 11 | */ 12 | public class RadiusFrameLayout extends FrameLayout { 13 | private RadiusViewDelegate delegate; 14 | 15 | public RadiusFrameLayout(Context context) { 16 | this(context, null); 17 | } 18 | 19 | public RadiusFrameLayout(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | delegate = new RadiusViewDelegate(this, context, attrs); 22 | } 23 | 24 | /** use delegate to set attr */ 25 | public RadiusViewDelegate getDelegate() { 26 | return delegate; 27 | } 28 | 29 | @Override 30 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 31 | if (delegate.getWidthHeightEqualEnable() && getWidth() > 0 && getHeight() > 0) { 32 | int max = Math.max(getWidth(), getHeight()); 33 | int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); 34 | super.onMeasure(measureSpec, measureSpec); 35 | return; 36 | } 37 | 38 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 39 | } 40 | 41 | @Override 42 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 43 | super.onLayout(changed, left, top, right, bottom); 44 | if (delegate.getRadiusHalfHeightEnable()) { 45 | delegate.setRadius(getHeight() / 2); 46 | }else { 47 | delegate.setBgSelector(); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /library/src/main/java/com/aries/ui/view/radius/RadiusLinearLayout.java: -------------------------------------------------------------------------------- 1 | package com.aries.ui.view.radius; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.LinearLayout; 6 | 7 | /** 8 | * Created: AriesHoo on 2017-02-10 14:25 9 | * Function:用于需要圆角矩形框背景的LinearLayout的情况,减少直接使用LinearLayout时引入的shape资源文件 10 | * Desc: 11 | */ 12 | public class RadiusLinearLayout extends LinearLayout { 13 | private RadiusViewDelegate delegate; 14 | 15 | public RadiusLinearLayout(Context context) { 16 | this(context, null); 17 | } 18 | 19 | public RadiusLinearLayout(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | delegate = new RadiusViewDelegate(this, context, attrs); 22 | } 23 | 24 | /** 25 | * use delegate to set attr 26 | */ 27 | public RadiusViewDelegate getDelegate() { 28 | return delegate; 29 | } 30 | 31 | @Override 32 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 33 | if (delegate.getWidthHeightEqualEnable() && getWidth() > 0 && getHeight() > 0) { 34 | int max = Math.max(getWidth(), getHeight()); 35 | int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); 36 | super.onMeasure(measureSpec, measureSpec); 37 | return; 38 | } 39 | 40 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 41 | } 42 | 43 | @Override 44 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 45 | super.onLayout(changed, left, top, right, bottom); 46 | if (delegate.getRadiusHalfHeightEnable()) { 47 | delegate.setRadius(getHeight() / 2); 48 | } else { 49 | delegate.setBgSelector(); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /library/src/main/java/com/aries/ui/view/radius/RadiusRelativeLayout.java: -------------------------------------------------------------------------------- 1 | package com.aries.ui.view.radius; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.RelativeLayout; 6 | 7 | /** 8 | * Created: AriesHoo on 2017-02-10 14:24 9 | * Function:用于需要圆角矩形框背景的RelativeLayout的情况,减少直接使用RelativeLayout时引入的shape资源文件 10 | * Desc: 11 | */ 12 | public class RadiusRelativeLayout extends RelativeLayout { 13 | private RadiusViewDelegate delegate; 14 | 15 | public RadiusRelativeLayout(Context context) { 16 | this(context, null); 17 | } 18 | 19 | public RadiusRelativeLayout(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | delegate = new RadiusViewDelegate(this, context, attrs); 22 | } 23 | 24 | /** 25 | * use delegate to set attr 26 | */ 27 | public RadiusViewDelegate getDelegate() { 28 | return delegate; 29 | } 30 | 31 | @Override 32 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 33 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 34 | if (delegate.getWidthHeightEqualEnable() && getWidth() > 0 && getHeight() > 0) { 35 | int max = Math.max(getWidth(), getHeight()); 36 | int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); 37 | super.onMeasure(measureSpec, measureSpec); 38 | return; 39 | } 40 | 41 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 42 | } 43 | 44 | @Override 45 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 46 | super.onLayout(changed, left, top, right, bottom); 47 | if (delegate.getRadiusHalfHeightEnable()) { 48 | delegate.setRadius(getHeight() / 2); 49 | } else { 50 | delegate.setBgSelector(); 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /library/src/main/java/com/aries/ui/view/radius/RadiusTextView.java: -------------------------------------------------------------------------------- 1 | package com.aries.ui.view.radius; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.TextView; 6 | 7 | /** 8 | * Created: AriesHoo on 2017-02-10 14:24 9 | * Function:用于需要圆角矩形框背景的TextView的情况,减少直接使用TextView时引入的shape资源文件 10 | * Desc: 11 | */ 12 | public class RadiusTextView extends TextView { 13 | private RadiusViewDelegate delegate; 14 | 15 | public RadiusTextView(Context context) { 16 | this(context, null); 17 | } 18 | 19 | public RadiusTextView(Context context, AttributeSet attrs) { 20 | this(context, attrs, 0); 21 | } 22 | 23 | public RadiusTextView(Context context, AttributeSet attrs, int defStyleAttr) { 24 | super(context, attrs, defStyleAttr); 25 | delegate = new RadiusViewDelegate(this, context, attrs); 26 | } 27 | 28 | /** 29 | * use delegate to set attr 30 | */ 31 | public RadiusViewDelegate getDelegate() { 32 | return delegate; 33 | } 34 | 35 | @Override 36 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 37 | if (delegate.getWidthHeightEqualEnable() && getWidth() > 0 && getHeight() > 0) { 38 | int max = Math.max(getWidth(), getHeight()); 39 | int measureSpec = MeasureSpec.makeMeasureSpec(max, MeasureSpec.EXACTLY); 40 | super.onMeasure(measureSpec, measureSpec); 41 | return; 42 | } 43 | 44 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 45 | } 46 | 47 | @Override 48 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 49 | super.onLayout(changed, left, top, right, bottom); 50 | if (delegate.getRadiusHalfHeightEnable()) { 51 | delegate.setRadius(getHeight() / 2); 52 | } else { 53 | delegate.setBgSelector(); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /library/src/main/java/com/aries/ui/view/radius/RadiusViewDelegate.java: -------------------------------------------------------------------------------- 1 | package com.aries.ui.view.radius; 2 | 3 | import android.annotation.TargetApi; 4 | import android.content.Context; 5 | import android.content.res.ColorStateList; 6 | import android.content.res.TypedArray; 7 | import android.graphics.Color; 8 | import android.graphics.drawable.GradientDrawable; 9 | import android.graphics.drawable.RippleDrawable; 10 | import android.graphics.drawable.StateListDrawable; 11 | import android.os.Build; 12 | import android.util.AttributeSet; 13 | import android.view.View; 14 | import android.widget.EditText; 15 | import android.widget.TextView; 16 | 17 | /** 18 | * Created: AriesHoo on 2017-02-10 14:25 19 | * Function: 公共属性解析类 20 | * Desc: 21 | */ 22 | public class RadiusViewDelegate { 23 | private View view; 24 | private Context context; 25 | private GradientDrawable gdBackground = new GradientDrawable(); 26 | private GradientDrawable gdBackgroundPressed = new GradientDrawable(); 27 | private GradientDrawable gdBackgroundEnabled = new GradientDrawable(); 28 | private int backgroundColor; 29 | private int backgroundPressedColor; 30 | private int backgroundEnabledColor; 31 | private int radius; 32 | private int topLeftRadius; 33 | private int topRightRadius; 34 | private int bottomLeftRadius; 35 | private int bottomRightRadius; 36 | private int strokeWidth; 37 | private int strokeColor; 38 | private int strokePressedColor; 39 | private int strokeEnabledColor; 40 | private int textColor; 41 | private int textPressedColor; 42 | private int textEnabledColor; 43 | private boolean isRadiusHalfHeight; 44 | private boolean isWidthHeightEqual; 45 | private boolean isRippleEnable; 46 | private float[] radiusArr = new float[8]; 47 | 48 | public RadiusViewDelegate(View view, Context context, AttributeSet attrs) { 49 | this.view = view; 50 | this.context = context; 51 | obtainAttributes(context, attrs); 52 | } 53 | 54 | private void obtainAttributes(Context context, AttributeSet attrs) { 55 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RadiusTextView); 56 | backgroundColor = ta.getColor(R.styleable.RadiusTextView_rv_backgroundColor, Color.TRANSPARENT); 57 | backgroundPressedColor = ta.getColor(R.styleable.RadiusTextView_rv_backgroundPressedColor, Integer.MAX_VALUE); 58 | backgroundEnabledColor = ta.getColor(R.styleable.RadiusTextView_rv_backgroundEnabledColor, Integer.MAX_VALUE); 59 | radius = ta.getDimensionPixelSize(R.styleable.RadiusTextView_rv_radius, 0); 60 | strokeWidth = ta.getDimensionPixelSize(R.styleable.RadiusTextView_rv_strokeWidth, 0); 61 | strokeColor = ta.getColor(R.styleable.RadiusTextView_rv_strokeColor, Color.TRANSPARENT); 62 | strokePressedColor = ta.getColor(R.styleable.RadiusTextView_rv_strokePressedColor, Integer.MAX_VALUE); 63 | strokeEnabledColor = ta.getColor(R.styleable.RadiusTextView_rv_strokeEnabledColor, Integer.MAX_VALUE); 64 | textColor = ta.getColor(R.styleable.RadiusTextView_rv_textColor, Integer.MAX_VALUE); 65 | textPressedColor = ta.getColor(R.styleable.RadiusTextView_rv_textPressedColor, Integer.MAX_VALUE); 66 | textEnabledColor = ta.getColor(R.styleable.RadiusTextView_rv_textEnabledColor, Integer.MAX_VALUE); 67 | isRadiusHalfHeight = ta.getBoolean(R.styleable.RadiusTextView_rv_radiusHalfHeightEnable, false); 68 | isWidthHeightEqual = ta.getBoolean(R.styleable.RadiusTextView_rv_widthHeightEqualEnable, false); 69 | topLeftRadius = ta.getDimensionPixelSize(R.styleable.RadiusTextView_rv_topLeftRadius, 0); 70 | topRightRadius = ta.getDimensionPixelSize(R.styleable.RadiusTextView_rv_topRightRadius, 0); 71 | bottomLeftRadius = ta.getDimensionPixelSize(R.styleable.RadiusTextView_rv_bottomLeftRadius, 0); 72 | bottomRightRadius = ta.getDimensionPixelSize(R.styleable.RadiusTextView_rv_bottomRightRadius, 0); 73 | isRippleEnable = ta.getBoolean(R.styleable.RadiusTextView_rv_rippleEnable, true); 74 | ta.recycle(); 75 | } 76 | 77 | public void setBackgroundColor(int backgroundColor) { 78 | this.backgroundColor = backgroundColor; 79 | setBgSelector(); 80 | } 81 | 82 | public void setBackgroundPressedColor(int backgroundPressedColor) { 83 | this.backgroundPressedColor = backgroundPressedColor; 84 | setBgSelector(); 85 | } 86 | 87 | public void setBackgroundEnabledColor(int backgroundEnabledColor) { 88 | this.backgroundEnabledColor = backgroundEnabledColor; 89 | setBgSelector(); 90 | } 91 | 92 | public void setRadius(int radius) { 93 | this.radius = dp2px(radius); 94 | setBgSelector(); 95 | } 96 | 97 | public void setStrokeWidth(int strokeWidth) { 98 | this.strokeWidth = dp2px(strokeWidth); 99 | setBgSelector(); 100 | } 101 | 102 | public void setStrokeColor(int strokeColor) { 103 | this.strokeColor = strokeColor; 104 | setBgSelector(); 105 | } 106 | 107 | public void setStrokePressedColor(int strokePressedColor) { 108 | this.strokePressedColor = strokePressedColor; 109 | setBgSelector(); 110 | } 111 | 112 | public void setStrokeEnabledColor(int strokeEnabledColor) { 113 | this.strokeEnabledColor = strokeEnabledColor; 114 | setBgSelector(); 115 | } 116 | 117 | public void setTextColor(int textColor) { 118 | this.textColor = textColor; 119 | setBgSelector(); 120 | } 121 | 122 | public void setTextPressedColor(int textPressedColor) { 123 | this.textPressedColor = textPressedColor; 124 | setBgSelector(); 125 | } 126 | 127 | public void setTextEnabledColor(int textEnabledColor) { 128 | this.textEnabledColor = textEnabledColor; 129 | setBgSelector(); 130 | } 131 | 132 | public void setEadiusHalfHeightEnable(boolean isRadiusHalfHeight) { 133 | this.isRadiusHalfHeight = isRadiusHalfHeight; 134 | setBgSelector(); 135 | } 136 | 137 | public void setWidthHeightEqualEnable(boolean isWidthHeightEqual) { 138 | this.isWidthHeightEqual = isWidthHeightEqual; 139 | setBgSelector(); 140 | } 141 | 142 | public void setTopLeftRadius(int topLeftRadius) { 143 | this.topLeftRadius = topLeftRadius; 144 | setBgSelector(); 145 | } 146 | 147 | public void setTopRightRadius(int topRightRadius) { 148 | this.topRightRadius = topRightRadius; 149 | setBgSelector(); 150 | } 151 | 152 | public void setBottomLeftRadius(int bottomLeftRadius) { 153 | this.bottomLeftRadius = bottomLeftRadius; 154 | setBgSelector(); 155 | } 156 | 157 | public void setBottomRightRadius(int bottomRightRadius) { 158 | this.bottomRightRadius = bottomRightRadius; 159 | setBgSelector(); 160 | } 161 | 162 | public int getBackgroundColor() { 163 | return backgroundColor; 164 | } 165 | 166 | public int getbackgroundPressedColor() { 167 | return backgroundPressedColor; 168 | } 169 | 170 | public int getRadius() { 171 | return radius; 172 | } 173 | 174 | public int getStrokeWidth() { 175 | return strokeWidth; 176 | } 177 | 178 | public int getStrokeColor() { 179 | return strokeColor; 180 | } 181 | 182 | public int getStrokePressedColor() { 183 | return strokePressedColor; 184 | } 185 | 186 | public int getTextPressedColor() { 187 | return textPressedColor; 188 | } 189 | 190 | public boolean getRadiusHalfHeightEnable() { 191 | return isRadiusHalfHeight; 192 | } 193 | 194 | public boolean getWidthHeightEqualEnable() { 195 | return isWidthHeightEqual; 196 | } 197 | 198 | public int gettopLeftRadius() { 199 | return topLeftRadius; 200 | } 201 | 202 | public int gettopRightRadius() { 203 | return topRightRadius; 204 | } 205 | 206 | public int getbottomLeftRadius() { 207 | return bottomLeftRadius; 208 | } 209 | 210 | public int getbottomRightRadius() { 211 | return bottomRightRadius; 212 | } 213 | 214 | protected int dp2px(float dp) { 215 | final float scale = context.getResources().getDisplayMetrics().density; 216 | return (int) (dp * scale + 0.5f); 217 | } 218 | 219 | protected int sp2px(float sp) { 220 | final float scale = this.context.getResources().getDisplayMetrics().scaledDensity; 221 | return (int) (sp * scale + 0.5f); 222 | } 223 | 224 | private void setDrawable(GradientDrawable gd, int color, int strokeColor) { 225 | gd.setColor(color); 226 | 227 | if (topLeftRadius > 0 || topRightRadius > 0 || bottomRightRadius > 0 || bottomLeftRadius > 0) { 228 | /**The corners are ordered top-left, top-right, bottom-right, bottom-left*/ 229 | radiusArr[0] = topLeftRadius; 230 | radiusArr[1] = topLeftRadius; 231 | radiusArr[2] = topRightRadius; 232 | radiusArr[3] = topRightRadius; 233 | radiusArr[4] = bottomRightRadius; 234 | radiusArr[5] = bottomRightRadius; 235 | radiusArr[6] = bottomLeftRadius; 236 | radiusArr[7] = bottomLeftRadius; 237 | gd.setCornerRadii(radiusArr); 238 | } else { 239 | gd.setCornerRadius(radius); 240 | } 241 | gd.setStroke(strokeWidth, strokeColor); 242 | } 243 | 244 | public void setBgSelector() { 245 | StateListDrawable bg = new StateListDrawable(); 246 | setDrawable(gdBackground, backgroundColor, strokeColor); 247 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && isRippleEnable && view.isEnabled()) { 248 | RippleDrawable rippleDrawable = new RippleDrawable( 249 | getColorSelector(backgroundColor, 250 | backgroundPressedColor, 251 | backgroundEnabledColor == Integer.MAX_VALUE ? backgroundColor : backgroundEnabledColor), gdBackground, null); 252 | view.setBackground(rippleDrawable); 253 | } else { 254 | if (view.isEnabled()) { 255 | bg.addState(new int[]{-android.R.attr.state_pressed, -android.R.attr.state_selected}, gdBackground); 256 | } 257 | if (backgroundPressedColor != Integer.MAX_VALUE || strokePressedColor != Integer.MAX_VALUE) { 258 | setDrawable(gdBackgroundPressed, 259 | backgroundPressedColor == Integer.MAX_VALUE ? backgroundColor : backgroundPressedColor, 260 | strokePressedColor == Integer.MAX_VALUE ? strokeColor : strokePressedColor); 261 | bg.addState(new int[]{android.R.attr.state_pressed, android.R.attr.state_pressed}, gdBackgroundPressed); 262 | } 263 | if (backgroundEnabledColor != Integer.MAX_VALUE || strokeEnabledColor != Integer.MAX_VALUE) { 264 | setDrawable(gdBackgroundEnabled, 265 | backgroundEnabledColor == Integer.MAX_VALUE ? backgroundColor : backgroundEnabledColor, 266 | strokeEnabledColor == Integer.MAX_VALUE ? strokeColor : strokeEnabledColor); 267 | bg.addState(new int[]{-android.R.attr.state_enabled}, gdBackgroundEnabled); 268 | } 269 | 270 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {//16 271 | view.setBackground(bg); 272 | } else { 273 | view.setBackgroundDrawable(bg); 274 | } 275 | } 276 | 277 | if (view instanceof TextView || view instanceof EditText) { 278 | TextView textView = (TextView) view; 279 | if (textPressedColor != Integer.MAX_VALUE) { 280 | textColor = (textColor == Integer.MAX_VALUE ? textView.getTextColors().getDefaultColor() : textColor); 281 | if (textColor != Integer.MAX_VALUE || textPressedColor != Integer.MAX_VALUE || textEnabledColor != Integer.MAX_VALUE) { 282 | ColorStateList colorStateList = 283 | getColorSelector(textColor, 284 | textPressedColor == Integer.MAX_VALUE ? textColor : textPressedColor, 285 | textEnabledColor == Integer.MAX_VALUE ? textColor : textEnabledColor); 286 | textView.setTextColor(colorStateList); 287 | } 288 | } 289 | } 290 | } 291 | 292 | @TargetApi(Build.VERSION_CODES.HONEYCOMB) 293 | private ColorStateList getColorSelector(int normalColor, int pressedColor, int enabledColor) { 294 | return new ColorStateList( 295 | new int[][]{ 296 | new int[]{android.R.attr.state_focused}, 297 | new int[]{android.R.attr.state_activated}, 298 | new int[]{android.R.attr.state_pressed}, 299 | new int[]{-android.R.attr.state_enabled}, 300 | new int[]{} 301 | }, 302 | new int[]{ 303 | pressedColor, 304 | pressedColor, 305 | pressedColor, 306 | enabledColor, 307 | normalColor 308 | } 309 | ); 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /library/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /screenshot/00.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AriesHoo/RadiusView/c065ed49f5e9aa998ebbe6a60099b69db18db869/screenshot/00.gif -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':library' 2 | --------------------------------------------------------------------------------