├── .gitignore ├── README.md ├── androidview ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── cy │ │ └── androidview │ │ ├── BitmapUtils.java │ │ ├── LogUtils.java │ │ ├── ScaleFrameLayout.java │ │ ├── ScreenPercentFrameLayout.java │ │ ├── ScreenUtils.java │ │ ├── TimeAndAgeUtils.java │ │ ├── VersionUtils.java │ │ ├── ViewMeasureUtils.java │ │ ├── cardview │ │ ├── ButtonCard.java │ │ ├── CardViewApi21Impl.java │ │ ├── CardViewDelegate.java │ │ ├── CardViewImpl.java │ │ ├── FrameLayoutCard.java │ │ ├── ImageViewCard.java │ │ ├── LinearLayoutCard.java │ │ ├── RelativeLayoutCard.java │ │ ├── RoundRectDrawable.java │ │ ├── RoundRectDrawableWithShadow.java │ │ └── TextViewCard.java │ │ ├── colorfilterview │ │ ├── ColorFilterCy.java │ │ ├── IColorFilter.java │ │ └── ImageViewColorFilter.java │ │ ├── edittext │ │ └── TextWatcherImpl.java │ │ ├── progress │ │ ├── ProgressWeightView.java │ │ └── VCutProgressView.java │ │ ├── rectangleview │ │ ├── ButtonRectangle.java │ │ ├── FrameLayoutRectangle.java │ │ ├── IRectangle.java │ │ ├── ImageViewRectangle.java │ │ ├── LinearLayoutRectangle.java │ │ ├── RectangleRatio.java │ │ ├── RelativeLayoutRectangle.java │ │ └── TextViewRectangle.java │ │ ├── rippleview │ │ ├── ButtonRipple.java │ │ ├── FrameLayoutRipple.java │ │ ├── IRipple.java │ │ ├── ImageViewRipple.java │ │ ├── LinearLayoutRipple.java │ │ ├── RelativeLayoutRipple.java │ │ ├── Ripple.java │ │ └── TextViewRipple.java │ │ ├── roundview │ │ ├── ButtonRound.java │ │ ├── FrameLayoutRound.java │ │ ├── IRound.java │ │ ├── ImageViewRound.java │ │ ├── LinearLayoutRound.java │ │ ├── RelativeLayoutRound.java │ │ ├── Round.java │ │ ├── TextViewRound.java │ │ └── helper │ │ │ ├── RCAttrs.java │ │ │ └── RCHelper.java │ │ ├── scrollview │ │ └── ScrollViewOverNever.java │ │ ├── selectorview │ │ ├── CheckBoxSelector.java │ │ ├── FrameLayoutSelector.java │ │ ├── ImageViewSelector.java │ │ ├── RadioButtonSelector.java │ │ └── TextViewSelector.java │ │ ├── shadow │ │ └── ImageViewShadow.java │ │ ├── shapeview │ │ ├── ButtonShape.java │ │ ├── FrameLayoutShape.java │ │ ├── IShape.java │ │ ├── LinearLayoutShape.java │ │ ├── RelativeLayoutShape.java │ │ ├── ShapeBackground.java │ │ └── TextViewShape.java │ │ ├── swipe │ │ ├── SwipeActivity.java │ │ ├── SwipeLayout.java │ │ └── TransparentUtils.java │ │ └── textview │ │ ├── LineMiddleTextView.java │ │ ├── MultiColorTextView.java │ │ └── SingleLineTextView.java │ └── res │ ├── anim │ ├── slide_in_right.xml │ └── slide_out_right.xml │ ├── drawable-xxhdpi │ ├── close_white.png │ ├── copy_white.png │ ├── eidit_white.png │ ├── rotate_3d_white.png │ └── rotate_white.png │ └── values │ ├── attrs.xml │ ├── colors.xml │ ├── dimens.xml │ ├── strings.xml │ └── styles.xml ├── app ├── .gitignore ├── build.gradle ├── proguard-rules.pro └── src │ └── main │ ├── AndroidManifest.xml │ ├── java │ └── com │ │ └── cy │ │ └── necessaryviewmaster │ │ ├── AnimateActivity.java │ │ ├── BaseActivity.java │ │ ├── CardActivity.java │ │ ├── ClickActivity.java │ │ ├── CornerView.java │ │ ├── FrameLayoutScale.java │ │ ├── LogUtils.java │ │ ├── MainActivity.java │ │ ├── ProgressActivity.java │ │ ├── RectangleActivity.java │ │ ├── RoundedIVActivity.java │ │ ├── SelectorActivity.java │ │ ├── ShadowActivity.java │ │ └── ShapeActivity.java │ └── res │ ├── drawable-xhdpi │ ├── after_sale_icon.png │ ├── back.png │ ├── cb_zuji_normal.png │ ├── cb_zuji_selected.png │ ├── flash_aotu_white.png │ ├── flash_on_white.png │ ├── hg.jpg │ ├── home_paihang_renqi.png │ ├── mn.jpg │ ├── pic_big.jpg │ ├── pic_edit_filter.png │ ├── search.png │ ├── search_home.png │ └── yuanxiangji_white.png │ ├── layout │ ├── activity_animate.xml │ ├── activity_card.xml │ ├── activity_main.xml │ ├── activity_progress.xml │ ├── activity_rectangle.xml │ ├── activity_ripple_color_filter.xml │ ├── activity_round.xml │ ├── activity_selector.xml │ ├── activity_shadow.xml │ ├── activity_shape.xml │ └── activity_stick.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 ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat └── settings.gradle /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .gradle 3 | /local.properties 4 | /.idea/workspace.xml 5 | /.idea/libraries 6 | .DS_Store 7 | /build 8 | /captures 9 | .externalNativeBuild 10 | -------------------------------------------------------------------------------- /androidview/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /androidview/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | apply plugin: 'com.github.dcendents.android-maven' 3 | 4 | group='com.github.AnJiaoDe' 5 | android { 6 | compileSdkVersion var.compileSdkVersion 7 | buildToolsVersion var.buildToolsVersion 8 | 9 | defaultConfig { 10 | minSdkVersion var.minSdkVersion 11 | targetSdkVersion var.targetSdkVersion 12 | versionCode 1 13 | versionName "1.0" 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | } 16 | buildTypes { 17 | release { 18 | minifyEnabled false 19 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 20 | } 21 | } 22 | } 23 | //---------------------------------------------下面的必加,加上下面的作用是在上传后会带上注释,不然会发现没有注释 24 | // 打包源码 25 | task sourcesJar(type: Jar) { 26 | from android.sourceSets.main.java.srcDirs 27 | classifier = 'sources' 28 | } 29 | artifacts { 30 | archives sourcesJar 31 | } 32 | 33 | dependencies { 34 | implementation fileTree(dir: 'libs', include: ['*.jar']) 35 | 36 | compileOnly 'androidx.appcompat:appcompat:1.1.0' 37 | } 38 | -------------------------------------------------------------------------------- /androidview/proguard-rules.pro: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/androidview/proguard-rules.pro -------------------------------------------------------------------------------- /androidview/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/LogUtils.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by lenovo on 2017/8/20. 7 | */ 8 | 9 | public class LogUtils { 10 | private static boolean DEBUG = BuildConfig.DEBUG; 11 | 12 | private LogUtils() { 13 | } 14 | public static boolean isDEBUG() { 15 | return DEBUG; 16 | } 17 | 18 | public static void logD(Object tag, Object content) { 19 | if(DEBUG==false)return; 20 | if (tag == null) tag = "LOG_I"; 21 | Log.d(String.valueOf(tag), "----------------------------------->>>>" + content); 22 | } 23 | public static void logI(Object tag, Object content) { 24 | if(DEBUG==false)return; 25 | if (tag == null) tag = "LOG_I"; 26 | Log.i(String.valueOf(tag), "----------------------------------->>>>" + content); 27 | } 28 | public static void logE(Object tag, Object content) { 29 | if(DEBUG==false)return; 30 | if (tag == null) tag = "LOG_E"; 31 | Log.e(String.valueOf(tag), "----------------------------------->>>>" + content); 32 | } 33 | 34 | 35 | public static void logD(Object content) { 36 | logD(null,content); 37 | } 38 | public static void logI(Object content) { 39 | logI(null,content); 40 | } 41 | public static void logE(Object content) { 42 | logE(null,content); 43 | } 44 | 45 | public static void log(Object tag, Object content) { 46 | logE(tag,content); 47 | } 48 | public static void log(Object content) { 49 | logE(content); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/ScaleFrameLayout.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.util.AttributeSet; 6 | import android.view.GestureDetector; 7 | import android.view.MotionEvent; 8 | import android.view.ScaleGestureDetector; 9 | import android.widget.FrameLayout; 10 | 11 | import androidx.annotation.NonNull; 12 | import androidx.annotation.Nullable; 13 | 14 | public class ScaleFrameLayout extends FrameLayout { 15 | private float zoom = 1; // 缩放 16 | private float zoom_max = 10; // 缩放 17 | private float zoom_min = 0.1f; // 缩放 18 | 19 | private float translate_x, translate_y; 20 | 21 | private boolean enableZoom = true; 22 | private boolean touchEventDownReturnTrue = true; 23 | private boolean touchEventUpReset = false; 24 | 25 | private Callback callback; 26 | 27 | private GestureDetector gestureDetector; 28 | private ScaleGestureDetector scaleGestureDetector; 29 | private boolean useDoubleTap=true; 30 | private boolean useScroll=true; 31 | public ScaleFrameLayout(@NonNull Context context) { 32 | this(context, null); 33 | } 34 | 35 | public ScaleFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { 36 | super(context, attrs); 37 | gestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { 38 | @Override 39 | public boolean onDoubleTap(MotionEvent e) { 40 | if(!useDoubleTap)return true; 41 | if (zoom == 1.f) { 42 | zoom = 2.f; 43 | } else { 44 | zoom = 1.f; 45 | translate_x = 0; 46 | translate_y = 0; 47 | } 48 | invalidate(); 49 | return true; 50 | } 51 | 52 | @Override 53 | public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { 54 | if(!useScroll)return true; 55 | translate_x -= distanceX; 56 | translate_y -= distanceY; 57 | translate_x = Math.max(-getWidth()*0.5f, Math.min(getWidth()*0.5f, translate_x)); 58 | translate_y = Math.max(-getHeight()*0.5f, Math.min(getHeight()*0.5f, translate_y)); 59 | invalidate(); 60 | return true; 61 | } 62 | 63 | @Override 64 | public boolean onSingleTapUp(MotionEvent e) { 65 | if (callback != null) callback.onSingleTapUp(); 66 | return super.onSingleTapUp(e); 67 | } 68 | }); 69 | scaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureDetector.SimpleOnScaleGestureListener() { 70 | @Override 71 | public boolean onScale(ScaleGestureDetector detector) { 72 | if (enableZoom) { 73 | zoom *= detector.getScaleFactor(); 74 | zoom = Math.max(zoom_min, Math.min(zoom, zoom_max)); 75 | invalidate(); 76 | } 77 | return true; 78 | } 79 | }); 80 | } 81 | 82 | public void setCallback(Callback callback) { 83 | this.callback = callback; 84 | } 85 | 86 | 87 | 88 | @Override 89 | protected void dispatchDraw(Canvas canvas) { 90 | canvas.scale(zoom, zoom, getWidth() * 1f / 2 + translate_x, getHeight() * 1f / 2 + translate_y); 91 | //必须先scale后translate,否则会往相反方向translate 92 | canvas.translate(translate_x, translate_y); 93 | if (callback != null) callback.onCanvasChange(zoom, translate_x, translate_y); 94 | super.dispatchDraw(canvas); 95 | } 96 | 97 | @Override 98 | public boolean onTouchEvent(MotionEvent event) { 99 | //处理多指触摸,这2个玩意是不能少的,否则贼复杂,还搞不定 100 | scaleGestureDetector.onTouchEvent(event); 101 | gestureDetector.onTouchEvent(event); 102 | switch (event.getActionMasked()) { 103 | case MotionEvent.ACTION_DOWN: 104 | if (touchEventDownReturnTrue) return true; 105 | break; 106 | case MotionEvent.ACTION_POINTER_UP: 107 | case MotionEvent.ACTION_UP: 108 | if (touchEventUpReset) { 109 | zoom = 1; 110 | translate_x = 0; 111 | translate_y = 0; 112 | invalidate(); 113 | } 114 | break; 115 | } 116 | return super.onTouchEvent(event); 117 | } 118 | public boolean isUseDoubleTap() { 119 | return useDoubleTap; 120 | } 121 | 122 | public ScaleFrameLayout setUseDoubleTap(boolean useDoubleTap) { 123 | this.useDoubleTap = useDoubleTap; 124 | return this; 125 | } 126 | 127 | public boolean isUseScroll() { 128 | return useScroll; 129 | } 130 | 131 | public ScaleFrameLayout setUseScroll(boolean useScroll) { 132 | this.useScroll = useScroll; 133 | return this; 134 | } 135 | 136 | public float getZoom_max() { 137 | return zoom_max; 138 | } 139 | 140 | public ScaleFrameLayout setZoom_max(float zoom_max) { 141 | this.zoom_max = zoom_max; 142 | return this; 143 | } 144 | 145 | public float getZoom_min() { 146 | return zoom_min; 147 | } 148 | 149 | public ScaleFrameLayout setZoom_min(float zoom_min) { 150 | this.zoom_min = zoom_min; 151 | return this; 152 | } 153 | 154 | public float getZoom() { 155 | return zoom; 156 | } 157 | 158 | public float getTranslate_x() { 159 | return translate_x; 160 | } 161 | 162 | public float getTranslate_y() { 163 | return translate_y; 164 | } 165 | 166 | public boolean isEnableZoom() { 167 | return enableZoom; 168 | } 169 | 170 | public ScaleFrameLayout setEnableZoom(boolean enableZoom) { 171 | this.enableZoom = enableZoom; 172 | return this; 173 | } 174 | 175 | 176 | public boolean isTouchEventDownReturnTrue() { 177 | return touchEventDownReturnTrue; 178 | } 179 | 180 | public ScaleFrameLayout setTouchEventDownReturnTrue(boolean touchEventDownReturnTrue) { 181 | this.touchEventDownReturnTrue = touchEventDownReturnTrue; 182 | return this; 183 | } 184 | 185 | public boolean isTouchEventUpReset() { 186 | return touchEventUpReset; 187 | } 188 | 189 | public ScaleFrameLayout setTouchEventUpReset(boolean touchEventUpReset) { 190 | this.touchEventUpReset = touchEventUpReset; 191 | return this; 192 | } 193 | 194 | public static interface Callback { 195 | public void onCanvasChange(float scale, float dx, float dy); 196 | 197 | public void onSingleTapUp(); 198 | } 199 | } 200 | 201 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/ScreenPercentFrameLayout.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | 7 | import com.cy.androidview.rippleview.FrameLayoutRipple; 8 | 9 | /** 10 | * @Description: 11 | * @Author: cy 12 | * @CreateDate: 2020/9/5 17:20 13 | * @UpdateUser: 14 | * @UpdateDate: 2020/9/5 17:20 15 | * @UpdateRemark: 16 | * @Version: 17 | */ 18 | public class ScreenPercentFrameLayout extends FrameLayoutRipple { 19 | private float width_percent=0; 20 | private float height_percent=0; 21 | 22 | public ScreenPercentFrameLayout(Context context, AttributeSet attrs) { 23 | super(context, attrs); 24 | TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.ScreenPercentFrameLayout); 25 | width_percent=typedArray.getFloat(R.styleable.ScreenPercentFrameLayout_cy_width_percent,width_percent); 26 | height_percent=typedArray.getFloat(R.styleable.ScreenPercentFrameLayout_cy_height_percent,height_percent); 27 | } 28 | 29 | @Override 30 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 31 | super.onMeasure(widthMeasureSpec, heightMeasureSpec); 32 | int measuredWidth=width_percent==0?getMeasuredWidth():(int)(ScreenUtils.getScreenWidth(getContext())*width_percent); 33 | int measuredHeigh= height_percent==0?getMeasuredHeight(): (int) (ScreenUtils.getScreenHeight(getContext()) * height_percent); 34 | setMeasuredDimension(measuredWidth,measuredHeigh); 35 | measureChildren(MeasureSpec.makeMeasureSpec(measuredWidth,MeasureSpec.EXACTLY),MeasureSpec.makeMeasureSpec(measuredHeigh,MeasureSpec.EXACTLY)); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/VersionUtils.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview; 2 | 3 | import android.app.ActivityManager; 4 | import android.content.Context; 5 | import android.content.pm.ApplicationInfo; 6 | import android.content.pm.PackageInfo; 7 | import android.content.pm.PackageManager; 8 | import android.graphics.drawable.Drawable; 9 | 10 | /** 11 | * Created by lenovo on 2017/9/20. 12 | */ 13 | 14 | public class VersionUtils { 15 | public static boolean isMonkey(){ 16 | return ActivityManager.isUserAMonkey()||ActivityManager.isRunningInTestHarness(); 17 | } 18 | /** 19 | * @param context 20 | * @param apkPath apk文件路径 21 | * @return 22 | */ 23 | 24 | public static Drawable getApkIcon(Context context, String apkPath) { 25 | PackageManager packageManager = context.getPackageManager(); 26 | PackageInfo packageInfo = packageManager.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES); 27 | if (packageInfo != null) { 28 | ApplicationInfo info = packageInfo.applicationInfo; 29 | info.sourceDir = apkPath; 30 | info.publicSourceDir = apkPath; 31 | try { 32 | return info.loadIcon(packageManager); 33 | } catch (Exception e) { 34 | 35 | } 36 | } 37 | return null; 38 | } 39 | /** 40 | * 获取应用程序名称 41 | */ 42 | public static String getAppName(Context context) { 43 | try { 44 | PackageManager packageManager = context.getPackageManager(); 45 | PackageInfo packageInfo = packageManager.getPackageInfo( 46 | context.getPackageName(), 0); 47 | int labelRes = packageInfo.applicationInfo.labelRes; 48 | return context.getResources().getString(labelRes); 49 | } catch (Exception e) { 50 | e.printStackTrace(); 51 | } 52 | return ""; 53 | } 54 | 55 | public static String getApplicationMeta(Context context,String key) { 56 | String value = ""; 57 | try { 58 | 59 | ApplicationInfo appInfo = context.getPackageManager().getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); 60 | if (appInfo == null || appInfo.metaData == null) return value; 61 | value = appInfo.metaData.get(key).toString(); 62 | } catch (PackageManager.NameNotFoundException e) { 63 | e.printStackTrace(); 64 | } 65 | return value; 66 | } 67 | 68 | /* 获取本地软件版本号 69 | */ 70 | public static int getVersionCode(Context ctx) { 71 | int localVersion = 0; 72 | try { 73 | PackageInfo packageInfo = ctx.getApplicationContext() 74 | .getPackageManager() 75 | .getPackageInfo(ctx.getPackageName(), 0); 76 | localVersion = packageInfo.versionCode; 77 | // LogUtil.d("TAG", "本软件的版本号。。" + localVersion); 78 | } catch (PackageManager.NameNotFoundException e) { 79 | e.printStackTrace(); 80 | } 81 | return localVersion; 82 | } 83 | 84 | // public static String getMetaData(Context context,String key) { 85 | // //在application应用元素。 86 | // ApplicationInfo appInfo = null; 87 | // try { 88 | // appInfo = context.getPackageManager() 89 | // .getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); 90 | // if (appInfo != null) return appInfo.metaData.getString(key); 91 | // } catch (PackageManager.NameNotFoundException e) { 92 | // e.printStackTrace(); 93 | // } 94 | // return ""; 95 | // } 96 | 97 | /** 98 | * 获取本地软件版本号名称 99 | */ 100 | public static String getVersionName(Context ctx) { 101 | String localVersion = ""; 102 | try { 103 | PackageInfo packageInfo = ctx.getApplicationContext() 104 | .getPackageManager() 105 | .getPackageInfo(ctx.getPackageName(), 0); 106 | localVersion = packageInfo.versionName; 107 | // LogUtil.d("TAG", "本软件的版本号。。" + localVersion); 108 | } catch (PackageManager.NameNotFoundException e) { 109 | e.printStackTrace(); 110 | } 111 | return localVersion; 112 | } 113 | 114 | /** 115 | * 获取渠道名 116 | * 117 | * @param context 此处习惯性的设置为activity,实际上context就可以 118 | * @return 如果没有获取成功,那么返回值为空 119 | */ 120 | public static String getChannelName(Context context) { 121 | String channelName = ""; 122 | try { 123 | PackageManager packageManager = context.getPackageManager(); 124 | if (packageManager != null) { 125 | //注意此处为ApplicationInfo 而不是 ActivityInfo,因为友盟设置的meta-data是在application标签中,而不是某activity标签中,所以用ApplicationInfo 126 | ApplicationInfo applicationInfo = packageManager. 127 | getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); 128 | if (applicationInfo != null && applicationInfo.metaData != null) { 129 | channelName = String.valueOf(applicationInfo.metaData.get("CHANNEL")); 130 | } 131 | 132 | } 133 | } catch (Exception e) { 134 | e.printStackTrace(); 135 | } 136 | return channelName; 137 | } 138 | public static String getMetaData(Context context,String key) { 139 | String value = ""; 140 | try { 141 | PackageManager packageManager = context.getPackageManager(); 142 | if (packageManager != null) { 143 | //注意此处为ApplicationInfo 而不是 ActivityInfo,因为友盟设置的meta-data是在application标签中,而不是某activity标签中,所以用ApplicationInfo 144 | ApplicationInfo applicationInfo = packageManager. 145 | getApplicationInfo(context.getPackageName(), PackageManager.GET_META_DATA); 146 | if (applicationInfo != null && applicationInfo.metaData != null) { 147 | value = String.valueOf(applicationInfo.metaData.get(key)); 148 | } 149 | 150 | } 151 | } catch (Exception e) { 152 | e.printStackTrace(); 153 | } 154 | return value; 155 | } 156 | 157 | } 158 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/ViewMeasureUtils.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview; 2 | 3 | import android.view.View; 4 | import android.view.View.MeasureSpec; 5 | import android.view.ViewGroup; 6 | 7 | /** 8 | * Created by cy on 2018/4/21. 9 | */ 10 | 11 | public class ViewMeasureUtils { 12 | 13 | /** 14 | * 根据父 View 规则和子 View 的 LayoutParams,计算子类的宽度(width)测量规则 15 | * 16 | * @param viewChild 17 | */ 18 | public static int getChildWidthMeasureSpec(View viewChild, int parentWidthMeasureSpec) { 19 | // 获取父 View 的测量模式 20 | int parentWidthMode = MeasureSpec.getMode(parentWidthMeasureSpec); 21 | // 获取父 View 的测量尺寸 22 | int parentWidthSize = MeasureSpec.getSize(parentWidthMeasureSpec); 23 | 24 | // 定义子 View 的测量规则 25 | int childWidthMeasureSpec = 0; 26 | 27 | // 获取子 View 的 LayoutParams 28 | ViewGroup.LayoutParams layoutParams = (ViewGroup.LayoutParams) viewChild.getLayoutParams(); 29 | 30 | 31 | if (parentWidthMode == MeasureSpec.EXACTLY || parentWidthMode == MeasureSpec.AT_MOST) { 32 | /* 这是当父类的模式是 dp 的情况 */ 33 | if (layoutParams.width > 0) { 34 | childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY); 35 | } else if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) { 36 | childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(parentWidthSize, MeasureSpec.AT_MOST); 37 | } else if (layoutParams.width == ViewGroup.LayoutParams.MATCH_PARENT) { 38 | childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(parentWidthSize, MeasureSpec.EXACTLY); 39 | } 40 | } else if (parentWidthMode == MeasureSpec.UNSPECIFIED) { 41 | /* 这是当父类的模式是 MATCH_PARENT 的情况 */ 42 | if (layoutParams.width > 0) { 43 | childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(layoutParams.width, MeasureSpec.EXACTLY); 44 | } else if (layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT) { 45 | childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 46 | } else if (layoutParams.width == ViewGroup.LayoutParams.MATCH_PARENT) { 47 | childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 48 | } 49 | } 50 | 51 | // 返回子 View 的测量规则 52 | return childWidthMeasureSpec; 53 | } 54 | 55 | /** 56 | * 根据父 View 规则和子 View 的 LayoutParams,计算子类的宽度(width)测量规则 57 | * 58 | * @param viewChild 59 | */ 60 | public static int getChildHeightMeasureSpec(View viewChild, int parentHeightMeasureSpec) { 61 | // 获取父 View 的测量模式 62 | int parentHeightMode = MeasureSpec.getMode(parentHeightMeasureSpec); 63 | // 获取父 View 的测量尺寸 64 | int parentHeightSize = MeasureSpec.getSize(parentHeightMeasureSpec); 65 | 66 | // 定义子 View 的测量规则 67 | int childHeightMeasureSpec = 0; 68 | 69 | // 获取子 View 的 LayoutParams 70 | ViewGroup.LayoutParams layoutParams = (ViewGroup.LayoutParams) viewChild.getLayoutParams(); 71 | 72 | 73 | if (parentHeightMode == MeasureSpec.EXACTLY || parentHeightMode == MeasureSpec.AT_MOST) { 74 | /* 这是当父类的模式是 dp 的情况 */ 75 | if (layoutParams.height > 0) { 76 | childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY); 77 | } else if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) { 78 | childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(parentHeightSize, MeasureSpec.AT_MOST); 79 | } else if (layoutParams.width == ViewGroup.LayoutParams.MATCH_PARENT) { 80 | childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(parentHeightSize, MeasureSpec.EXACTLY); 81 | } 82 | } else if (parentHeightMode == MeasureSpec.UNSPECIFIED) { 83 | /* 这是当父类的模式是 MATCH_PARENT 的情况 */ 84 | if (layoutParams.height > 0) { 85 | childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(layoutParams.height, MeasureSpec.EXACTLY); 86 | } else if (layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT) { 87 | childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 88 | } else if (layoutParams.height == ViewGroup.LayoutParams.MATCH_PARENT) { 89 | childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 90 | } 91 | } 92 | 93 | // 返回子 View 的测量规则 94 | return childHeightMeasureSpec; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/cardview/CardViewApi21Impl.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.cardview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.view.View; 6 | 7 | import androidx.annotation.Nullable; 8 | 9 | 10 | public class CardViewApi21Impl implements CardViewImpl { 11 | CardViewApi21Impl() { 12 | } 13 | 14 | public void initialize(CardViewDelegate cardView, Context context, ColorStateList backgroundColor, float radius, float elevation, float maxElevation) { 15 | RoundRectDrawable background = new RoundRectDrawable(backgroundColor, radius); 16 | cardView.setCardBackground(background); 17 | View view = cardView.getCardView(); 18 | view.setClipToOutline(true); 19 | view.setElevation(elevation); 20 | this.setMaxElevation(cardView, maxElevation); 21 | } 22 | 23 | public void setRadius(CardViewDelegate cardView, float radius) { 24 | this.getCardBackground(cardView).setRadius(radius); 25 | } 26 | 27 | public void initStatic() { 28 | } 29 | 30 | public void setMaxElevation(CardViewDelegate cardView, float maxElevation) { 31 | this.getCardBackground(cardView).setPadding(maxElevation, cardView.getUseCompatPadding(), cardView.getPreventCornerOverlap()); 32 | this.updatePadding(cardView); 33 | } 34 | 35 | public float getMaxElevation(CardViewDelegate cardView) { 36 | return this.getCardBackground(cardView).getPadding(); 37 | } 38 | 39 | public float getMinWidth(CardViewDelegate cardView) { 40 | return this.getRadius(cardView) * 2.0F; 41 | } 42 | 43 | public float getMinHeight(CardViewDelegate cardView) { 44 | return this.getRadius(cardView) * 2.0F; 45 | } 46 | 47 | public float getRadius(CardViewDelegate cardView) { 48 | return this.getCardBackground(cardView).getRadius(); 49 | } 50 | 51 | public void setElevation(CardViewDelegate cardView, float elevation) { 52 | cardView.getCardView().setElevation(elevation); 53 | } 54 | 55 | public float getElevation(CardViewDelegate cardView) { 56 | return cardView.getCardView().getElevation(); 57 | } 58 | 59 | public void updatePadding(CardViewDelegate cardView) { 60 | 61 | if (!cardView.getUseCompatPadding()) { 62 | cardView.setShadowPadding(0, 0, 0, 0); 63 | } else { 64 | float elevation = this.getMaxElevation(cardView); 65 | float radius = this.getRadius(cardView); 66 | int hPadding = (int)Math.ceil((double)RoundRectDrawableWithShadow.calculateHorizontalPadding(elevation, radius, cardView.getPreventCornerOverlap())); 67 | int vPadding = (int)Math.ceil((double)RoundRectDrawableWithShadow.calculateVerticalPadding(elevation, radius, cardView.getPreventCornerOverlap())); 68 | cardView.setShadowPadding(hPadding, vPadding, hPadding, vPadding); 69 | } 70 | } 71 | 72 | public void onCompatPaddingChanged(CardViewDelegate cardView) { 73 | this.setMaxElevation(cardView, this.getMaxElevation(cardView)); 74 | } 75 | 76 | public void onPreventCornerOverlapChanged(CardViewDelegate cardView) { 77 | this.setMaxElevation(cardView, this.getMaxElevation(cardView)); 78 | } 79 | 80 | public void setBackgroundColor(CardViewDelegate cardView, @Nullable ColorStateList color) { 81 | this.getCardBackground(cardView).setColor(color); 82 | } 83 | 84 | public ColorStateList getBackgroundColor(CardViewDelegate cardView) { 85 | return this.getCardBackground(cardView).getColor(); 86 | } 87 | 88 | private RoundRectDrawable getCardBackground(CardViewDelegate cardView) { 89 | return (RoundRectDrawable)cardView.getCardBackground(); 90 | } 91 | } 92 | 93 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/cardview/CardViewDelegate.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.cardview; 2 | 3 | import android.graphics.drawable.Drawable; 4 | import android.view.View; 5 | 6 | interface CardViewDelegate { 7 | void setCardBackground(Drawable var1); 8 | 9 | Drawable getCardBackground(); 10 | 11 | boolean getUseCompatPadding(); 12 | 13 | boolean getPreventCornerOverlap(); 14 | 15 | void setShadowPadding(int var1, int var2, int var3, int var4); 16 | 17 | void setMinWidthHeightInternal(int var1, int var2); 18 | 19 | View getCardView(); 20 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/cardview/CardViewImpl.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.cardview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | 6 | import androidx.annotation.Nullable; 7 | 8 | interface CardViewImpl { 9 | void initialize(CardViewDelegate var1, Context var2, ColorStateList var3, float var4, float var5, float var6); 10 | 11 | void setRadius(CardViewDelegate var1, float var2); 12 | 13 | float getRadius(CardViewDelegate var1); 14 | 15 | void setElevation(CardViewDelegate var1, float var2); 16 | 17 | float getElevation(CardViewDelegate var1); 18 | 19 | void initStatic(); 20 | 21 | void setMaxElevation(CardViewDelegate var1, float var2); 22 | 23 | float getMaxElevation(CardViewDelegate var1); 24 | 25 | float getMinWidth(CardViewDelegate var1); 26 | 27 | float getMinHeight(CardViewDelegate var1); 28 | 29 | void updatePadding(CardViewDelegate var1); 30 | 31 | void onCompatPaddingChanged(CardViewDelegate var1); 32 | 33 | void onPreventCornerOverlapChanged(CardViewDelegate var1); 34 | 35 | void setBackgroundColor(CardViewDelegate var1, @Nullable ColorStateList var2); 36 | 37 | ColorStateList getBackgroundColor(CardViewDelegate var1); 38 | } 39 | 40 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/cardview/RoundRectDrawable.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.cardview; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.graphics.Canvas; 5 | import android.graphics.ColorFilter; 6 | import android.graphics.Outline; 7 | import android.graphics.Paint; 8 | import android.graphics.PorterDuff; 9 | import android.graphics.PorterDuffColorFilter; 10 | import android.graphics.Rect; 11 | import android.graphics.RectF; 12 | import android.graphics.drawable.Drawable; 13 | 14 | import androidx.annotation.Nullable; 15 | 16 | public class RoundRectDrawable extends Drawable { 17 | private float mRadius; 18 | private final Paint mPaint; 19 | private final RectF mBoundsF; 20 | private final Rect mBoundsI; 21 | private float mPadding; 22 | private boolean mInsetForPadding = false; 23 | private boolean mInsetForRadius = true; 24 | private ColorStateList mBackground; 25 | private PorterDuffColorFilter mTintFilter; 26 | private ColorStateList mTint; 27 | private PorterDuff.Mode mTintMode; 28 | 29 | RoundRectDrawable(ColorStateList backgroundColor, float radius) { 30 | this.mTintMode = PorterDuff.Mode.SRC_IN; 31 | this.mRadius = radius; 32 | this.mPaint = new Paint(5); 33 | this.setBackground(backgroundColor); 34 | this.mBoundsF = new RectF(); 35 | this.mBoundsI = new Rect(); 36 | } 37 | 38 | private void setBackground(ColorStateList color) { 39 | this.mBackground = color == null ? ColorStateList.valueOf(0) : color; 40 | this.mPaint.setColor(this.mBackground.getColorForState(this.getState(), this.mBackground.getDefaultColor())); 41 | } 42 | 43 | void setPadding(float padding, boolean insetForPadding, boolean insetForRadius) { 44 | if (padding != this.mPadding || this.mInsetForPadding != insetForPadding || this.mInsetForRadius != insetForRadius) { 45 | this.mPadding = padding; 46 | this.mInsetForPadding = insetForPadding; 47 | this.mInsetForRadius = insetForRadius; 48 | this.updateBounds((Rect)null); 49 | this.invalidateSelf(); 50 | } 51 | } 52 | 53 | float getPadding() { 54 | return this.mPadding; 55 | } 56 | 57 | public void draw(Canvas canvas) { 58 | Paint paint = this.mPaint; 59 | boolean clearColorFilter; 60 | if (this.mTintFilter != null && paint.getColorFilter() == null) { 61 | paint.setColorFilter(this.mTintFilter); 62 | clearColorFilter = true; 63 | } else { 64 | clearColorFilter = false; 65 | } 66 | 67 | canvas.drawRoundRect(this.mBoundsF, this.mRadius, this.mRadius, paint); 68 | if (clearColorFilter) { 69 | paint.setColorFilter((ColorFilter)null); 70 | } 71 | 72 | } 73 | 74 | private void updateBounds(Rect bounds) { 75 | if (bounds == null) { 76 | bounds = this.getBounds(); 77 | } 78 | 79 | this.mBoundsF.set((float)bounds.left, (float)bounds.top, (float)bounds.right, (float)bounds.bottom); 80 | this.mBoundsI.set(bounds); 81 | if (this.mInsetForPadding) { 82 | float vInset = RoundRectDrawableWithShadow.calculateVerticalPadding(this.mPadding, this.mRadius, this.mInsetForRadius); 83 | float hInset = RoundRectDrawableWithShadow.calculateHorizontalPadding(this.mPadding, this.mRadius, this.mInsetForRadius); 84 | this.mBoundsI.inset((int)Math.ceil((double)hInset), (int)Math.ceil((double)vInset)); 85 | this.mBoundsF.set(this.mBoundsI); 86 | } 87 | 88 | } 89 | 90 | protected void onBoundsChange(Rect bounds) { 91 | super.onBoundsChange(bounds); 92 | this.updateBounds(bounds); 93 | } 94 | 95 | public void getOutline(Outline outline) { 96 | outline.setRoundRect(this.mBoundsI, this.mRadius); 97 | } 98 | 99 | void setRadius(float radius) { 100 | if (radius != this.mRadius) { 101 | this.mRadius = radius; 102 | this.updateBounds((Rect)null); 103 | this.invalidateSelf(); 104 | } 105 | } 106 | 107 | public void setAlpha(int alpha) { 108 | this.mPaint.setAlpha(alpha); 109 | } 110 | 111 | public void setColorFilter(ColorFilter cf) { 112 | this.mPaint.setColorFilter(cf); 113 | } 114 | 115 | public int getOpacity() { 116 | return -3; 117 | } 118 | 119 | public float getRadius() { 120 | return this.mRadius; 121 | } 122 | 123 | public void setColor(@Nullable ColorStateList color) { 124 | this.setBackground(color); 125 | this.invalidateSelf(); 126 | } 127 | 128 | public ColorStateList getColor() { 129 | return this.mBackground; 130 | } 131 | 132 | public void setTintList(ColorStateList tint) { 133 | this.mTint = tint; 134 | this.mTintFilter = this.createTintFilter(this.mTint, this.mTintMode); 135 | this.invalidateSelf(); 136 | } 137 | 138 | public void setTintMode(PorterDuff.Mode tintMode) { 139 | this.mTintMode = tintMode; 140 | this.mTintFilter = this.createTintFilter(this.mTint, this.mTintMode); 141 | this.invalidateSelf(); 142 | } 143 | 144 | protected boolean onStateChange(int[] stateSet) { 145 | int newColor = this.mBackground.getColorForState(stateSet, this.mBackground.getDefaultColor()); 146 | boolean colorChanged = newColor != this.mPaint.getColor(); 147 | if (colorChanged) { 148 | this.mPaint.setColor(newColor); 149 | } 150 | 151 | if (this.mTint != null && this.mTintMode != null) { 152 | this.mTintFilter = this.createTintFilter(this.mTint, this.mTintMode); 153 | return true; 154 | } else { 155 | return colorChanged; 156 | } 157 | } 158 | 159 | public boolean isStateful() { 160 | return this.mTint != null && this.mTint.isStateful() || this.mBackground != null && this.mBackground.isStateful() || super.isStateful(); 161 | } 162 | 163 | private PorterDuffColorFilter createTintFilter(ColorStateList tint, PorterDuff.Mode tintMode) { 164 | if (tint != null && tintMode != null) { 165 | int color = tint.getColorForState(this.getState(), 0); 166 | return new PorterDuffColorFilter(color, tintMode); 167 | } else { 168 | return null; 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/colorfilterview/ColorFilterCy.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.colorfilterview; 2 | 3 | import android.content.res.TypedArray; 4 | import android.graphics.ColorMatrixColorFilter; 5 | import android.os.Handler; 6 | import android.view.MotionEvent; 7 | import android.view.View; 8 | import android.widget.ImageView; 9 | 10 | import androidx.annotation.StyleableRes; 11 | 12 | /** 13 | * @Description: 14 | * @Author: cy 15 | * @CreateDate: 2020/6/26 19:36 16 | * @UpdateUser: 17 | * @UpdateDate: 2020/6/26 19:36 18 | * @UpdateRemark: 19 | * @Version: 1.0 20 | */ 21 | public class ColorFilterCy { 22 | 23 | //正数,变亮 24 | // public float[] BT_SELECTED_LIGHT = new float[]{ 25 | // 1, 0, 0, 0, 30, 26 | // 0, 1, 0, 0, 30, 27 | // 0, 0, 1, 0, 30, 28 | // 0, 0, 0, 1, 0}; 29 | // //恢复 30 | // public float[] BT_NOT_SELECTED = new float[]{ 31 | // 1, 0, 0, 0, 0, 32 | // 0, 1, 0, 0, 0, 33 | // 0, 0, 1, 0, 0, 34 | // 0, 0, 0, 1, 0}; 35 | 36 | private TypedArray typedArray; 37 | private ImageView imageView; 38 | private boolean havaFilter = true; 39 | private boolean lightOrDark = false; 40 | private float lightNumber = -50; 41 | //负数,变暗(三个-30,值越大则效果越深) 42 | private float[] filters = new float[]{ 43 | 1, 0, 0, 0, 0, 44 | 0, 1, 0, 0, 0, 45 | 0, 0, 1, 0, 0, 46 | 0, 0, 0, 1, 0}; 47 | 48 | public ColorFilterCy(ImageView imageView, TypedArray typedArray) { 49 | this.imageView = imageView; 50 | this.typedArray = typedArray; 51 | } 52 | 53 | public ColorFilterCy setHavaFilter(@StyleableRes int index) { 54 | havaFilter = typedArray.getBoolean(index, havaFilter);//设置是否有滤镜点击效果,默认有 55 | return this; 56 | } 57 | 58 | public ColorFilterCy setHavaFilter_(boolean havaFilter) { 59 | this.havaFilter = havaFilter;//设置是否有滤镜点击效果,默认有 60 | return this; 61 | } 62 | 63 | 64 | /** 65 | * //设置滤镜,变亮还是变暗,默认变暗 66 | * 67 | * @param index 68 | * @return 69 | */ 70 | public ColorFilterCy setLightOrDark(@StyleableRes int index) { 71 | lightOrDark = typedArray.getBoolean(index, lightOrDark); 72 | return this; 73 | } 74 | public ColorFilterCy setLightOrDark_(boolean lightOrDark) { 75 | this.lightOrDark=lightOrDark; 76 | return this; 77 | } 78 | 79 | public ColorFilterCy setLightNumber(@StyleableRes int index) { 80 | lightNumber = typedArray.getFloat(index, lightOrDark ? -lightNumber : lightNumber); 81 | return this; 82 | } 83 | public ColorFilterCy setLightNumber_(float lightNumber) { 84 | this.lightNumber=lightNumber; 85 | return this; 86 | } 87 | 88 | public boolean isHavaFilter() { 89 | return havaFilter; 90 | } 91 | 92 | 93 | public boolean isLightOrDark() { 94 | return lightOrDark; 95 | } 96 | 97 | public float getLightNumber() { 98 | return lightNumber; 99 | } 100 | 101 | public float[] getFilters() { 102 | return filters; 103 | } 104 | 105 | 106 | public ColorFilterCy colorFilter(MotionEvent event) { 107 | if (!havaFilter) return this; 108 | //滤镜,变暗或者变亮,负数,变暗(值越大则效果越深),正数,变亮 109 | filters[4] = lightNumber; 110 | filters[9] = lightNumber; 111 | filters[14] = lightNumber; 112 | 113 | switch (event.getAction()) { 114 | case MotionEvent.ACTION_DOWN: 115 | imageView.setColorFilter(new ColorMatrixColorFilter(filters)); 116 | new Handler().postDelayed(new Runnable() { 117 | @Override 118 | public void run() { 119 | imageView.clearColorFilter(); 120 | } 121 | }, 100); 122 | break; 123 | } 124 | return this; 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/colorfilterview/IColorFilter.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.colorfilterview; 2 | 3 | import android.content.res.TypedArray; 4 | 5 | /** 6 | * @Description: 7 | * @Author: cy 8 | * @CreateDate: 2020/6/26 19:36 9 | * @UpdateUser: 10 | * @UpdateDate: 2020/6/26 19:36 11 | * @UpdateRemark: 12 | * @Version: 1.0 13 | */ 14 | public interface IColorFilter { 15 | public ColorFilterCy colorFilter(TypedArray typedArray); 16 | public ColorFilterCy getColorFilterCy(); 17 | } 18 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/colorfilterview/ImageViewColorFilter.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.colorfilterview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.ColorMatrixColorFilter; 6 | import android.os.Handler; 7 | import android.util.AttributeSet; 8 | import android.view.MotionEvent; 9 | import android.view.View; 10 | 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.widget.AppCompatImageView; 13 | 14 | import com.cy.androidview.R; 15 | 16 | 17 | /** 18 | * Created by cy on 2018/10/27. 19 | */ 20 | 21 | public class ImageViewColorFilter extends AppCompatImageView implements IColorFilter { 22 | 23 | private ColorFilterCy colorFilter; 24 | 25 | public ImageViewColorFilter(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ImageViewColorFilter); 28 | colorFilter = colorFilter(typedArray); 29 | typedArray.recycle(); 30 | } 31 | 32 | @Override 33 | public boolean onTouchEvent(MotionEvent event) { 34 | colorFilter.colorFilter(event); 35 | return super.onTouchEvent(event); 36 | } 37 | 38 | @Override 39 | public ColorFilterCy colorFilter(TypedArray typedArray) { 40 | return new ColorFilterCy(this, typedArray) 41 | .setHavaFilter(R.styleable.ImageViewColorFilter_cy_haveFilter) 42 | .setLightOrDark(R.styleable.ImageViewColorFilter_cy_lightOrDark) 43 | .setLightNumber(R.styleable.ImageViewColorFilter_cy_lightNumber); 44 | } 45 | 46 | @Override 47 | public ColorFilterCy getColorFilterCy() { 48 | return colorFilter; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/edittext/TextWatcherImpl.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.edittext; 2 | 3 | import android.text.Editable; 4 | import android.text.TextWatcher; 5 | 6 | /** 7 | * Created by lenovo on 2017/8/2. 8 | */ 9 | 10 | public abstract class TextWatcherImpl implements TextWatcher { 11 | @Override 12 | public void beforeTextChanged(CharSequence s, int start, int count, int after) { 13 | 14 | } 15 | 16 | @Override 17 | public void onTextChanged(CharSequence s, int start, int before, int count) { 18 | 19 | } 20 | 21 | @Override 22 | public abstract void afterTextChanged(Editable s) ; 23 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/progress/ProgressWeightView.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.progress; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Paint; 7 | import android.util.AttributeSet; 8 | import android.view.View; 9 | 10 | import androidx.annotation.Nullable; 11 | 12 | import com.cy.androidview.R; 13 | import com.cy.androidview.ScreenUtils; 14 | 15 | public class ProgressWeightView extends View { 16 | private Paint paintBg, paintFg; 17 | private float progress; 18 | private int width; 19 | private int height; 20 | private int radius; 21 | 22 | public ProgressWeightView(Context context) { 23 | this(context, null); 24 | } 25 | 26 | public ProgressWeightView(Context context, @Nullable AttributeSet attrs) { 27 | super(context, attrs); 28 | paintFg = new Paint(); 29 | paintFg.setAntiAlias(true); 30 | 31 | paintBg = new Paint(); 32 | paintBg.setAntiAlias(true); 33 | 34 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ProgressWeightView); 35 | setBgColor(typedArray.getColor(R.styleable.ProgressWeightView_cy_color_bg, 0x11000000)); 36 | setFgColor(typedArray.getColor(R.styleable.ProgressWeightView_cy_color_fg, 0xff2a83fc)); 37 | typedArray.recycle(); 38 | } 39 | 40 | public ProgressWeightView setBgColor(int color) { 41 | paintBg.setColor(color); 42 | return this; 43 | } 44 | 45 | public ProgressWeightView setFgColor(int color) { 46 | paintFg.setColor(color); 47 | return this; 48 | } 49 | 50 | 51 | public ProgressWeightView setProgress(float progress) { 52 | this.progress = Math.min(1, Math.max(0, progress)); 53 | invalidate(); 54 | return this; 55 | } 56 | 57 | @Override 58 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 59 | super.onLayout(changed, left, top, right, bottom); 60 | width = getWidth(); 61 | height = getHeight(); 62 | radius= (int) (height*0.5f); 63 | } 64 | 65 | @Override 66 | protected void onDraw(Canvas canvas) { 67 | super.onDraw(canvas); 68 | canvas.drawRoundRect(0, 0, width, height, radius, radius, paintBg); 69 | canvas.drawRoundRect(0, 0, progress * width, height, radius, radius, paintFg); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/progress/VCutProgressView.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.progress; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Canvas; 6 | import android.graphics.Color; 7 | import android.graphics.CornerPathEffect; 8 | import android.graphics.LinearGradient; 9 | import android.graphics.Paint; 10 | import android.graphics.Path; 11 | import android.graphics.RectF; 12 | import android.graphics.Shader; 13 | import android.util.AttributeSet; 14 | import android.view.View; 15 | 16 | import androidx.annotation.Nullable; 17 | 18 | import com.cy.androidview.R; 19 | import com.cy.androidview.ScreenUtils; 20 | 21 | public class VCutProgressView extends View { 22 | 23 | private final Paint paint; 24 | private final Paint paintProgress; 25 | private int width, height; 26 | private Path path; 27 | private int corner = 0; 28 | private int widthStroke = 0; 29 | private RectF rectF, rectFCorner; 30 | public static final int PROGRESS_MAX = 100; 31 | private int progress = 0; 32 | private int[] progressT; 33 | 34 | public VCutProgressView(Context context, @Nullable AttributeSet attrs) { 35 | super(context, attrs); 36 | // 创建画笔 37 | paint = new Paint(); 38 | paint.setStyle(Paint.Style.STROKE); 39 | paint.setAntiAlias(true); // 开启抗锯齿 40 | 41 | paintProgress = new Paint(); 42 | paintProgress.setStyle(Paint.Style.STROKE); 43 | paintProgress.setAntiAlias(true); // 开启抗锯齿 44 | 45 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VCutProgressView); 46 | setColorBg(typedArray.getColor(R.styleable.VCutProgressView_cy_color_bg, 0x33ffffff)); 47 | setColorProgress(typedArray.getColor(R.styleable.VCutProgressView_cy_color_progress, 0xff2a83fc)); 48 | setCorner(typedArray.getDimensionPixelSize(R.styleable.VCutProgressView_cy_radiusCorner, ScreenUtils.dpAdapt(context, 10))); 49 | setWidthStroke(typedArray.getDimensionPixelSize(R.styleable.VCutProgressView_cy_strokeWidth, ScreenUtils.dpAdapt(context, 3))); 50 | setProgress(typedArray.getInt(R.styleable.VCutProgressView_cy_progress, 0)); 51 | typedArray.recycle(); 52 | 53 | path = new Path(); 54 | rectF = new RectF(); 55 | rectFCorner = new RectF(); 56 | } 57 | 58 | public void setCorner(int corner) { 59 | this.corner = corner; 60 | } 61 | 62 | public void setColorBg(int color) { 63 | paint.setColor(color); 64 | } 65 | 66 | public void setColorProgress(int color) { 67 | paintProgress.setColor(color); 68 | } 69 | 70 | public void setWidthStroke(int widthStroke) { 71 | this.widthStroke = widthStroke; 72 | paint.setStrokeWidth(widthStroke); 73 | paintProgress.setStrokeWidth(widthStroke); 74 | } 75 | 76 | public void setProgress(int progress) { 77 | this.progress = Math.min(PROGRESS_MAX, Math.max(0, progress)); 78 | invalidate(); 79 | } 80 | 81 | public int getProgress() { 82 | return progress; 83 | } 84 | 85 | @Override 86 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 87 | super.onLayout(changed, left, top, right, bottom); 88 | width = getWidth(); 89 | height = getHeight(); 90 | float all = 2 * width + 2 * height; 91 | //31 50 81 100 92 | progressT = new int[]{(int) (width / all * PROGRESS_MAX), (int) ((width + height) / all * PROGRESS_MAX), 93 | (int) ((2 * width + height) / all * PROGRESS_MAX), PROGRESS_MAX}; 94 | } 95 | 96 | @Override 97 | protected void onDraw(Canvas canvas) { 98 | super.onDraw(canvas); 99 | rectF.left = widthStroke * 0.5f; 100 | rectF.top = rectF.left; 101 | rectF.right = width - rectF.left; 102 | rectF.bottom = height - rectF.left; 103 | canvas.drawRoundRect(rectF, corner, corner, paint); 104 | 105 | //注意:这里考虑了corner为0的时候,进度也能填满方框 106 | path.moveTo(corner, rectF.top); 107 | path.lineTo(Math.min(width - corner, corner + (width - 2.0f * corner) * progress / progressT[0]), rectF.top); 108 | 109 | if (progress > progressT[0]) { 110 | rectFCorner.left = rectF.right - 2 * corner; 111 | rectFCorner.top = rectF.top; 112 | rectFCorner.right = rectF.right; 113 | rectFCorner.bottom = rectF.top + 2 * corner; 114 | path.arcTo(rectFCorner, 0, -90, true); 115 | 116 | path.moveTo(rectF.right, rectF.top + corner); 117 | path.lineTo(rectF.right, Math.min(rectF.bottom - corner, 118 | rectF.top + corner + (height - 2.0f * corner) * (progress - progressT[0]) / (progressT[1] - progressT[0]))); 119 | } 120 | 121 | if (progress > progressT[1]) { 122 | rectFCorner.left = rectF.right - 2 * corner; 123 | rectFCorner.top = rectF.bottom - 2 * corner; 124 | rectFCorner.right = rectF.right; 125 | rectFCorner.bottom = rectF.bottom; 126 | path.arcTo(rectFCorner, 0, 90, true); 127 | 128 | path.moveTo(width - corner, rectF.bottom); 129 | path.lineTo(Math.max(corner, 130 | width - corner - (width - 2.0f * corner) * (progress - progressT[1]) / (progressT[2] - progressT[1])), rectF.bottom); 131 | } 132 | 133 | if (progress > progressT[2]) { 134 | rectFCorner.left = rectF.left; 135 | rectFCorner.top = rectF.bottom - 2 * corner; 136 | rectFCorner.right = rectF.left + 2 * corner; 137 | rectFCorner.bottom = rectF.bottom; 138 | path.arcTo(rectFCorner, 90, 90, true); 139 | 140 | path.moveTo(rectF.left, rectF.bottom - corner); 141 | path.lineTo(rectF.left, Math.max(rectF.top + corner, 142 | rectF.bottom - corner - (height - 2.0f * corner) * (progress - progressT[2]) / (progressT[3] - progressT[2]))); 143 | } 144 | 145 | if (progress >= progressT[3]) { 146 | rectFCorner.left = rectF.left; 147 | rectFCorner.top = rectF.top; 148 | rectFCorner.right = rectF.left + 2 * corner; 149 | rectFCorner.bottom = rectF.top + 2 * corner; 150 | path.arcTo(rectFCorner, 180, 90, true); 151 | } 152 | 153 | canvas.drawPath(path, paintProgress); 154 | } 155 | 156 | } 157 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/ButtonRectangle.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import androidx.appcompat.widget.AppCompatButton; 10 | 11 | import com.cy.androidview.R; 12 | import com.cy.androidview.ViewMeasureUtils; 13 | import com.cy.androidview.rippleview.IRipple; 14 | import com.cy.androidview.rippleview.Ripple; 15 | 16 | 17 | /** 18 | * 正方形的LinearLayout 类似桥接模式,避免多重继承带来的维护成本 19 | * 20 | * @author Administrator 21 | */ 22 | public class ButtonRectangle extends AppCompatButton implements IRectangle, IRipple { 23 | private RectangleRatio rectangleRatio; 24 | private Ripple ripple; 25 | public ButtonRectangle(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRectangle); 28 | ripple=ripple(typedArray); 29 | rectangleRatio=rectangle(typedArray); 30 | typedArray.recycle(); 31 | } 32 | 33 | @Override 34 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 35 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 36 | super.onMeasure(specs[0],specs[1]); 37 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 38 | } 39 | @Override 40 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 41 | super.onLayout(changed, l, t, r, b); 42 | ripple.ripple(); 43 | } 44 | @Override 45 | public RectangleRatio rectangle(TypedArray typedArray) { 46 | return new RectangleRatio(this, typedArray); 47 | } 48 | 49 | @Override 50 | public Ripple ripple(TypedArray typedArray) { 51 | return new Ripple(this, typedArray); 52 | } 53 | 54 | @Override 55 | public Ripple getRipple() { 56 | return ripple; 57 | } 58 | 59 | @Override 60 | public RectangleRatio getRectangleRatio() { 61 | return rectangleRatio; 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/FrameLayoutRectangle.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.FrameLayout; 9 | 10 | import com.cy.androidview.R; 11 | import com.cy.androidview.ViewMeasureUtils; 12 | import com.cy.androidview.rippleview.IRipple; 13 | import com.cy.androidview.rippleview.Ripple; 14 | 15 | 16 | /** 17 | * 正方形的LinearLayout 18 | * 19 | * @author Administrator 20 | */ 21 | public class FrameLayoutRectangle extends FrameLayout implements IRectangle, IRipple { 22 | private RectangleRatio rectangleRatio; 23 | private Ripple ripple; 24 | 25 | public FrameLayoutRectangle(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRectangle); 28 | ripple = ripple(typedArray); 29 | rectangleRatio = rectangle(typedArray); 30 | typedArray.recycle(); 31 | } 32 | 33 | @Override 34 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 35 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 36 | super.onMeasure(specs[0],specs[1]); 37 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 38 | } 39 | @Override 40 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 41 | super.onLayout(changed, l, t, r, b); 42 | ripple.ripple(); 43 | } 44 | @Override 45 | public RectangleRatio rectangle(TypedArray typedArray) { 46 | return new RectangleRatio(this, typedArray); 47 | } 48 | 49 | @Override 50 | public Ripple ripple(TypedArray typedArray) { 51 | return new Ripple(this, typedArray); 52 | } 53 | 54 | @Override 55 | public Ripple getRipple() { 56 | return ripple; 57 | } 58 | 59 | @Override 60 | public RectangleRatio getRectangleRatio() { 61 | return rectangleRatio; 62 | } 63 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/IRectangle.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | 4 | import android.content.res.TypedArray; 5 | 6 | /** 7 | * @Description: 8 | * @Author: cy 9 | * @CreateDate: 2020/6/26 19:24 10 | * @UpdateUser: 11 | * @UpdateDate: 2020/6/26 19:24 12 | * @UpdateRemark: 13 | * @Version: 1.0 14 | */ 15 | public interface IRectangle { 16 | public RectangleRatio rectangle(TypedArray typedArray); 17 | public RectangleRatio getRectangleRatio(); 18 | } 19 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/ImageViewRectangle.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.graphics.ColorMatrixColorFilter; 6 | import android.util.AttributeSet; 7 | import android.view.MotionEvent; 8 | import android.view.View; 9 | import android.view.ViewGroup; 10 | 11 | import androidx.annotation.Nullable; 12 | import androidx.appcompat.widget.AppCompatImageView; 13 | 14 | import com.cy.androidview.R; 15 | import com.cy.androidview.ViewMeasureUtils; 16 | import com.cy.androidview.colorfilterview.ColorFilterCy; 17 | import com.cy.androidview.colorfilterview.IColorFilter; 18 | 19 | 20 | /** 21 | * 正方形的LinearLayout 22 | * 23 | * @author Administrator 24 | */ 25 | public class ImageViewRectangle extends AppCompatImageView implements IRectangle { 26 | private RectangleRatio rectangleRatio; 27 | // private ColorFilterCy colorFilter; 28 | public ImageViewRectangle(Context context, AttributeSet attrs) { 29 | super(context, attrs); 30 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRectangle); 31 | // colorFilter=colorFilter(typedArray); 32 | rectangleRatio = rectangle(typedArray); 33 | typedArray.recycle(); 34 | } 35 | @Override 36 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 37 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 38 | super.onMeasure(specs[0],specs[1]); 39 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 40 | } 41 | @Override 42 | public RectangleRatio rectangle(TypedArray typedArray) { 43 | return new RectangleRatio(this,typedArray); 44 | } 45 | 46 | // @Override 47 | // public boolean onTouchEvent(MotionEvent event) { 48 | // colorFilter.colorFilter(event); 49 | // return super.onTouchEvent(event); 50 | // } 51 | 52 | // @Override 53 | // public ColorFilterCy colorFilter(TypedArray typedArray) { 54 | // return new ColorFilterCy(this, typedArray) 55 | // .setHavaFilter(R.styleable.ImageViewColorFilter_cy_haveFilter) 56 | // .setLightOrDark(R.styleable.ImageViewColorFilter_cy_lightOrDark) 57 | // .setLightNumber(R.styleable.ImageViewColorFilter_cy_lightNumber); 58 | // } 59 | 60 | @Override 61 | public RectangleRatio getRectangleRatio() { 62 | return rectangleRatio; 63 | } 64 | 65 | // @Override 66 | // public ColorFilterCy getColorFilterCy() { 67 | // return colorFilter; 68 | // } 69 | } 70 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/LinearLayoutRectangle.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.LinearLayout; 9 | 10 | import com.cy.androidview.R; 11 | import com.cy.androidview.ViewMeasureUtils; 12 | import com.cy.androidview.rippleview.IRipple; 13 | import com.cy.androidview.rippleview.LinearLayoutRipple; 14 | import com.cy.androidview.rippleview.Ripple; 15 | 16 | 17 | /** 18 | * 正方形的LinearLayout 19 | * 20 | * @author Administrator 21 | */ 22 | public class LinearLayoutRectangle extends LinearLayout implements IRectangle, IRipple { 23 | private RectangleRatio rectangleRatio; 24 | private Ripple ripple; 25 | public LinearLayoutRectangle(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRectangle); 28 | ripple=ripple(typedArray); 29 | rectangleRatio = rectangle(typedArray); 30 | typedArray.recycle(); 31 | } 32 | @Override 33 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 34 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 35 | super.onMeasure(specs[0],specs[1]); 36 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 37 | } 38 | @Override 39 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 40 | super.onLayout(changed, l, t, r, b); 41 | ripple.ripple(); 42 | } 43 | @Override 44 | public RectangleRatio rectangle(TypedArray typedArray) { 45 | return new RectangleRatio(this,typedArray); 46 | } 47 | 48 | @Override 49 | public Ripple ripple(TypedArray typedArray) { 50 | return new Ripple(this, typedArray); 51 | } 52 | 53 | @Override 54 | public Ripple getRipple() { 55 | return ripple; 56 | } 57 | 58 | @Override 59 | public RectangleRatio getRectangleRatio() { 60 | return rectangleRatio; 61 | } 62 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/RectangleRatio.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | import android.content.res.TypedArray; 4 | import android.util.AttributeSet; 5 | import android.util.Log; 6 | import android.view.View; 7 | 8 | import androidx.annotation.StyleableRes; 9 | 10 | import com.cy.androidview.R; 11 | import com.cy.androidview.rippleview.Ripple; 12 | 13 | /** 14 | * @Description: 15 | * @Author: cy 16 | * @CreateDate: 2020/6/26 22:11 17 | * @UpdateUser: 18 | * @UpdateDate: 2020/6/26 22:11 19 | * @UpdateRemark: 20 | * @Version: 1.0 21 | */ 22 | public class RectangleRatio { 23 | private float heightWidthRatio = 1; //高 / 宽(默认是高/宽),或者宽/高 比例 24 | private boolean baseOnWidthOrHeight = true;//默认true,即默认基于宽 25 | private TypedArray typedArray; 26 | private View view; 27 | 28 | public RectangleRatio(View view, TypedArray typedArray) { 29 | this.view = view; 30 | this.typedArray = typedArray; 31 | heightWidthRatio = typedArray.getFloat(R.styleable.AttrsRectangle_cy_heightWidthRatio, heightWidthRatio); 32 | baseOnWidthOrHeight = typedArray.getBoolean(R.styleable.AttrsRectangle_cy_baseOnWidthOrHeight, baseOnWidthOrHeight); 33 | } 34 | 35 | 36 | public RectangleRatio setHeightWidthRatio_(float heightWidthRatio) { 37 | this.heightWidthRatio = heightWidthRatio; 38 | return this; 39 | } 40 | 41 | public RectangleRatio setHeightWidthRatio(@StyleableRes int index, int defaultValue) { 42 | heightWidthRatio = typedArray.getFloat(index, defaultValue); 43 | return this; 44 | } 45 | 46 | public RectangleRatio setBaseOnWidthOrHeight_(boolean baseOnWidthOrHeight) { 47 | this.baseOnWidthOrHeight = baseOnWidthOrHeight; 48 | return this; 49 | } 50 | 51 | public float getHeightWidthRatio() { 52 | return heightWidthRatio; 53 | } 54 | 55 | public boolean isBaseOnWidthOrHeight() { 56 | return baseOnWidthOrHeight; 57 | } 58 | 59 | public int[] rectangle(int widthMeasureSpec, int heightMeasureSpec) { 60 | int[] widthHeightMeasureSpecs = new int[]{widthMeasureSpec, heightMeasureSpec}; 61 | if (heightWidthRatio == 0) return widthHeightMeasureSpecs; 62 | //默认基于宽,即高会和宽度一致,高由宽决定 63 | if (baseOnWidthOrHeight) { 64 | int widthSize = View.MeasureSpec.getSize(widthMeasureSpec); 65 | widthHeightMeasureSpecs[1] = View.MeasureSpec.makeMeasureSpec((int) (widthSize * heightWidthRatio), View.MeasureSpec.EXACTLY); 66 | } else { 67 | //基于高,即宽度会和高度一致,宽度由高度决定 68 | int heightSize = view.getMeasuredHeight(); 69 | widthHeightMeasureSpecs[0] = View.MeasureSpec.makeMeasureSpec((int) (heightSize * heightWidthRatio), View.MeasureSpec.EXACTLY); 70 | } 71 | return widthHeightMeasureSpecs; 72 | } 73 | 74 | } 75 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/RelativeLayoutRectangle.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.RelativeLayout; 9 | 10 | import com.cy.androidview.R; 11 | import com.cy.androidview.ViewMeasureUtils; 12 | import com.cy.androidview.rippleview.IRipple; 13 | import com.cy.androidview.rippleview.RelativeLayoutRipple; 14 | import com.cy.androidview.rippleview.Ripple; 15 | 16 | 17 | /** 18 | * 正方形的LinearLayout 19 | * 20 | * @author Administrator 21 | */ 22 | public class RelativeLayoutRectangle extends RelativeLayout implements IRectangle, IRipple { 23 | private RectangleRatio rectangleRatio; 24 | private Ripple ripple; 25 | public RelativeLayoutRectangle(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRectangle); 28 | ripple=ripple(typedArray); 29 | rectangleRatio = rectangle(typedArray); 30 | typedArray.recycle(); 31 | } 32 | @Override 33 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 34 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 35 | super.onMeasure(specs[0],specs[1]); 36 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 37 | } 38 | @Override 39 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 40 | super.onLayout(changed, l, t, r, b); 41 | ripple.ripple(); 42 | } 43 | @Override 44 | public RectangleRatio rectangle(TypedArray typedArray) { 45 | return new RectangleRatio(this, typedArray); 46 | } 47 | 48 | @Override 49 | public Ripple ripple(TypedArray typedArray) { 50 | return new Ripple(this, typedArray); 51 | } 52 | 53 | @Override 54 | public Ripple getRipple() { 55 | return ripple; 56 | } 57 | 58 | @Override 59 | public RectangleRatio getRectangleRatio() { 60 | return rectangleRatio; 61 | } 62 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rectangleview/TextViewRectangle.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rectangleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import androidx.appcompat.widget.AppCompatTextView; 10 | 11 | import com.cy.androidview.R; 12 | import com.cy.androidview.ViewMeasureUtils; 13 | import com.cy.androidview.rippleview.IRipple; 14 | import com.cy.androidview.rippleview.Ripple; 15 | import com.cy.androidview.rippleview.TextViewRipple; 16 | 17 | 18 | /** 19 | * 正方形的LinearLayout 20 | * 21 | * @author Administrator 22 | */ 23 | public class TextViewRectangle extends AppCompatTextView implements IRectangle, IRipple { 24 | private RectangleRatio rectangleRatio; 25 | private Ripple ripple; 26 | public TextViewRectangle(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRectangle); 29 | ripple=ripple(typedArray); 30 | rectangleRatio = rectangle(typedArray); 31 | typedArray.recycle(); 32 | } 33 | 34 | @Override 35 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 36 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 37 | super.onMeasure(specs[0],specs[1]); 38 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 39 | } 40 | @Override 41 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 42 | super.onLayout(changed, l, t, r, b); 43 | ripple.ripple(); 44 | } 45 | @Override 46 | public RectangleRatio rectangle(TypedArray typedArray) { 47 | return new RectangleRatio(this, typedArray); 48 | } 49 | 50 | @Override 51 | public Ripple ripple(TypedArray typedArray) { 52 | return new Ripple(this, typedArray); 53 | } 54 | 55 | @Override 56 | public Ripple getRipple() { 57 | return ripple; 58 | } 59 | 60 | @Override 61 | public RectangleRatio getRectangleRatio() { 62 | return rectangleRatio; 63 | } 64 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/ButtonRipple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.content.res.TypedArray; 6 | import android.graphics.drawable.Drawable; 7 | import android.graphics.drawable.RippleDrawable; 8 | import android.util.AttributeSet; 9 | 10 | import androidx.appcompat.widget.AppCompatButton; 11 | 12 | import com.cy.androidview.R; 13 | 14 | 15 | /** 16 | * Created by cy on 2018/10/27. 17 | */ 18 | 19 | public class ButtonRipple extends AppCompatButton implements IRipple { 20 | private Ripple ripple; 21 | 22 | public ButtonRipple(Context context, AttributeSet attrs) { 23 | super(context, attrs); 24 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRipple); 25 | ripple = ripple(typedArray); 26 | typedArray.recycle(); 27 | } 28 | @Override 29 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 30 | super.onLayout(changed, l, t, r, b); 31 | ripple.ripple(); 32 | } 33 | @Override 34 | public Ripple ripple(TypedArray typedArray) { 35 | return new Ripple(this, typedArray); 36 | } 37 | 38 | @Override 39 | public Ripple getRipple() { 40 | return ripple; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/FrameLayoutRipple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.content.res.TypedArray; 6 | import android.graphics.drawable.Drawable; 7 | import android.graphics.drawable.RippleDrawable; 8 | import android.util.AttributeSet; 9 | import android.widget.FrameLayout; 10 | 11 | import com.cy.androidview.R; 12 | 13 | 14 | /** 15 | * Created by cy on 2018/10/27. 16 | */ 17 | 18 | public class FrameLayoutRipple extends FrameLayout implements IRipple { 19 | private Ripple ripple; 20 | public FrameLayoutRipple(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRipple); 23 | ripple=ripple(typedArray); 24 | typedArray.recycle(); 25 | } 26 | @Override 27 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 28 | super.onLayout(changed, l, t, r, b); 29 | ripple.ripple(); 30 | } 31 | @Override 32 | public Ripple ripple(TypedArray typedArray) { 33 | return new Ripple(this, typedArray); 34 | } 35 | 36 | @Override 37 | public Ripple getRipple() { 38 | return ripple; 39 | } 40 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/IRipple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | 7 | /** 8 | * @Description: 9 | * @Author: cy 10 | * @CreateDate: 2020/6/26 18:30 11 | * @UpdateUser: 12 | * @UpdateDate: 2020/6/26 18:30 13 | * @UpdateRemark: 14 | * @Version: 1.0 15 | */ 16 | public interface IRipple { 17 | public Ripple ripple(TypedArray typedArray); 18 | public Ripple getRipple(); 19 | } 20 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/ImageViewRipple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.content.res.TypedArray; 6 | import android.graphics.ColorMatrixColorFilter; 7 | import android.graphics.drawable.Drawable; 8 | import android.graphics.drawable.GradientDrawable; 9 | import android.graphics.drawable.RippleDrawable; 10 | import android.util.AttributeSet; 11 | import android.view.MotionEvent; 12 | 13 | import androidx.appcompat.widget.AppCompatImageView; 14 | 15 | import com.cy.androidview.R; 16 | 17 | 18 | /** 19 | * Created by cy on 2018/10/27. 20 | */ 21 | 22 | public class ImageViewRipple extends AppCompatImageView implements IRipple { 23 | private Ripple ripple; 24 | public ImageViewRipple(Context context, AttributeSet attrs) { 25 | super(context, attrs); 26 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRipple); 27 | ripple=ripple(typedArray); 28 | typedArray.recycle(); 29 | } 30 | @Override 31 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 32 | super.onLayout(changed, l, t, r, b); 33 | ripple.ripple(); 34 | } 35 | @Override 36 | public Ripple ripple(TypedArray typedArray) { 37 | return new Ripple(this, typedArray); 38 | } 39 | 40 | @Override 41 | public Ripple getRipple() { 42 | return ripple; 43 | } 44 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/LinearLayoutRipple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.content.res.TypedArray; 6 | import android.graphics.drawable.Drawable; 7 | import android.graphics.drawable.RippleDrawable; 8 | import android.util.AttributeSet; 9 | import android.widget.LinearLayout; 10 | 11 | import com.cy.androidview.R; 12 | 13 | 14 | /** 15 | * Created by cy on 2018/10/27. 16 | */ 17 | 18 | public class LinearLayoutRipple extends LinearLayout implements IRipple { 19 | private Ripple ripple; 20 | public LinearLayoutRipple(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRipple); 23 | ripple=ripple(typedArray); 24 | typedArray.recycle(); 25 | } 26 | 27 | @Override 28 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 29 | super.onLayout(changed, l, t, r, b); 30 | ripple.ripple(); 31 | } 32 | 33 | @Override 34 | public Ripple ripple(TypedArray typedArray) { 35 | return new Ripple(this, typedArray); 36 | } 37 | 38 | @Override 39 | public Ripple getRipple() { 40 | return ripple; 41 | } 42 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/RelativeLayoutRipple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.content.res.TypedArray; 6 | import android.graphics.drawable.Drawable; 7 | import android.graphics.drawable.RippleDrawable; 8 | import android.util.AttributeSet; 9 | import android.widget.RelativeLayout; 10 | 11 | import com.cy.androidview.R; 12 | 13 | 14 | /** 15 | * Created by cy on 2018/10/27. 16 | */ 17 | 18 | public class RelativeLayoutRipple extends RelativeLayout implements IRipple { 19 | private Ripple ripple; 20 | public RelativeLayoutRipple(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRipple); 23 | ripple=ripple(typedArray); 24 | typedArray.recycle(); 25 | } 26 | @Override 27 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 28 | super.onLayout(changed, l, t, r, b); 29 | ripple.ripple(); 30 | } 31 | @Override 32 | public Ripple ripple(TypedArray typedArray) { 33 | return new Ripple(this, typedArray); 34 | } 35 | 36 | @Override 37 | public Ripple getRipple() { 38 | return ripple; 39 | } 40 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/Ripple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.res.ColorStateList; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Color; 6 | import android.graphics.drawable.Drawable; 7 | import android.graphics.drawable.GradientDrawable; 8 | import android.graphics.drawable.RippleDrawable; 9 | import android.graphics.drawable.ShapeDrawable; 10 | import android.graphics.drawable.shapes.Shape; 11 | import android.util.AttributeSet; 12 | import android.util.Log; 13 | import android.view.Gravity; 14 | import android.view.View; 15 | 16 | import androidx.annotation.DrawableRes; 17 | import androidx.annotation.StyleableRes; 18 | 19 | import com.cy.androidview.R; 20 | 21 | /** 22 | * @Description: 23 | * @Author: cy 24 | * @CreateDate: 2020/6/26 18:30 25 | * @UpdateUser: 26 | * @UpdateDate: 2020/6/26 18:30 27 | * @UpdateRemark: 28 | * @Version: 1.0 29 | */ 30 | public class Ripple { 31 | private int colorRipple = 0x22000000; 32 | private boolean havaRipple = true; 33 | private TypedArray typedArray; 34 | private View view; 35 | 36 | public Ripple(View view, TypedArray typedArray) { 37 | this.view = view; 38 | this.typedArray = typedArray; 39 | colorRipple = typedArray.getColor(R.styleable.AttrsRipple_cy_colorRipple, colorRipple); 40 | havaRipple = typedArray.getBoolean(R.styleable.AttrsRipple_cy_haveRipple, true); 41 | } 42 | 43 | public Ripple setColorRipple_(int color) { 44 | colorRipple = color; 45 | return this; 46 | } 47 | 48 | 49 | public Ripple setHavaRipple_(boolean havaRipple) { 50 | this.havaRipple = havaRipple; 51 | return this; 52 | } 53 | 54 | public int getColorRipple() { 55 | return colorRipple; 56 | } 57 | 58 | public boolean isHavaRipple() { 59 | return havaRipple; 60 | } 61 | 62 | public Ripple ripple() { 63 | //耗内存极其严重 64 | // RippleDrawable rippleDrawable; 65 | // Drawable drawable_bg = view.getBackground(); 66 | // GradientDrawable drawable_mask = null; 67 | // if (drawable_bg == null) { 68 | // drawable_bg = new ShapeDrawable(); 69 | // drawable_bg.setAlpha(0); 70 | // drawable_bg.setBounds(view.getLeft(), view.getTop(), view.getRight(), view.getBottom()); 71 | // 72 | //// drawable_mask = new GradientDrawable(); 73 | //// drawable_mask.setColor(0xffffffff); 74 | //// if(view.getWidth()>view.getHeight()){ 75 | //// drawable_mask.setBounds((int) (view.getLeft()+view.getWidth()*1f/2-view.getHeight()*1f/2), 76 | //// view.getTop(), 77 | //// (int) (view.getRight()-view.getWidth()*1f/2+view.getHeight()*1f/2), 78 | //// view.getBottom()); 79 | //// drawable_mask.setGradientRadius(10); 80 | //// drawable_mask.setCornerRadius(view.getHeight() * 1f / 2); 81 | //// }else { 82 | //// drawable_mask.setBounds(view.getLeft(), 83 | //// (int) (view.getTop()+view.getHeight()*1f/2-view.getWidth()*1f/2), 84 | //// view.getRight(), 85 | //// (int) (view.getBottom()-view.getHeight()*1f/2+view.getWidth()*1f/2)); 86 | //// drawable_mask.setCornerRadius(view.getWidth() * 1f / 2); 87 | //// } 88 | //// drawable_mask.setStroke(1, 0xffffffff); 89 | // } 90 | // //当控件设置了点击监听器,并且控件点击有效,时,才能产生水波纹 91 | // rippleDrawable = new RippleDrawable(ColorStateList.valueOf(colorRipple), drawable_bg, drawable_mask); 92 | // 93 | // view.setBackground(rippleDrawable); 94 | return this; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/rippleview/TextViewRipple.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.rippleview; 2 | 3 | import android.content.Context; 4 | import android.content.res.ColorStateList; 5 | import android.content.res.TypedArray; 6 | import android.graphics.drawable.Drawable; 7 | import android.graphics.drawable.RippleDrawable; 8 | import android.util.AttributeSet; 9 | 10 | import androidx.appcompat.widget.AppCompatTextView; 11 | 12 | import com.cy.androidview.R; 13 | 14 | 15 | /** 16 | * Created by cy on 2018/10/27. 17 | */ 18 | 19 | public class TextViewRipple extends AppCompatTextView implements IRipple { 20 | private Ripple ripple; 21 | public TextViewRipple(Context context, AttributeSet attrs) { 22 | super(context, attrs); 23 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsRipple); 24 | ripple=ripple(typedArray); 25 | typedArray.recycle(); 26 | } 27 | @Override 28 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 29 | super.onLayout(changed, l, t, r, b); 30 | ripple.ripple(); 31 | } 32 | @Override 33 | public Ripple ripple(TypedArray typedArray) { 34 | return new Ripple(this, typedArray); 35 | } 36 | 37 | @Override 38 | public Ripple getRipple() { 39 | return ripple; 40 | } 41 | } -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/roundview/IRound.java: -------------------------------------------------------------------------------- 1 | //package com.cy.androidview.roundview; 2 | // 3 | //import android.content.res.TypedArray; 4 | // 5 | //import com.cy.androidview.shapeview.ShapeBackground; 6 | // 7 | ///** 8 | // * @Description: 9 | // * @Author: cy 10 | // * @CreateDate: 2020/6/26 22:58 11 | // * @UpdateUser: 12 | // * @UpdateDate: 2020/6/26 22:58 13 | // * @UpdateRemark: 14 | // * @Version: 1.0 15 | // */ 16 | //public interface IRound { 17 | // public Round round(TypedArray typedArray); 18 | // public Round getRound(); 19 | //} 20 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/roundview/Round.java: -------------------------------------------------------------------------------- 1 | //package com.cy.androidview.roundview; 2 | // 3 | //import android.content.res.ColorStateList; 4 | //import android.content.res.TypedArray; 5 | //import android.graphics.Canvas; 6 | //import android.graphics.Color; 7 | //import android.graphics.Paint; 8 | //import android.graphics.Path; 9 | //import android.graphics.PorterDuff; 10 | //import android.graphics.PorterDuffXfermode; 11 | //import android.graphics.RectF; 12 | //import android.graphics.drawable.Drawable; 13 | //import android.graphics.drawable.RippleDrawable; 14 | //import android.view.View; 15 | // 16 | //import androidx.annotation.StyleableRes; 17 | // 18 | //import com.cy.androidview.R; 19 | // 20 | ///** 21 | // * @Description: 22 | // * @Author: cy 23 | // * @CreateDate: 2020/6/26 18:30 24 | // * @UpdateUser: 25 | // * @UpdateDate: 2020/6/26 18:30 26 | // * @UpdateRemark: 27 | // * @Version: 1.0 28 | // */ 29 | //public class Round { 30 | // private TypedArray typedArray; 31 | // private View view; 32 | // private int radius = 20; 33 | // private int topLeftRadius = 20; 34 | // private int topRightRadius = 20; 35 | // private int bottomLeftRadius = 20; 36 | // private int bottomRightRadius = 20; 37 | // private Paint roundPaint; 38 | // 39 | // public Round(View view, TypedArray typedArray) { 40 | // this.view = view; 41 | // this.typedArray = typedArray; 42 | // } 43 | // 44 | // public Round setRadius(@StyleableRes int index) { 45 | // radius = typedArray.getDimensionPixelSize(index, radius); 46 | // topLeftRadius=radius; 47 | // topRightRadius=radius; 48 | // bottomLeftRadius=radius; 49 | // bottomRightRadius=radius; 50 | // return this; 51 | // } 52 | // 53 | // public Round setRadius_(int radius) { 54 | // this.radius = radius; 55 | // topLeftRadius=radius; 56 | // topRightRadius=radius; 57 | // bottomLeftRadius=radius; 58 | // bottomRightRadius=radius; 59 | // return this; 60 | // } 61 | // 62 | // public Round setTopLeftRadius(@StyleableRes int index) { 63 | // topLeftRadius = typedArray.getDimensionPixelSize(index, topLeftRadius); 64 | // return this; 65 | // } 66 | // 67 | // public Round setTopLeftRadius_(int topLeftRadius) { 68 | // this.topLeftRadius = topLeftRadius; 69 | // return this; 70 | // } 71 | // 72 | // public Round setTopRightRadius(@StyleableRes int index) { 73 | // topRightRadius = typedArray.getDimensionPixelSize(index, topRightRadius); 74 | // return this; 75 | // } 76 | // public Round setTopRightRadius_(int topRightRadius) { 77 | // this.topRightRadius=topRightRadius; 78 | // return this; 79 | // } 80 | // 81 | // public Round setBottomLeftRadius(@StyleableRes int index) { 82 | // bottomLeftRadius = typedArray.getDimensionPixelSize(index, bottomLeftRadius); 83 | // return this; 84 | // } 85 | // public Round setBottomLeftRadius_(int bottomLeftRadius) { 86 | // this.bottomLeftRadius=bottomLeftRadius; 87 | // return this; 88 | // } 89 | // 90 | // public Round setBottomRightRadius(@StyleableRes int index) { 91 | // bottomRightRadius = typedArray.getDimensionPixelSize(index, bottomRightRadius); 92 | // return this; 93 | // } 94 | // 95 | // public Round setBottomRightRadius_(int bottomRightRadius) { 96 | // this.bottomRightRadius=bottomRightRadius; 97 | // return this; 98 | // } 99 | // 100 | // public Round saveLayer(Canvas canvas) { 101 | // roundPaint = new Paint(); 102 | // roundPaint.setColor(Color.WHITE); 103 | // roundPaint.setAntiAlias(true); 104 | // roundPaint.setStyle(Paint.Style.FILL); 105 | // roundPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); 106 | // view.setBackgroundColor(0x00000000); 107 | // 108 | // //禁用硬件加速 109 | // view.setLayerType(View.LAYER_TYPE_SOFTWARE, null); 110 | // //离屏绘制,新建图层 111 | // canvas.saveLayer(new RectF(0, 0, canvas.getWidth(), canvas.getHeight()), null, Canvas.ALL_SAVE_FLAG); 112 | // return this; 113 | // } 114 | // 115 | // public Round round(Canvas canvas) { 116 | // drawTopLeft(canvas); 117 | // drawTopRight(canvas); 118 | // drawBottomLeft(canvas); 119 | // drawBottomRight(canvas); 120 | // canvas.restore(); 121 | // return this; 122 | // } 123 | // 124 | // private void drawTopLeft(Canvas canvas) { 125 | // if (topLeftRadius > 0) { 126 | // Path path = new Path(); 127 | // path.moveTo(0, topLeftRadius); 128 | // path.lineTo(0, 0); 129 | // path.lineTo(topLeftRadius, 0); 130 | // path.arcTo(new RectF(0, 0, topLeftRadius * 2, topLeftRadius * 2), -90, -90); 131 | // path.close(); 132 | // canvas.drawPath(path, roundPaint); 133 | // } 134 | // } 135 | // 136 | // private void drawTopRight(Canvas canvas) { 137 | // if (topRightRadius > 0) { 138 | // int width = view.getWidth(); 139 | // Path path = new Path(); 140 | // path.moveTo(width - topRightRadius, 0); 141 | // path.lineTo(width, 0); 142 | // path.lineTo(width, topRightRadius); 143 | // path.arcTo(new RectF(width - 2 * topRightRadius, 0, width, 144 | // topRightRadius * 2), 0, -90); 145 | // path.close(); 146 | // canvas.drawPath(path, roundPaint); 147 | // } 148 | // } 149 | // 150 | // private void drawBottomLeft(Canvas canvas) { 151 | // if (bottomLeftRadius > 0) { 152 | // int height = view.getHeight(); 153 | // Path path = new Path(); 154 | // path.moveTo(0, height - bottomLeftRadius); 155 | // path.lineTo(0, height); 156 | // path.lineTo(bottomLeftRadius, height); 157 | // path.arcTo(new RectF(0, height - 2 * bottomLeftRadius, 158 | // bottomLeftRadius * 2, height), 90, 90); 159 | // path.close(); 160 | // canvas.drawPath(path, roundPaint); 161 | // } 162 | // } 163 | // 164 | // private void drawBottomRight(Canvas canvas) { 165 | // if (bottomRightRadius > 0) { 166 | // int height = view.getHeight(); 167 | // int width = view.getWidth(); 168 | // Path path = new Path(); 169 | // path.moveTo(width - bottomRightRadius, height); 170 | // path.lineTo(width, height); 171 | // path.lineTo(width, height - bottomRightRadius); 172 | // path.arcTo(new RectF(width - 2 * bottomRightRadius, height - 2 173 | // * bottomRightRadius, width, height), 0, 90); 174 | // path.close(); 175 | // canvas.drawPath(path, roundPaint); 176 | // } 177 | // } 178 | //} 179 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/roundview/helper/RCAttrs.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2018 GcsSloop 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * Last modified 2018-04-16 13:11:58 17 | * 18 | * GitHub: https://github.com/GcsSloop 19 | * WeiBo: http://weibo.com/GcsSloop 20 | * WebSite: http://www.gcssloop.com 21 | */ 22 | 23 | package com.cy.androidview.roundview.helper; 24 | 25 | public interface RCAttrs { 26 | void setClipBackground(boolean clipBackground); 27 | 28 | void setRoundAsCircle(boolean roundAsCircle); 29 | 30 | void setRadius(int radius); 31 | 32 | void setTopLeftRadius(int topLeftRadius); 33 | 34 | void setTopRightRadius(int topRightRadius); 35 | 36 | void setBottomLeftRadius(int bottomLeftRadius); 37 | 38 | void setBottomRightRadius(int bottomRightRadius); 39 | 40 | void setStrokeWidth(int strokeWidth); 41 | 42 | void setStrokeColor(int strokeColor); 43 | 44 | boolean isClipBackground(); 45 | 46 | boolean isRoundAsCircle(); 47 | 48 | float getTopLeftRadius(); 49 | 50 | float getTopRightRadius(); 51 | 52 | float getBottomLeftRadius(); 53 | 54 | float getBottomRightRadius(); 55 | 56 | int getStrokeWidth(); 57 | 58 | int getStrokeColor(); 59 | } 60 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/scrollview/ScrollViewOverNever.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.scrollview; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.widget.ScrollView; 6 | 7 | public class ScrollViewOverNever extends ScrollView { 8 | 9 | public ScrollViewOverNever(Context context) { 10 | this(context,null); 11 | } 12 | 13 | public ScrollViewOverNever(Context context, AttributeSet attrs) { 14 | super(context, attrs); 15 | setOverScrollMode(OVER_SCROLL_NEVER); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/selectorview/CheckBoxSelector.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.selectorview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.widget.CompoundButton; 7 | 8 | import androidx.appcompat.widget.AppCompatCheckBox; 9 | 10 | import com.cy.androidview.R; 11 | 12 | 13 | /** 14 | * Created by lenovo on 2017/7/31. 15 | */ 16 | 17 | public class CheckBoxSelector extends AppCompatCheckBox { 18 | private int backgroundID, backgroundCheckedID, bg_color, bg_checked_color, 19 | textColorID, textColorCheckedID, 20 | buttonRes, buttonCheckedRes; 21 | private SelectorOnCheckedChangeListener selectorOnCheckedChangeListener; 22 | 23 | private boolean myListener = true; 24 | 25 | 26 | public CheckBoxSelector(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | 29 | 30 | TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.CheckBoxSelector); 31 | 32 | backgroundID = arr.getResourceId(R.styleable.CheckBoxSelector_cy_backgroundUnChecked, -1);//未选中的背景资源 33 | backgroundCheckedID = arr.getResourceId(R.styleable.CheckBoxSelector_cy_backgroundChecked, -1);//选中的背景资源 34 | 35 | if (backgroundID == -1) { 36 | bg_color = arr.getColor(R.styleable.CheckBoxSelector_cy_backgroundUnChecked, 0x00000000);//未选中的背景颜色 37 | 38 | } 39 | if (backgroundCheckedID == -1) { 40 | bg_checked_color = arr.getColor(R.styleable.CheckBoxSelector_cy_backgroundChecked, 0x00000000);//选中的背景颜色 41 | 42 | } 43 | 44 | buttonRes = arr.getResourceId(R.styleable.CheckBoxSelector_cy_buttonUnChecked, -1);//未选中的按钮资源 45 | buttonCheckedRes = arr.getResourceId(R.styleable.CheckBoxSelector_cy_buttonChecked, -1);//选中的按钮资源 46 | 47 | textColorID = arr.getColor(R.styleable.CheckBoxSelector_cy_textColorUnChecked, getCurrentTextColor());//未选中的文字颜色 48 | textColorCheckedID = arr.getColor(R.styleable.CheckBoxSelector_cy_textColorChecked, getCurrentTextColor());//选中的文字颜色 49 | arr.recycle(); 50 | 51 | if (isChecked()) { 52 | 53 | setResOnChecked(); 54 | 55 | } else { 56 | setResOnUnChecked(); 57 | 58 | } 59 | 60 | setOnCheckedChangeListener(new OnCheckedChangeListener() { 61 | @Override 62 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 63 | if (isChecked) { 64 | setResOnChecked(); 65 | } else { 66 | setResOnUnChecked(); 67 | } 68 | if (selectorOnCheckedChangeListener != null) { 69 | selectorOnCheckedChangeListener.onCheckedChanged(buttonView, isChecked); 70 | } 71 | } 72 | }); 73 | 74 | } 75 | 76 | @Override 77 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { 78 | if (myListener) { 79 | super.setOnCheckedChangeListener(listener); 80 | myListener = false; 81 | } 82 | } 83 | 84 | //监听器使用这个方法 85 | public void setSelectorOnCheckedChangeListener(SelectorOnCheckedChangeListener listener) { 86 | this.selectorOnCheckedChangeListener = listener; 87 | } 88 | 89 | public static interface SelectorOnCheckedChangeListener extends OnCheckedChangeListener { 90 | @Override 91 | void onCheckedChanged(CompoundButton buttonView, boolean isChecked); 92 | } 93 | 94 | //设置选中时的背景,文字颜色等 95 | private void setResOnChecked() { 96 | if (backgroundCheckedID != -1) { 97 | 98 | setBackgroundResource(backgroundCheckedID); 99 | } else { 100 | setBackgroundColor(bg_checked_color); 101 | } 102 | if (buttonCheckedRes != -1) { 103 | setButtonDrawable(buttonCheckedRes); 104 | } 105 | 106 | setTextColor(textColorCheckedID); 107 | } 108 | //设置未选中时的背景,文字颜色等 109 | 110 | private void setResOnUnChecked() { 111 | if (backgroundID != -1) { 112 | 113 | setBackgroundResource(backgroundID); 114 | } else { 115 | setBackgroundColor(bg_color); 116 | } 117 | if (buttonRes != -1) { 118 | setButtonDrawable(buttonRes); 119 | } 120 | setTextColor(textColorID); 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/selectorview/FrameLayoutSelector.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.selectorview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.FrameLayout; 9 | 10 | import androidx.annotation.NonNull; 11 | import androidx.annotation.Nullable; 12 | 13 | import com.cy.androidview.R; 14 | 15 | /** 16 | * @Description: 17 | * @Author: cy 18 | * @CreateDate: 2021/1/9 15:14 19 | * @UpdateUser: 20 | * @UpdateDate: 2021/1/9 15:14 21 | * @UpdateRemark: 22 | * @Version: 23 | */ 24 | public class FrameLayoutSelector extends FrameLayout { 25 | private int backgroundID, backgroundCheckedID, bg_color, bg_checked_color; 26 | 27 | private OnCheckedChangeListener onCheckedChangeListener; 28 | private boolean isChecked = false; 29 | 30 | private boolean isMyListener = true; 31 | 32 | 33 | public FrameLayoutSelector(Context context, AttributeSet attrs) { 34 | super(context, attrs); 35 | 36 | TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.FrameLayoutSelector); 37 | backgroundID = arr.getResourceId(R.styleable.FrameLayoutSelector_cy_bgUnChecked, -1);//未选中时的背景 38 | backgroundCheckedID = arr.getResourceId(R.styleable.FrameLayoutSelector_cy_bgChecked, -1);//选中时的背景 39 | 40 | if (backgroundID == -1) { 41 | bg_color = arr.getColor(R.styleable.FrameLayoutSelector_cy_bgUnChecked, 0x00000000);//未选中时的背景颜色 42 | 43 | } 44 | if (backgroundCheckedID == -1) { 45 | bg_checked_color = arr.getColor(R.styleable.FrameLayoutSelector_cy_bgChecked, 0x00000000);//选中时的背景颜色 46 | } 47 | isChecked = arr.getBoolean(R.styleable.FrameLayoutSelector_cy_checked, false);//是否选中 48 | 49 | 50 | if (isChecked()) { 51 | 52 | setResOnChecked(); 53 | 54 | } else { 55 | setResOnUnChecked(); 56 | 57 | } 58 | arr.recycle(); 59 | setOnClickListener(new OnClickListener() { 60 | @Override 61 | public void onClick(View v) { 62 | setChecked(!isChecked); 63 | } 64 | }); 65 | 66 | } 67 | 68 | 69 | @Override 70 | public void setOnClickListener(OnClickListener l) { 71 | if (isMyListener) { 72 | super.setOnClickListener(l); 73 | isMyListener = false; 74 | } 75 | } 76 | 77 | //监听器使用这个方法 78 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { 79 | this.onCheckedChangeListener = listener; 80 | } 81 | 82 | public static interface OnCheckedChangeListener { 83 | void onCheckedChanged(FrameLayoutSelector iv, boolean isChecked); 84 | } 85 | 86 | //判断是否选中 87 | public boolean isChecked() { 88 | return isChecked; 89 | } 90 | 91 | //设置是否选中 92 | public void setChecked(boolean checked) { 93 | if(isChecked==checked)return; 94 | isChecked = checked; 95 | if (checked) { 96 | setResOnChecked(); 97 | } else { 98 | setResOnUnChecked(); 99 | } 100 | if (onCheckedChangeListener != null) { 101 | onCheckedChangeListener.onCheckedChanged(FrameLayoutSelector.this, isChecked); 102 | } 103 | } 104 | //设置选中时的背景,Src等 105 | 106 | private void setResOnChecked() { 107 | if (backgroundCheckedID != -1) { 108 | 109 | setBackgroundResource(backgroundCheckedID); 110 | } else { 111 | setBackgroundColor(bg_checked_color); 112 | } 113 | } 114 | 115 | //设置未选中时的背景,Src等 116 | private void setResOnUnChecked() { 117 | if (backgroundID != -1) { 118 | setBackgroundResource(backgroundID); 119 | } else { 120 | setBackgroundColor(bg_color); 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/selectorview/ImageViewSelector.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.selectorview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.View; 8 | 9 | import androidx.appcompat.widget.AppCompatImageView; 10 | 11 | import com.cy.androidview.R; 12 | 13 | 14 | /** 15 | * Created by lenovo on 2017/8/30. 16 | */ 17 | 18 | public class ImageViewSelector extends AppCompatImageView { 19 | private int backgroundID, backgroundCheckedID, bg_color, bg_checked_color, 20 | srcCheckedID, srcUncheckedID; 21 | 22 | private OnCheckedChangeListener onCheckedChangeListener; 23 | private boolean isChecked = false; 24 | 25 | private boolean isMyListener = true; 26 | 27 | 28 | public ImageViewSelector(Context context, AttributeSet attrs) { 29 | super(context, attrs); 30 | 31 | TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.ImageViewSelector); 32 | backgroundID = arr.getResourceId(R.styleable.ImageViewSelector_cy_bgUnChecked, -1);//未选中时的背景 33 | backgroundCheckedID = arr.getResourceId(R.styleable.ImageViewSelector_cy_bgChecked, -1);//选中时的背景 34 | 35 | if (backgroundID == -1) { 36 | bg_color = arr.getColor(R.styleable.ImageViewSelector_cy_bgUnChecked, 0x00000000);//未选中时的背景颜色 37 | 38 | } 39 | if (backgroundCheckedID == -1) { 40 | bg_checked_color = arr.getColor(R.styleable.ImageViewSelector_cy_bgChecked, 0x00000000);//选中时的背景颜色 41 | 42 | } 43 | 44 | srcCheckedID = arr.getResourceId(R.styleable.ImageViewSelector_cy_srcChecked, -1);//未选中时的src 45 | srcUncheckedID = arr.getResourceId(R.styleable.ImageViewSelector_cy_srcUnChecked, -1);//选中时的src 46 | isChecked = arr.getBoolean(R.styleable.ImageViewSelector_cy_checked, false);//是否选中 47 | 48 | 49 | if (isChecked()) { 50 | 51 | setResOnChecked(); 52 | 53 | } else { 54 | setResOnUnChecked(); 55 | 56 | } 57 | arr.recycle(); 58 | setOnClickListener(new OnClickListener() { 59 | @Override 60 | public void onClick(View v) { 61 | setChecked(!isChecked); 62 | } 63 | }); 64 | 65 | } 66 | 67 | 68 | @Override 69 | public void setOnClickListener(OnClickListener l) { 70 | if (isMyListener) { 71 | super.setOnClickListener(l); 72 | isMyListener = false; 73 | } 74 | } 75 | 76 | //监听器使用这个方法 77 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { 78 | this.onCheckedChangeListener = listener; 79 | } 80 | 81 | public static interface OnCheckedChangeListener { 82 | void onCheckedChanged(ImageViewSelector iv, boolean isChecked); 83 | } 84 | 85 | //判断是否选中 86 | public boolean isChecked() { 87 | return isChecked; 88 | } 89 | 90 | //设置是否选中 91 | public void setChecked(boolean checked) { 92 | if(isChecked==checked)return; 93 | isChecked = checked; 94 | if (checked) { 95 | setResOnChecked(); 96 | } else { 97 | setResOnUnChecked(); 98 | } 99 | if (onCheckedChangeListener != null) { 100 | onCheckedChangeListener.onCheckedChanged(ImageViewSelector.this, isChecked); 101 | } 102 | } 103 | //设置选中时的背景,Src等 104 | 105 | private void setResOnChecked() { 106 | if (backgroundCheckedID != -1) { 107 | 108 | setBackgroundResource(backgroundCheckedID); 109 | } else { 110 | setBackgroundColor(bg_checked_color); 111 | } 112 | if (srcCheckedID != -1) { 113 | setImageResource(srcCheckedID); 114 | } 115 | 116 | } 117 | 118 | //设置未选中时的背景,Src等 119 | private void setResOnUnChecked() { 120 | if (backgroundID != -1) { 121 | setBackgroundResource(backgroundID); 122 | } else { 123 | setBackgroundColor(bg_color); 124 | } 125 | if (srcUncheckedID != -1) { 126 | setImageResource(srcUncheckedID); 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/selectorview/RadioButtonSelector.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.selectorview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.widget.CompoundButton; 7 | 8 | import androidx.appcompat.widget.AppCompatRadioButton; 9 | 10 | import com.cy.androidview.R; 11 | 12 | 13 | /** 14 | * Created by lenovo on 2017/7/31. 15 | */ 16 | 17 | public class RadioButtonSelector extends AppCompatRadioButton { 18 | private int backgroundID, backgroundCheckedID, bg_color, bg_checked_color, 19 | textColorID, textColorCheckedID, 20 | buttonRes, buttonCheckedRes; 21 | private SelectorOnCheckedChangeListener selectorOnCheckedChangeListener; 22 | 23 | private boolean myListener = true; 24 | 25 | public RadioButtonSelector(Context context, AttributeSet attrs) { 26 | super(context, attrs); 27 | 28 | 29 | TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.RadioButtonSelector); 30 | 31 | backgroundID = arr.getResourceId(R.styleable.RadioButtonSelector_cy_backgroundUnChecked, -1);//未选中的背景资源 32 | backgroundCheckedID = arr.getResourceId(R.styleable.RadioButtonSelector_cy_backgroundChecked, -1);//选中的背景资源 33 | 34 | if (backgroundID == -1) { 35 | bg_color = arr.getColor(R.styleable.RadioButtonSelector_cy_backgroundUnChecked, 0x00000000);//未选中的背景颜色 36 | 37 | } 38 | if (backgroundCheckedID == -1) { 39 | bg_checked_color = arr.getColor(R.styleable.RadioButtonSelector_cy_backgroundChecked, 0x00000000);//选中的背景颜色 40 | 41 | } 42 | 43 | buttonRes = arr.getResourceId(R.styleable.RadioButtonSelector_cy_buttonUnChecked, -1);//未选中的按钮资源 44 | buttonCheckedRes = arr.getResourceId(R.styleable.RadioButtonSelector_cy_buttonChecked, -1);//选中的按钮资源 45 | 46 | textColorID = arr.getColor(R.styleable.RadioButtonSelector_cy_textColorUnChecked, -1);//未选中的文字颜色 47 | textColorCheckedID = arr.getColor(R.styleable.RadioButtonSelector_cy_textColorChecked, -1);//选中的文字颜色 48 | 49 | arr.recycle(); 50 | 51 | if (isChecked()) { 52 | 53 | setResOnChecked(); 54 | 55 | } else { 56 | setResOnUnChecked(); 57 | 58 | } 59 | 60 | setOnCheckedChangeListener(new OnCheckedChangeListener() { 61 | @Override 62 | public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 63 | if (isChecked) { 64 | setResOnChecked(); 65 | } else { 66 | setResOnUnChecked(); 67 | } 68 | if (selectorOnCheckedChangeListener != null) { 69 | selectorOnCheckedChangeListener.onCheckedChanged(buttonView, isChecked); 70 | } 71 | } 72 | }); 73 | } 74 | 75 | @Override 76 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { 77 | if (myListener) { 78 | 79 | super.setOnCheckedChangeListener(listener); 80 | myListener = false; 81 | } 82 | } 83 | 84 | //监听器使用这个方法 85 | public void setSelectorOnCheckedChangeListener(SelectorOnCheckedChangeListener listener) { 86 | this.selectorOnCheckedChangeListener = listener; 87 | } 88 | 89 | public static interface SelectorOnCheckedChangeListener extends OnCheckedChangeListener { 90 | @Override 91 | void onCheckedChanged(CompoundButton buttonView, boolean isChecked); 92 | } 93 | 94 | //设置选中时的背景,文字颜色等 95 | private void setResOnChecked() { 96 | if (backgroundCheckedID != -1) { 97 | 98 | setBackgroundResource(backgroundCheckedID); 99 | } else { 100 | setBackgroundColor(bg_checked_color); 101 | } 102 | if (buttonCheckedRes != -1) { 103 | setButtonDrawable(buttonCheckedRes); 104 | } 105 | 106 | setTextColor(textColorCheckedID); 107 | } 108 | //设置未选中时的背景,文字颜色等 109 | 110 | private void setResOnUnChecked() { 111 | if (backgroundID != -1) { 112 | 113 | setBackgroundResource(backgroundID); 114 | } else { 115 | setBackgroundColor(bg_color); 116 | } 117 | if (buttonRes != -1) { 118 | setButtonDrawable(buttonRes); 119 | } 120 | 121 | 122 | setTextColor(textColorID); 123 | } 124 | } 125 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/selectorview/TextViewSelector.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.selectorview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.util.Log; 7 | import android.view.View; 8 | import android.widget.FrameLayout; 9 | import android.widget.TextView; 10 | 11 | import androidx.annotation.ColorInt; 12 | import androidx.appcompat.widget.AppCompatTextView; 13 | import androidx.core.widget.TextViewCompat; 14 | 15 | import com.cy.androidview.R; 16 | 17 | /** 18 | * @Description: 19 | * @Author: cy 20 | * @CreateDate: 2021/1/9 15:14 21 | * @UpdateUser: 22 | * @UpdateDate: 2021/1/9 15:14 23 | * @UpdateRemark: 24 | * @Version: 25 | */ 26 | public class TextViewSelector extends AppCompatTextView { 27 | private int backgroundID, backgroundCheckedID, bg_color, bg_checked_color; 28 | private int tv_color, tv_color_checked; 29 | 30 | private TextViewSelector.OnCheckedChangeListener onCheckedChangeListener; 31 | private boolean isChecked = false; 32 | 33 | private boolean isMyListener = true; 34 | 35 | 36 | public TextViewSelector(Context context, AttributeSet attrs) { 37 | super(context, attrs); 38 | 39 | TypedArray arr = context.obtainStyledAttributes(attrs, R.styleable.TextViewSelector); 40 | backgroundID = arr.getResourceId(R.styleable.TextViewSelector_cy_bgUnChecked, -1);//未选中时的背景 41 | backgroundCheckedID = arr.getResourceId(R.styleable.TextViewSelector_cy_bgChecked, -1);//选中时的背景 42 | 43 | if (backgroundID == -1) { 44 | bg_color = arr.getColor(R.styleable.TextViewSelector_cy_bgUnChecked, 0x00000000);//未选中时的背景颜色 45 | } 46 | if (backgroundCheckedID == -1) { 47 | bg_checked_color = arr.getColor(R.styleable.TextViewSelector_cy_bgChecked, 0x00000000);//选中时的背景颜色 48 | } 49 | 50 | tv_color_checked = arr.getColor(R.styleable.TextViewSelector_cy_textColorChecked, -1); 51 | tv_color = arr.getColor(R.styleable.TextViewSelector_cy_textColorUnChecked, -1); 52 | //即使有颜色,也是-1,奇了葩了 53 | // LogUtils.log("tv_color_checked",tv_color_checked); 54 | isChecked = arr.getBoolean(R.styleable.TextViewSelector_cy_checked, false);//是否选中 55 | 56 | arr.recycle(); 57 | 58 | if (isChecked()) { 59 | 60 | setResOnChecked(); 61 | 62 | } else { 63 | setResOnUnChecked(); 64 | 65 | } 66 | setOnClickListener(new OnClickListener() { 67 | @Override 68 | public void onClick(View v) { 69 | setChecked(!isChecked); 70 | } 71 | }); 72 | 73 | } 74 | 75 | 76 | @Override 77 | public void setOnClickListener(OnClickListener l) { 78 | if (isMyListener) { 79 | super.setOnClickListener(l); 80 | isMyListener = false; 81 | } 82 | } 83 | 84 | //监听器使用这个方法 85 | public void setOnCheckedChangeListener(TextViewSelector.OnCheckedChangeListener listener) { 86 | this.onCheckedChangeListener = listener; 87 | } 88 | 89 | public static interface OnCheckedChangeListener { 90 | void onCheckedChanged(TextViewSelector iv, boolean isChecked); 91 | } 92 | 93 | //判断是否选中 94 | public boolean isChecked() { 95 | return isChecked; 96 | } 97 | 98 | //设置是否选中 99 | public void setChecked(boolean checked) { 100 | if(isChecked==checked)return; 101 | isChecked = checked; 102 | if (checked) { 103 | setResOnChecked(); 104 | } else { 105 | setResOnUnChecked(); 106 | } 107 | if (onCheckedChangeListener != null) { 108 | onCheckedChangeListener.onCheckedChanged(TextViewSelector.this, isChecked); 109 | } 110 | } 111 | //设置选中时的背景,Src等 112 | 113 | private void setResOnChecked() { 114 | if (backgroundCheckedID != -1) { 115 | setBackgroundResource(backgroundCheckedID); 116 | } else { 117 | setBackgroundColor(bg_checked_color); 118 | } 119 | setTextColor(tv_color_checked); 120 | } 121 | 122 | //设置未选中时的背景,Src等 123 | private void setResOnUnChecked() { 124 | if (backgroundID != -1) { 125 | setBackgroundResource(backgroundID); 126 | } else { 127 | setBackgroundColor(bg_color); 128 | } 129 | setTextColor(tv_color); 130 | } 131 | } 132 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/shapeview/ButtonShape.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.shapeview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import androidx.appcompat.widget.AppCompatButton; 10 | 11 | import com.cy.androidview.R; 12 | import com.cy.androidview.ViewMeasureUtils; 13 | import com.cy.androidview.rectangleview.IRectangle; 14 | import com.cy.androidview.rectangleview.RectangleRatio; 15 | import com.cy.androidview.rippleview.IRipple; 16 | import com.cy.androidview.rippleview.Ripple; 17 | 18 | 19 | /** 20 | * Created by cy on 2018/10/24. 21 | */ 22 | 23 | public class ButtonShape extends AppCompatButton implements IShape, IRectangle, IRipple { 24 | private RectangleRatio rectangleRatio; 25 | private Ripple ripple; 26 | private ShapeBackground shapeBackground; 27 | public ButtonShape(Context context, AttributeSet attrs) { 28 | super(context, attrs); 29 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsShape); 30 | ripple=ripple(typedArray); 31 | shapeBackground=shape(typedArray); 32 | rectangleRatio = rectangle(typedArray); 33 | typedArray.recycle(); 34 | } 35 | @Override 36 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 37 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 38 | super.onMeasure(specs[0],specs[1]); 39 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 40 | } 41 | @Override 42 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 43 | super.onLayout(changed, l, t, r, b); 44 | ripple.ripple(); 45 | } 46 | @Override 47 | public RectangleRatio rectangle(TypedArray typedArray) { 48 | return new RectangleRatio(this,typedArray) 49 | .setHeightWidthRatio(R.styleable.AttrsShape_cy_heightWidthRatio,0); 50 | } 51 | 52 | @Override 53 | public Ripple ripple(TypedArray typedArray) { 54 | return new Ripple(this, typedArray); 55 | } 56 | 57 | @Override 58 | public ShapeBackground shape(TypedArray typedArray) { 59 | return new ShapeBackground(this,typedArray).shape(); 60 | } 61 | 62 | @Override 63 | public Ripple getRipple() { 64 | return ripple; 65 | } 66 | 67 | @Override 68 | public ShapeBackground getShapeBackground() { 69 | return shapeBackground; 70 | } 71 | 72 | @Override 73 | public RectangleRatio getRectangleRatio() { 74 | return rectangleRatio; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/shapeview/FrameLayoutShape.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.shapeview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.FrameLayout; 9 | 10 | import com.cy.androidview.R; 11 | import com.cy.androidview.ViewMeasureUtils; 12 | import com.cy.androidview.rectangleview.IRectangle; 13 | import com.cy.androidview.rectangleview.RectangleRatio; 14 | import com.cy.androidview.rippleview.IRipple; 15 | import com.cy.androidview.rippleview.Ripple; 16 | 17 | 18 | /** 19 | * Created by cy on 2018/10/24. 20 | */ 21 | 22 | public class FrameLayoutShape extends FrameLayout implements IShape, IRectangle, IRipple { 23 | private RectangleRatio rectangleRatio; 24 | private Ripple ripple; 25 | private ShapeBackground shapeBackground; 26 | public FrameLayoutShape(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsShape); 29 | ripple=ripple(typedArray); 30 | shapeBackground=shape(typedArray); 31 | rectangleRatio = rectangle(typedArray); 32 | typedArray.recycle(); 33 | } 34 | 35 | @Override 36 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 37 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 38 | super.onMeasure(specs[0],specs[1]); 39 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 40 | } 41 | @Override 42 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 43 | super.onLayout(changed, l, t, r, b); 44 | ripple.ripple(); 45 | } 46 | @Override 47 | public RectangleRatio rectangle(TypedArray typedArray) { 48 | return new RectangleRatio(this,typedArray) 49 | .setHeightWidthRatio(R.styleable.AttrsShape_cy_heightWidthRatio,0); 50 | } 51 | 52 | @Override 53 | public Ripple ripple(TypedArray typedArray) { 54 | return new Ripple(this, typedArray); 55 | } 56 | 57 | @Override 58 | public ShapeBackground shape(TypedArray typedArray) { 59 | return new ShapeBackground(this,typedArray) 60 | .shape(); 61 | } 62 | 63 | @Override 64 | public RectangleRatio getRectangleRatio() { 65 | return rectangleRatio; 66 | } 67 | 68 | @Override 69 | public Ripple getRipple() { 70 | return ripple; 71 | } 72 | 73 | @Override 74 | public ShapeBackground getShapeBackground() { 75 | return shapeBackground; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/shapeview/IShape.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.shapeview; 2 | 3 | import android.content.res.TypedArray; 4 | import android.graphics.drawable.shapes.Shape; 5 | 6 | import com.cy.androidview.rippleview.Ripple; 7 | 8 | /** 9 | * @Description: 10 | * @Author: cy 11 | * @CreateDate: 2020/6/26 22:58 12 | * @UpdateUser: 13 | * @UpdateDate: 2020/6/26 22:58 14 | * @UpdateRemark: 15 | * @Version: 1.0 16 | */ 17 | public interface IShape { 18 | public ShapeBackground shape(TypedArray typedArray); 19 | public ShapeBackground getShapeBackground(); 20 | } 21 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/shapeview/LinearLayoutShape.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.shapeview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.LinearLayout; 9 | 10 | import com.cy.androidview.R; 11 | import com.cy.androidview.ViewMeasureUtils; 12 | import com.cy.androidview.rectangleview.IRectangle; 13 | import com.cy.androidview.rectangleview.RectangleRatio; 14 | import com.cy.androidview.rippleview.IRipple; 15 | import com.cy.androidview.rippleview.Ripple; 16 | 17 | 18 | /** 19 | * Created by cy on 2018/10/24. 20 | */ 21 | 22 | public class LinearLayoutShape extends LinearLayout implements IShape, IRectangle, IRipple { 23 | private RectangleRatio rectangleRatio; 24 | private Ripple ripple; 25 | private ShapeBackground shapeBackground; 26 | public LinearLayoutShape(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsShape); 29 | ripple=ripple(typedArray); 30 | shapeBackground=shape(typedArray); 31 | rectangleRatio = rectangle(typedArray); 32 | typedArray.recycle(); 33 | } 34 | @Override 35 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 36 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 37 | super.onMeasure(specs[0],specs[1]); 38 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 39 | } 40 | @Override 41 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 42 | super.onLayout(changed, l, t, r, b); 43 | ripple.ripple(); 44 | } 45 | @Override 46 | public RectangleRatio rectangle(TypedArray typedArray) { 47 | return new RectangleRatio(this,typedArray) 48 | .setHeightWidthRatio(R.styleable.AttrsShape_cy_heightWidthRatio,0); 49 | } 50 | 51 | @Override 52 | public Ripple ripple(TypedArray typedArray) { 53 | return new Ripple(this, typedArray); 54 | } 55 | 56 | @Override 57 | public ShapeBackground shape(TypedArray typedArray) { 58 | return new ShapeBackground(this,typedArray) 59 | .shape(); 60 | } 61 | 62 | @Override 63 | public Ripple getRipple() { 64 | return ripple; 65 | } 66 | 67 | @Override 68 | public RectangleRatio getRectangleRatio() { 69 | return rectangleRatio; 70 | } 71 | 72 | @Override 73 | public ShapeBackground getShapeBackground() { 74 | return shapeBackground; 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/shapeview/RelativeLayoutShape.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.shapeview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | import android.widget.RelativeLayout; 9 | 10 | import com.cy.androidview.R; 11 | import com.cy.androidview.ViewMeasureUtils; 12 | import com.cy.androidview.rectangleview.IRectangle; 13 | import com.cy.androidview.rectangleview.RectangleRatio; 14 | import com.cy.androidview.rippleview.IRipple; 15 | import com.cy.androidview.rippleview.Ripple; 16 | 17 | 18 | /** 19 | * Created by cy on 2018/10/24. 20 | */ 21 | 22 | public class RelativeLayoutShape extends RelativeLayout implements IShape, IRectangle, IRipple { 23 | private RectangleRatio rectangleRatio; 24 | private Ripple ripple; 25 | private ShapeBackground shapeBackground; 26 | public RelativeLayoutShape(Context context, AttributeSet attrs) { 27 | super(context, attrs); 28 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsShape); 29 | ripple=ripple(typedArray); 30 | shapeBackground=shape(typedArray); 31 | rectangleRatio = rectangle(typedArray); 32 | typedArray.recycle(); 33 | } 34 | 35 | @Override 36 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 37 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 38 | super.onMeasure(specs[0],specs[1]); 39 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 40 | } 41 | @Override 42 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 43 | super.onLayout(changed, l, t, r, b); 44 | ripple.ripple(); 45 | } 46 | @Override 47 | public RectangleRatio rectangle(TypedArray typedArray) { 48 | return new RectangleRatio(this,typedArray) 49 | .setHeightWidthRatio(R.styleable.AttrsShape_cy_heightWidthRatio,0); 50 | } 51 | 52 | @Override 53 | public Ripple ripple(TypedArray typedArray) { 54 | return new Ripple(this, typedArray); 55 | } 56 | 57 | @Override 58 | public ShapeBackground shape(TypedArray typedArray) { 59 | return new ShapeBackground(this,typedArray) 60 | .shape(); 61 | } 62 | 63 | @Override 64 | public Ripple getRipple() { 65 | return ripple; 66 | } 67 | 68 | @Override 69 | public RectangleRatio getRectangleRatio() { 70 | return rectangleRatio; 71 | } 72 | 73 | @Override 74 | public ShapeBackground getShapeBackground() { 75 | return shapeBackground; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/shapeview/TextViewShape.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.shapeview; 2 | 3 | import android.content.Context; 4 | import android.content.res.TypedArray; 5 | import android.util.AttributeSet; 6 | import android.view.View; 7 | import android.view.ViewGroup; 8 | 9 | import androidx.appcompat.widget.AppCompatTextView; 10 | 11 | import com.cy.androidview.R; 12 | import com.cy.androidview.ViewMeasureUtils; 13 | import com.cy.androidview.rectangleview.IRectangle; 14 | import com.cy.androidview.rectangleview.RectangleRatio; 15 | import com.cy.androidview.rippleview.IRipple; 16 | import com.cy.androidview.rippleview.Ripple; 17 | 18 | 19 | /** 20 | * Created by cy on 2018/10/24. 21 | */ 22 | 23 | public class TextViewShape extends AppCompatTextView implements IShape, IRectangle, IRipple { 24 | private RectangleRatio rectangleRatio; 25 | private ShapeBackground shapeBackground; 26 | private Ripple ripple; 27 | public TextViewShape(Context context, AttributeSet attrs) { 28 | super(context, attrs); 29 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttrsShape); 30 | ripple=ripple(typedArray); 31 | shapeBackground = shape(typedArray); 32 | rectangleRatio = rectangle(typedArray); 33 | typedArray.recycle(); 34 | } 35 | 36 | @Override 37 | protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 38 | int[] specs=rectangleRatio.rectangle(widthMeasureSpec,heightMeasureSpec); 39 | super.onMeasure(specs[0],specs[1]); 40 | //不要调用setMeasuredDimension,否则会导致子View的测量不灵,GG 41 | } 42 | @Override 43 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 44 | super.onLayout(changed, l, t, r, b); 45 | ripple.ripple(); 46 | } 47 | @Override 48 | public RectangleRatio rectangle(TypedArray typedArray) { 49 | return new RectangleRatio(this, typedArray) 50 | .setHeightWidthRatio(R.styleable.AttrsShape_cy_heightWidthRatio, 0); 51 | } 52 | 53 | @Override 54 | public Ripple ripple(TypedArray typedArray) { 55 | return new Ripple(this, typedArray); 56 | } 57 | 58 | @Override 59 | public ShapeBackground shape(TypedArray typedArray) { 60 | return new ShapeBackground(this, typedArray) 61 | .shape(); 62 | } 63 | 64 | public ShapeBackground getShapeBackground() { 65 | return shapeBackground; 66 | } 67 | 68 | @Override 69 | public Ripple getRipple() { 70 | return ripple; 71 | } 72 | 73 | @Override 74 | public RectangleRatio getRectangleRatio() { 75 | return rectangleRatio; 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/swipe/SwipeActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.swipe; 2 | 3 | import android.app.Activity; 4 | import android.content.res.TypedArray; 5 | import android.graphics.Color; 6 | import android.graphics.drawable.ColorDrawable; 7 | import android.graphics.drawable.Drawable; 8 | import android.os.Build; 9 | import android.os.Bundle; 10 | import android.view.MotionEvent; 11 | import android.view.View; 12 | import android.view.ViewGroup; 13 | import android.view.Window; 14 | import android.view.WindowManager; 15 | 16 | import androidx.activity.ComponentActivity; 17 | import androidx.annotation.Nullable; 18 | 19 | import com.cy.androidview.R; 20 | import com.cy.androidview.ScreenUtils; 21 | 22 | public class SwipeActivity extends ComponentActivity { 23 | private float downX; 24 | private static final int SWIPE_THRESHOLD = 200; // 触发返回的滑动距离 25 | private ViewGroup viewDecor; 26 | private boolean draging = false; 27 | private float dx; 28 | private View contentView; 29 | private SwipeLayout swipeLayout; 30 | private ViewGroup decorChild; 31 | 32 | @Override 33 | protected void onCreate(@Nullable Bundle savedInstanceState) { 34 | super.onCreate(savedInstanceState); 35 | 36 | swipeLayout = new SwipeLayout(this); 37 | getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT)); 38 | getWindow().getDecorView().setBackgroundDrawable(null); 39 | TransparentUtils.convertActivityToTranslucent(this); 40 | } 41 | 42 | @Override 43 | protected void onPostCreate(@Nullable Bundle savedInstanceState) { 44 | super.onPostCreate(savedInstanceState); 45 | TypedArray a = getTheme().obtainStyledAttributes(new int[]{ 46 | android.R.attr.windowBackground 47 | }); 48 | int background = a.getResourceId(0, 0); 49 | a.recycle(); 50 | 51 | ViewGroup decor = (ViewGroup) getWindow().getDecorView(); 52 | decorChild = (ViewGroup) decor.getChildAt(0); 53 | decorChild.setBackgroundResource(background); 54 | decor.removeView(decorChild); 55 | swipeLayout.addView(decorChild, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 56 | swipeLayout.setContentView(decorChild); 57 | decor.addView(swipeLayout, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)); 58 | } 59 | 60 | 61 | @Override 62 | public boolean onTouchEvent(MotionEvent event) { 63 | switch (event.getActionMasked()) { 64 | case MotionEvent.ACTION_DOWN: 65 | case MotionEvent.ACTION_POINTER_DOWN: 66 | downX = event.getX(); 67 | draging = false; 68 | break; 69 | case MotionEvent.ACTION_MOVE: 70 | float moveX = event.getX(); 71 | dx = moveX - downX; 72 | if (dx >= SWIPE_THRESHOLD) draging = true; 73 | if (draging){ 74 | swipeLayout.setMargin_left((int) dx); 75 | swipeLayout.requestLayout(); 76 | } 77 | // if (deltaX > SWIPE_THRESHOLD) { 78 | // finish(); 79 | // overridePendingTransition(0, R.anim.slide_out_right); 80 | // } 81 | break; 82 | case MotionEvent.ACTION_UP: 83 | case MotionEvent.ACTION_POINTER_UP: 84 | case MotionEvent.ACTION_CANCEL: 85 | if (dx > ScreenUtils.getScreenWidth(this) * 0.5) { 86 | finish(); 87 | } else { 88 | swipeLayout.setMargin_left(0); 89 | swipeLayout.requestLayout(); 90 | } 91 | break; 92 | } 93 | return super.onTouchEvent(event); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/swipe/SwipeLayout.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.swipe; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | import android.view.View; 6 | import android.view.ViewGroup; 7 | import android.widget.FrameLayout; 8 | 9 | import com.cy.androidview.LogUtils; 10 | 11 | public class SwipeLayout extends FrameLayout { 12 | private View contentView; 13 | private int margin_left; 14 | private int margin_top; 15 | public SwipeLayout(Context context) { 16 | this(context,null); 17 | } 18 | 19 | public SwipeLayout(Context context, AttributeSet attrs) { 20 | super(context, attrs); 21 | } 22 | 23 | @Override 24 | protected void onLayout(boolean changed, int l, int t, int r, int b) { 25 | if (contentView != null) 26 | contentView.layout(margin_left, margin_top, 27 | margin_left + contentView.getMeasuredWidth(), 28 | margin_top + contentView.getMeasuredHeight()); 29 | } 30 | 31 | public void setContentView(View contentView) { 32 | this.contentView = contentView; 33 | } 34 | 35 | public void setMargin_left(int margin_left) { 36 | this.margin_left = margin_left; 37 | } 38 | 39 | public void setMargin_top(int margin_top) { 40 | this.margin_top = margin_top; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/swipe/TransparentUtils.java: -------------------------------------------------------------------------------- 1 | 2 | package com.cy.androidview.swipe; 3 | 4 | import android.app.Activity; 5 | import android.app.ActivityOptions; 6 | import android.os.Build; 7 | 8 | import java.lang.reflect.Method; 9 | 10 | /** 11 | * Created by Chaojun Wang on 6/9/14. 12 | */ 13 | public class TransparentUtils { 14 | /** 15 | * Convert a translucent themed Activity 16 | * {@link android.R.attr#windowIsTranslucent} to a fullscreen opaque 17 | * Activity. 18 | *

19 | * Call this whenever the background of a translucent Activity has changed 20 | * to become opaque. Doing so will allow the {@link android.view.Surface} of 21 | * the Activity behind to be released. 22 | *

23 | * This call has no effect on non-translucent activities or on activities 24 | * with the {@link android.R.attr#windowIsFloating} attribute. 25 | */ 26 | public static void convertActivityFromTranslucent(Activity activity) { 27 | try { 28 | Method method = Activity.class.getDeclaredMethod("convertFromTranslucent"); 29 | method.setAccessible(true); 30 | method.invoke(activity); 31 | } catch (Throwable t) { 32 | } 33 | } 34 | 35 | /** 36 | * Convert a translucent themed Activity 37 | * {@link android.R.attr#windowIsTranslucent} back from opaque to 38 | * translucent following a call to 39 | * {@link #convertActivityFromTranslucent(Activity)} . 40 | *

41 | * Calling this allows the Activity behind this one to be seen again. Once 42 | * all such Activities have been redrawn 43 | *

44 | * This call has no effect on non-translucent activities or on activities 45 | * with the {@link android.R.attr#windowIsFloating} attribute. 46 | */ 47 | public static void convertActivityToTranslucent(Activity activity) { 48 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 49 | convertActivityToTranslucentAfterL(activity); 50 | } else { 51 | convertActivityToTranslucentBeforeL(activity); 52 | } 53 | } 54 | 55 | /** 56 | * Calling the convertToTranslucent method on platforms before Android 5.0 57 | */ 58 | public static void convertActivityToTranslucentBeforeL(Activity activity) { 59 | try { 60 | Class[] classes = Activity.class.getDeclaredClasses(); 61 | Class translucentConversionListenerClazz = null; 62 | for (Class clazz : classes) { 63 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) { 64 | translucentConversionListenerClazz = clazz; 65 | } 66 | } 67 | Method method = Activity.class.getDeclaredMethod("convertToTranslucent", 68 | translucentConversionListenerClazz); 69 | method.setAccessible(true); 70 | method.invoke(activity, new Object[] { 71 | null 72 | }); 73 | } catch (Throwable t) { 74 | } 75 | } 76 | 77 | /** 78 | * Calling the convertToTranslucent method on platforms after Android 5.0 79 | */ 80 | private static void convertActivityToTranslucentAfterL(Activity activity) { 81 | try { 82 | Method getActivityOptions = Activity.class.getDeclaredMethod("getActivityOptions"); 83 | getActivityOptions.setAccessible(true); 84 | Object options = getActivityOptions.invoke(activity); 85 | 86 | Class[] classes = Activity.class.getDeclaredClasses(); 87 | Class translucentConversionListenerClazz = null; 88 | for (Class clazz : classes) { 89 | if (clazz.getSimpleName().contains("TranslucentConversionListener")) { 90 | translucentConversionListenerClazz = clazz; 91 | } 92 | } 93 | Method convertToTranslucent = Activity.class.getDeclaredMethod("convertToTranslucent", 94 | translucentConversionListenerClazz, ActivityOptions.class); 95 | convertToTranslucent.setAccessible(true); 96 | convertToTranslucent.invoke(activity, null, options); 97 | } catch (Throwable t) { 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/textview/LineMiddleTextView.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.textview; 2 | 3 | import android.content.Context; 4 | import android.graphics.Paint; 5 | import android.util.AttributeSet; 6 | 7 | import androidx.appcompat.widget.AppCompatTextView; 8 | 9 | /** 10 | * Created by lenovo on 2017/7/22. 11 | */ 12 | 13 | public class LineMiddleTextView extends AppCompatTextView { 14 | public LineMiddleTextView(Context context) { 15 | this(context,null); 16 | } 17 | 18 | public LineMiddleTextView(Context context, AttributeSet attrs) { 19 | super(context, attrs); 20 | getPaint().setFlags(Paint. STRIKE_THRU_TEXT_FLAG|Paint.ANTI_ALIAS_FLAG); 21 | setSingleLine(); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/textview/MultiColorTextView.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.textview; 2 | 3 | import android.content.Context; 4 | import android.text.Html; 5 | import android.util.AttributeSet; 6 | 7 | import androidx.appcompat.widget.AppCompatTextView; 8 | 9 | 10 | /** 11 | * Created by lenovo on 2017/8/12. 12 | */ 13 | 14 | public class MultiColorTextView extends AppCompatTextView { 15 | private StringBuilder stringBuilder; 16 | 17 | public MultiColorTextView(Context context) { 18 | this(context, null); 19 | } 20 | 21 | public MultiColorTextView(Context context, AttributeSet attrs) { 22 | super(context, attrs); 23 | stringBuilder = new StringBuilder(); 24 | } 25 | 26 | public MultiColorTextView addText(String text,int color) { 27 | stringBuilder.append(String.format("%s", text)); 28 | return this; 29 | } 30 | 31 | public void setText() { 32 | setText(Html.fromHtml(stringBuilder.toString())); 33 | stringBuilder.delete(0,stringBuilder.length()); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /androidview/src/main/java/com/cy/androidview/textview/SingleLineTextView.java: -------------------------------------------------------------------------------- 1 | package com.cy.androidview.textview; 2 | 3 | import android.content.Context; 4 | import android.util.AttributeSet; 5 | 6 | import androidx.appcompat.widget.AppCompatTextView; 7 | 8 | /** 9 | * Created by lenovo on 2017/8/12. 10 | */ 11 | 12 | public class SingleLineTextView extends AppCompatTextView { 13 | public SingleLineTextView(Context context) { 14 | this(context,null); 15 | } 16 | public SingleLineTextView(Context context, AttributeSet attrs) { 17 | super(context, attrs); 18 | setSingleLine(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /androidview/src/main/res/anim/slide_in_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /androidview/src/main/res/anim/slide_out_right.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | -------------------------------------------------------------------------------- /androidview/src/main/res/drawable-xxhdpi/close_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/androidview/src/main/res/drawable-xxhdpi/close_white.png -------------------------------------------------------------------------------- /androidview/src/main/res/drawable-xxhdpi/copy_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/androidview/src/main/res/drawable-xxhdpi/copy_white.png -------------------------------------------------------------------------------- /androidview/src/main/res/drawable-xxhdpi/eidit_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/androidview/src/main/res/drawable-xxhdpi/eidit_white.png -------------------------------------------------------------------------------- /androidview/src/main/res/drawable-xxhdpi/rotate_3d_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/androidview/src/main/res/drawable-xxhdpi/rotate_3d_white.png -------------------------------------------------------------------------------- /androidview/src/main/res/drawable-xxhdpi/rotate_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/androidview/src/main/res/drawable-xxhdpi/rotate_white.png -------------------------------------------------------------------------------- /androidview/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #eeeeee 4 | 5 | #FF424242 6 | #FFFFFFFF 7 | #03000000 8 | #37000000 9 | 10 | -------------------------------------------------------------------------------- /androidview/src/main/res/values/dimens.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1dp 4 | -------------------------------------------------------------------------------- /androidview/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | AndroidView 3 | 4 | -------------------------------------------------------------------------------- /androidview/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | android { 4 | compileSdkVersion var.compileSdkVersion 5 | buildToolsVersion var.buildToolsVersion 6 | defaultConfig { 7 | applicationId "com.cy.necessaryviewmaster" 8 | minSdkVersion var.minSdkVersion 9 | targetSdkVersion var.targetSdkVersion 10 | versionCode 1 11 | versionName "1.0" 12 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 13 | } 14 | buildTypes { 15 | release { 16 | minifyEnabled false 17 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' 18 | } 19 | } 20 | compileOptions { 21 | sourceCompatibility JavaVersion.VERSION_1_8 22 | targetCompatibility JavaVersion.VERSION_1_8 23 | } 24 | } 25 | dependencies { 26 | implementation fileTree(dir: 'libs', include: ['*.jar']) 27 | implementation 'androidx.appcompat:appcompat:1.1.0' 28 | api project(':androidview') 29 | api "androidx.palette:palette:1.0.0" 30 | } 31 | -------------------------------------------------------------------------------- /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:\AndroidSDK/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 | 14 | 17 | 20 | 23 | 26 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/AnimateActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.os.Bundle; 4 | 5 | import com.cy.androidview.swipe.SwipeActivity; 6 | 7 | public class AnimateActivity extends SwipeActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_animate); 13 | } 14 | 15 | // @Override 16 | // protected void onDestroy() { 17 | // super.onDestroy(); 18 | // overridePendingTransition(0, R.anim.slide_out_right); // 退出动画 19 | // } 20 | } -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/BaseActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.content.Context; 4 | import android.content.Intent; 5 | import android.content.SharedPreferences; 6 | import android.content.pm.PackageManager; 7 | import android.graphics.Color; 8 | import android.os.Build; 9 | import android.os.Bundle; 10 | import android.view.View; 11 | import android.view.Window; 12 | import android.view.WindowManager; 13 | import android.widget.Toast; 14 | 15 | import androidx.annotation.NonNull; 16 | import androidx.annotation.Nullable; 17 | import androidx.appcompat.app.AppCompatActivity; 18 | import androidx.core.app.ActivityCompat; 19 | import androidx.fragment.app.Fragment; 20 | import androidx.fragment.app.FragmentManager; 21 | import androidx.fragment.app.FragmentTransaction; 22 | 23 | 24 | /** 25 | * Created by lenovo on 2017/4/25. 26 | */ 27 | 28 | public abstract class BaseActivity extends AppCompatActivity implements View.OnClickListener { 29 | private String toast_permission; 30 | private OnPermissionHaveListener onPermissionHaveListener; 31 | public SharedPreferences sharedPreferences; 32 | 33 | 34 | public SharedPreferences.Editor editor; 35 | 36 | 37 | public Context context_applicaiton; 38 | 39 | @Override 40 | protected void onCreate(@Nullable Bundle savedInstanceState) { 41 | super.onCreate(savedInstanceState); 42 | 43 | 44 | // setStatusBarTransparent(); 45 | 46 | sharedPreferences = getSharedPreferences("SP", Context.MODE_PRIVATE); 47 | 48 | editor = sharedPreferences.edit(); 49 | 50 | context_applicaiton = getApplicationContext(); 51 | 52 | } 53 | 54 | public Context getContext_applicaiton() { 55 | return context_applicaiton; 56 | } 57 | 58 | public void setContext_applicaiton(Context context_applicaiton) { 59 | this.context_applicaiton = context_applicaiton; 60 | } 61 | 62 | 63 | 64 | 65 | 66 | //?????????????????????????????????????????????????????????????????????? 67 | 68 | /* 69 | Acitivity跳转 70 | */ 71 | public void showToast(String msg) { 72 | Toast.makeText(this, msg, Toast.LENGTH_SHORT).show(); 73 | } 74 | 75 | public void showToast(int string_id) { 76 | Toast.makeText(this, getResources().getString(string_id), Toast.LENGTH_SHORT).show(); 77 | } 78 | 79 | 80 | public void startAppcompatActivity(Class cls) { 81 | startActivity(new Intent(this, cls)); 82 | } 83 | 84 | 85 | public SharedPreferences.Editor getEditor() { 86 | return editor; 87 | } 88 | 89 | public void setEditor(SharedPreferences.Editor editor) { 90 | this.editor = editor; 91 | } 92 | 93 | public SharedPreferences getSharedPreferences() { 94 | return sharedPreferences; 95 | } 96 | 97 | public void setSharedPreferences(SharedPreferences sharedPreferences) { 98 | this.sharedPreferences = sharedPreferences; 99 | } 100 | 101 | 102 | public void initData() { 103 | } 104 | /* 105 | 状态栏全透明去阴影 106 | */ 107 | 108 | public void setStatusBarTransparent() { 109 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 110 | Window window = getWindow(); 111 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 112 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 113 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 114 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 115 | window.setStatusBarColor(Color.TRANSPARENT); 116 | } 117 | } 118 | /* 119 | 状态栏隐藏 120 | */ 121 | 122 | public void setStatusBarHide() { 123 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 124 | Window window = getWindow(); 125 | window.clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); 126 | window.getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN 127 | | View.SYSTEM_UI_FLAG_LAYOUT_STABLE); 128 | window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS); 129 | window.setStatusBarColor(Color.TRANSPARENT); 130 | } 131 | } 132 | /* 133 | 134 | */ 135 | 136 | public void replaceFragment(int framelayout_id, Fragment fragment) { 137 | FragmentManager fragmentManager = getSupportFragmentManager(); 138 | FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction(); 139 | fragmentTransaction.replace(framelayout_id, fragment).commitAllowingStateLoss(); 140 | } 141 | 142 | 143 | public Fragment createFragment(int position) { 144 | return null; 145 | } 146 | 147 | /* 148 | 6.0权限检查 149 | */ 150 | public void checkPermission(String[] permission, String toast_permission, OnPermissionHaveListener onPermissionHaveListener) { 151 | ActivityCompat.requestPermissions(this, permission, 1); 152 | this.toast_permission = toast_permission; 153 | 154 | this.onPermissionHaveListener = onPermissionHaveListener; 155 | 156 | } 157 | 158 | @Override 159 | public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 160 | super.onRequestPermissionsResult(requestCode, permissions, grantResults); 161 | 162 | for (int i = 0; i < permissions.length; i++) { 163 | if (grantResults[i] != PackageManager.PERMISSION_GRANTED) { 164 | 165 | showToast(toast_permission); 166 | return; 167 | } 168 | } 169 | if (onPermissionHaveListener != null) { 170 | onPermissionHaveListener.onPermissionHave(); 171 | } 172 | 173 | 174 | } 175 | 176 | public interface OnPermissionHaveListener { 177 | public void onPermissionHave(); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/CardActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | 7 | public class CardActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_card); 13 | } 14 | } -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/ClickActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | import android.widget.Toast; 6 | 7 | 8 | public class ClickActivity extends com.cy.necessaryviewmaster.BaseActivity { 9 | 10 | @Override 11 | protected void onCreate(Bundle savedInstanceState) { 12 | super.onCreate(savedInstanceState); 13 | setContentView(R.layout.activity_ripple_color_filter); 14 | findViewById(R.id.rpfl).setOnClickListener(this); 15 | findViewById(R.id.rpfl2).setOnClickListener(this); 16 | findViewById(R.id.civ1).setOnClickListener(this); 17 | findViewById(R.id.civ2).setOnClickListener(this); 18 | findViewById(R.id.civ3).setOnClickListener(this); 19 | findViewById(R.id.ivcf1).setOnClickListener(new View.OnClickListener() { 20 | @Override 21 | public void onClick(View v) { 22 | Toast.makeText(ClickActivity.this,"点击",Toast.LENGTH_SHORT).show(); 23 | } 24 | }); 25 | findViewById(R.id.ll).setOnClickListener(new View.OnClickListener() { 26 | @Override 27 | public void onClick(View v) { 28 | Toast.makeText(ClickActivity.this,"点击父view",Toast.LENGTH_SHORT).show(); 29 | } 30 | }); 31 | 32 | } 33 | 34 | @Override 35 | public void onClick(View v) { 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/CornerView.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.content.Context; 4 | import android.graphics.Canvas; 5 | import android.graphics.Color; 6 | import android.graphics.Paint; 7 | import android.graphics.PorterDuff; 8 | import android.graphics.PorterDuffXfermode; 9 | import android.graphics.RectF; 10 | import android.util.AttributeSet; 11 | import android.widget.FrameLayout; 12 | 13 | /** 14 | * Created by cy on 2018/10/23. 15 | */ 16 | 17 | 18 | public class CornerView extends FrameLayout { 19 | 20 | public CornerView(Context context, AttributeSet attrs) { 21 | super(context, attrs); 22 | init(); 23 | } 24 | 25 | public CornerView(Context context) { 26 | super(context); 27 | init(); 28 | } 29 | 30 | private final RectF roundRect = new RectF(); 31 | private float rect_adius = 10; 32 | private final Paint maskPaint = new Paint(); 33 | private final Paint zonePaint = new Paint(); 34 | 35 | private void init() { 36 | maskPaint.setAntiAlias(true); 37 | maskPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); 38 | // 39 | zonePaint.setAntiAlias(true); 40 | zonePaint.setColor(Color.WHITE); 41 | // 42 | float density = getResources().getDisplayMetrics().density; 43 | rect_adius = rect_adius * density; 44 | } 45 | 46 | public void setCorner(float adius) { 47 | rect_adius = adius; 48 | invalidate(); 49 | } 50 | 51 | @Override 52 | protected void onLayout(boolean changed, int left, int top, int right, int bottom) { 53 | super.onLayout(changed, left, top, right, bottom); 54 | int w = getWidth(); 55 | int h = getHeight(); 56 | roundRect.set(0, 0, w, h); 57 | } 58 | 59 | @Override 60 | public void draw(Canvas canvas) { 61 | canvas.saveLayer(roundRect, zonePaint, Canvas.ALL_SAVE_FLAG); 62 | canvas.drawRoundRect(roundRect, rect_adius, rect_adius, zonePaint); 63 | canvas.saveLayer(roundRect, maskPaint, Canvas.ALL_SAVE_FLAG); 64 | super.draw(canvas); 65 | canvas.restore(); 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/LogUtils.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.util.Log; 4 | 5 | /** 6 | * Created by lenovo on 2017/8/20. 7 | */ 8 | 9 | public class LogUtils { 10 | private static boolean DEBUG = true; 11 | 12 | private LogUtils() { 13 | } 14 | 15 | public static synchronized void debug(boolean debug) { 16 | DEBUG = debug; 17 | } 18 | 19 | public static void logI(Object tag, Object content) { 20 | if(DEBUG==false)return; 21 | if (tag == null) tag = "LOG_I"; 22 | Log.i(String.valueOf(tag), "----------------------------------->>>>" + content); 23 | } 24 | public static void logE(Object tag, Object content) { 25 | if(DEBUG==false)return; 26 | if (tag == null) tag = "LOG_E"; 27 | Log.e(String.valueOf(tag), "----------------------------------->>>>" + content); 28 | } 29 | 30 | 31 | public static void logI(Object content) { 32 | logI(null,content); 33 | } 34 | public static void logE(Object content) { 35 | logE(null,content); 36 | } 37 | 38 | public static void log(Object tag, Object content) { 39 | logE(tag,content); 40 | } 41 | public static void log(Object content) { 42 | logE(content); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/MainActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import static androidx.core.util.Preconditions.checkNotNull; 4 | 5 | import android.gesture.Prediction; 6 | import android.graphics.Color; 7 | import android.graphics.Paint; 8 | import android.graphics.Typeface; 9 | import android.os.Bundle; 10 | import android.os.Looper; 11 | import android.text.Spannable; 12 | import android.text.SpannableStringBuilder; 13 | import android.text.style.ForegroundColorSpan; 14 | import android.text.style.RelativeSizeSpan; 15 | import android.text.style.StyleSpan; 16 | import android.view.View; 17 | import android.widget.TextView; 18 | import android.widget.Toast; 19 | 20 | import com.cy.androidview.progress.ProgressWeightView; 21 | 22 | 23 | public class MainActivity extends BaseActivity { 24 | 25 | @Override 26 | protected void onCreate(Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | setContentView(R.layout.activity_main); 29 | findViewById(R.id.btn_click).setOnClickListener(this); 30 | findViewById(R.id.btn_rectangle).setOnClickListener(this); 31 | findViewById(R.id.btn_shape).setOnClickListener(this); 32 | findViewById(R.id.btn_card).setOnClickListener(this); 33 | findViewById(R.id.btn_roundiv).setOnClickListener(this); 34 | findViewById(R.id.btn_selector).setOnClickListener(this); 35 | findViewById(R.id.btn_shadow).setOnClickListener(this); 36 | findViewById(R.id.btn_progress).setOnClickListener(this); 37 | findViewById(R.id.btn_swipe_activity).setOnClickListener(this); 38 | 39 | String str = "各个大哥更"; 40 | for (String s : str.split("")) { 41 | LogUtils.log("String", s); 42 | } 43 | 44 | /** 45 | * flag 参数的作用 46 | * flag 参数是一个整数值,指定如何处理新添加的文本的样式和格式。常见的标志值包括: 47 | * Spannable.SPAN_EXCLUSIVE_EXCLUSIVE: 新文本的样式不包括在原文本中(即,样式只应用于新文本)。 48 | * Spannable.SPAN_EXCLUSIVE_INCLUSIVE: 新文本的样式从其开始位置开始,但不包括原文本的结束位置。 49 | * Spannable.SPAN_INCLUSIVE_EXCLUSIVE: 新文本的样式从原文本的起始位置开始,但不包括新文本的结束位置。 50 | * Spannable.SPAN_INCLUSIVE_INCLUSIVE: 新文本的样式包括原文本的起始和结束位置。 51 | */ 52 | SpannableStringBuilder builder = new SpannableStringBuilder(); 53 | builder.append("Hello, "); 54 | builder.append("colorful", new ForegroundColorSpan(Color.RED), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 55 | builder.append(" and "); 56 | builder.append("size varied", new RelativeSizeSpan(2f), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 57 | builder.append(" text!"); 58 | 59 | TextView tv = findViewById(R.id.tv); 60 | tv.setText(builder); 61 | 62 | 63 | // 添加文本 64 | builder.append("Hello, "); 65 | int start = builder.length(); 66 | builder.append("world!"); 67 | int end = builder.length(); 68 | 69 | // 设置粗体 70 | builder.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 71 | // 设置斜体 72 | builder.setSpan(new StyleSpan(Typeface.ITALIC), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 73 | // 设置文本颜色 74 | builder.setSpan(new ForegroundColorSpan(Color.RED), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 75 | // 设置文本相对大小 76 | builder.setSpan(new RelativeSizeSpan(1.5f), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 77 | // 设置 SpannableStringBuilder 为 TextView 的内容 78 | tv.setText(builder); 79 | 80 | ProgressWeightView progressWeightView = findViewById(R.id.ProgressWeightView); 81 | progressWeightView.setProgress(0.1f); 82 | 83 | } 84 | 85 | @Override 86 | public void onClick(View v) { 87 | 88 | switch (v.getId()) { 89 | case R.id.btn_click: 90 | startAppcompatActivity(ClickActivity.class); 91 | break; 92 | case R.id.btn_rectangle: 93 | startAppcompatActivity(RectangleActivity.class); 94 | break; 95 | case R.id.btn_shape: 96 | startAppcompatActivity(ShapeActivity.class); 97 | break; 98 | case R.id.btn_card: 99 | startAppcompatActivity(CardActivity.class); 100 | break; 101 | case R.id.btn_roundiv: 102 | startAppcompatActivity(RoundedIVActivity.class); 103 | break; 104 | case R.id.btn_selector: 105 | startAppcompatActivity(SelectorActivity.class); 106 | break; 107 | case R.id.btn_shadow: 108 | startAppcompatActivity(ShadowActivity.class); 109 | break; 110 | case R.id.btn_progress: 111 | startAppcompatActivity(ProgressActivity.class); 112 | break; 113 | case R.id.btn_swipe_activity: 114 | startAppcompatActivity(AnimateActivity.class); 115 | // overridePendingTransition(R.anim.slide_in_right, 0); // 进入动画 116 | break; 117 | } 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/ProgressActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.os.Bundle; 6 | import android.view.View; 7 | 8 | import com.cy.androidview.progress.VCutProgressView; 9 | 10 | public class ProgressActivity extends BaseActivity { 11 | 12 | @Override 13 | protected void onCreate(Bundle savedInstanceState) { 14 | super.onCreate(savedInstanceState); 15 | setContentView(R.layout.activity_progress); 16 | VCutProgressView cutProgressView=findViewById(R.id.VCutProgressView); 17 | // cutProgressView.setProgress(70); 18 | } 19 | 20 | @Override 21 | public void onClick(View v) { 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/RectangleActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | 6 | public class RectangleActivity extends BaseActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_rectangle); 12 | 13 | findViewById(R.id.riv).setOnClickListener(this); 14 | findViewById(R.id.rfl).setOnClickListener(this); 15 | } 16 | 17 | @Override 18 | public void onClick(View v) { 19 | 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/RoundedIVActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.os.Bundle; 4 | 5 | import androidx.appcompat.app.AppCompatActivity; 6 | 7 | public class RoundedIVActivity extends AppCompatActivity { 8 | 9 | @Override 10 | protected void onCreate(Bundle savedInstanceState) { 11 | super.onCreate(savedInstanceState); 12 | setContentView(R.layout.activity_round); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/SelectorActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.os.Bundle; 4 | import android.view.View; 5 | 6 | public class SelectorActivity extends BaseActivity { 7 | 8 | @Override 9 | protected void onCreate(Bundle savedInstanceState) { 10 | super.onCreate(savedInstanceState); 11 | setContentView(R.layout.activity_selector); 12 | } 13 | 14 | @Override 15 | public void onClick(View v) { 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/ShadowActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import androidx.appcompat.app.AppCompatActivity; 4 | 5 | import android.graphics.Color; 6 | import android.os.Bundle; 7 | import android.view.View; 8 | import android.widget.CheckBox; 9 | import android.widget.CompoundButton; 10 | 11 | import com.cy.androidview.shadow.ImageViewShadow; 12 | 13 | public class ShadowActivity extends AppCompatActivity { 14 | 15 | @Override 16 | protected void onCreate(Bundle savedInstanceState) { 17 | super.onCreate(savedInstanceState); 18 | setContentView(R.layout.activity_shadow); 19 | ImageViewShadow imageViewShadow =findViewById(R.id.PicShadowView); 20 | 21 | ImageViewShadow imageViewShadow2 =findViewById(R.id.PicShadowView2); 22 | CheckBox cb_colorFilter=findViewById(R.id.cb_colorFilter); 23 | cb_colorFilter.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { 24 | @Override 25 | public void onCheckedChanged(CompoundButton compoundButton, boolean b) { 26 | imageViewShadow.setColorFilter(b?Color.RED:-1); 27 | } 28 | }); 29 | findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { 30 | @Override 31 | public void onClick(View view) { 32 | imageViewShadow2.setImageResource(R.drawable.cb_zuji_normal); 33 | } 34 | }); 35 | 36 | } 37 | } -------------------------------------------------------------------------------- /app/src/main/java/com/cy/necessaryviewmaster/ShapeActivity.java: -------------------------------------------------------------------------------- 1 | package com.cy.necessaryviewmaster; 2 | 3 | import android.graphics.Shader; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | 7 | import com.cy.androidview.shapeview.TextViewShape; 8 | 9 | public class ShapeActivity extends BaseActivity { 10 | 11 | @Override 12 | protected void onCreate(Bundle savedInstanceState) { 13 | super.onCreate(savedInstanceState); 14 | setContentView(R.layout.activity_shape); 15 | 16 | findViewById(R.id.rsf).setOnClickListener(this); 17 | TextViewShape tv_gradient = findViewById(R.id.TextViewShape); 18 | tv_gradient.getShapeBackground().setGradientColors( 19 | new int[]{0xffff0000, 0xffffff00, 0xff00ff00, 0xff00ffff, 0xff0000ff, 0xffff00ff}).shape(); 20 | } 21 | 22 | @Override 23 | public void onClick(View v) { 24 | 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/after_sale_icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/after_sale_icon.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/back.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/cb_zuji_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/cb_zuji_normal.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/cb_zuji_selected.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/cb_zuji_selected.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/flash_aotu_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/flash_aotu_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/flash_on_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/flash_on_white.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/hg.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/hg.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/home_paihang_renqi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/home_paihang_renqi.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/mn.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/mn.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pic_big.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/pic_big.jpg -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/pic_edit_filter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/pic_edit_filter.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/search.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/search.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/search_home.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/search_home.png -------------------------------------------------------------------------------- /app/src/main/res/drawable-xhdpi/yuanxiangji_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnJiaoDe/AndroidView/d03a9dff7d0be01d9ab1d8c93b9a15d47cf2522d/app/src/main/res/drawable-xhdpi/yuanxiangji_white.png -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_animate.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 15 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_card.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 15 | 16 | 22 | 23 | 29 | 30 | 31 | 37 | 38 | 42 | 43 | 48 | 49 | 50 | 54 | 55 | 56 | 66 | 67 | 77 | 78 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 |