├── .gitignore
├── .idea
├── compiler.xml
├── copyright
│ └── profiles_settings.xml
├── encodings.xml
├── gradle.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── markdown-navigator.xml
├── markdown-navigator
│ └── profiles_settings.xml
├── misc.xml
└── vcs.xml
├── README.md
├── animation_button.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── allen
│ │ └── androidcustomview
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── allen
│ │ │ └── androidcustomview
│ │ │ ├── activity
│ │ │ ├── AliPayHomeActivity.java
│ │ │ ├── AnimationBtnActivity.java
│ │ │ ├── AnimationViewActivity.java
│ │ │ ├── BannerActivity.java
│ │ │ ├── BubbleViewActivity.java
│ │ │ ├── ClearScreenActivity.kt
│ │ │ ├── DragBallActivity.java
│ │ │ ├── FingerprintActivity.java
│ │ │ ├── HoverItemActivity.java
│ │ │ ├── MainActivity.kt
│ │ │ ├── PathActivity.kt
│ │ │ ├── PayPsdViewActivity.java
│ │ │ ├── ProgressBarActivity.java
│ │ │ ├── RadarActivity.java
│ │ │ ├── RecyclerViewItemAnimActivity.kt
│ │ │ ├── RevealAnimationActivity.java
│ │ │ ├── SinaVoteActivity.kt
│ │ │ ├── WaveByBezierActivity.java
│ │ │ └── WaveBySinCosActivity.java
│ │ │ ├── adapter
│ │ │ ├── HoverAdapter.java
│ │ │ ├── ItemAnimAdapter.kt
│ │ │ └── MainAdapter.java
│ │ │ ├── anim
│ │ │ ├── BaseItemAnimation.java
│ │ │ ├── RotateXItemAnimation.kt
│ │ │ ├── RotateYItemAnimation.kt
│ │ │ ├── ScaleItemAnimation.kt
│ │ │ ├── SlideItemAnimation.kt
│ │ │ └── SuperItemAnimation.kt
│ │ │ ├── bean
│ │ │ ├── CircleBean.java
│ │ │ ├── TypeBean.java
│ │ │ ├── UserBean.java
│ │ │ ├── VoteBean.kt
│ │ │ └── WaveBean.java
│ │ │ ├── data
│ │ │ └── VoteData.kt
│ │ │ ├── helper
│ │ │ └── DragViewHelper.kt
│ │ │ ├── listener
│ │ │ └── OnDragTouchListener.kt
│ │ │ ├── tagview
│ │ │ ├── TagActivity.java
│ │ │ ├── TagAdapter.java
│ │ │ ├── TagBean.java
│ │ │ └── recyclerview.md
│ │ │ ├── utils
│ │ │ ├── BezierUtil.java
│ │ │ ├── CharacterParser.java
│ │ │ ├── DisplayUtils.java
│ │ │ ├── FingerprintUtil.java
│ │ │ └── PinyinComparator.java
│ │ │ └── widget
│ │ │ ├── AnimationButton.java
│ │ │ ├── ArcView.kt
│ │ │ ├── BaseView.java
│ │ │ ├── BubbleView.java
│ │ │ ├── CarMoveView.kt
│ │ │ ├── CircleProgressBarView.java
│ │ │ ├── ClearScreenView.kt
│ │ │ ├── DividerItemDecoration.java
│ │ │ ├── DragBallView.java
│ │ │ ├── FadeInTextView.java
│ │ │ ├── HorizontalProgressBar.java
│ │ │ ├── HoverItemDecoration.java
│ │ │ ├── IndexView.java
│ │ │ ├── IndicatorView.java
│ │ │ ├── LoadingButton.java
│ │ │ ├── LoadingLineView.java
│ │ │ ├── LoadingView.java
│ │ │ ├── PayPsdInputView.java
│ │ │ ├── ProductProgressBar.java
│ │ │ ├── RadarWaveView.java
│ │ │ ├── StudyPlanProgressView.kt
│ │ │ ├── SuperDividerItemDecoration.java
│ │ │ ├── WaveViewByBezier.java
│ │ │ ├── WaveViewBySinCos.java
│ │ │ ├── banner
│ │ │ ├── BannerView.java
│ │ │ ├── PagerOptions.java
│ │ │ ├── adapter
│ │ │ │ └── BannerViewPagerAdapter.java
│ │ │ ├── holder
│ │ │ │ ├── BannerViewHolder.java
│ │ │ │ └── BannerViewHolderCreator.java
│ │ │ └── listener
│ │ │ │ ├── OnPageChangeListener.java
│ │ │ │ └── OnPageClickListener.java
│ │ │ ├── status
│ │ │ ├── StatusBuilder.kt
│ │ │ ├── StatusLayout.kt
│ │ │ └── StatusManager.kt
│ │ │ └── vote
│ │ │ ├── VoteContainerView.kt
│ │ │ ├── VoteLayoutAdapter.kt
│ │ │ └── VoteView.kt
│ └── res
│ │ ├── drawable
│ │ ├── background_gradual_assarts.xml
│ │ ├── shape_bg_clickable.xml
│ │ ├── shape_bg_un_clickable.xml
│ │ ├── shape_circle_bg.xml
│ │ ├── shape_item_bg.xml
│ │ ├── shape_search.xml
│ │ ├── shape_vote_item_bg.xml
│ │ ├── tag_bg_selector.xml
│ │ ├── tag_checked_bg.xml
│ │ ├── tag_normal_bg.xml
│ │ └── tag_text_selector.xml
│ │ ├── layout
│ │ ├── activity_alipay_home.xml
│ │ ├── activity_animation_btn.xml
│ │ ├── activity_animation_view.xml
│ │ ├── activity_banner.xml
│ │ ├── activity_bubble_view.xml
│ │ ├── activity_clear_screen.xml
│ │ ├── activity_drag_ball.xml
│ │ ├── activity_finger_print.xml
│ │ ├── activity_hover_item.xml
│ │ ├── activity_main.xml
│ │ ├── activity_path.xml
│ │ ├── activity_pay_psd_view.xml
│ │ ├── activity_pregress_bar.xml
│ │ ├── activity_radar.xml
│ │ ├── activity_recycler_view_item_anim.xml
│ │ ├── activity_reveal_animation.xml
│ │ ├── activity_sina_vote.xml
│ │ ├── activity_tag.xml
│ │ ├── activity_wave_by_bezier.xml
│ │ ├── activity_wave_by_sin_cos.xml
│ │ ├── activity_webview.xml
│ │ ├── adapter_item_hover_user.xml
│ │ ├── adapter_item_main.xml
│ │ ├── banner_item.xml
│ │ ├── banner_view_layout.xml
│ │ ├── include_default_layout.xml
│ │ ├── include_toolbar_close.xml
│ │ ├── include_toolbar_open.xml
│ │ ├── item_danmu_layout.xml
│ │ ├── tag_layout.xml
│ │ └── widget_vote_layout.xml
│ │ ├── mipmap-hdpi
│ │ └── ic_launcher.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ ├── icon_study_progress_completed.png
│ │ └── icon_study_progress_not_check.png
│ │ ├── mipmap-xhdpi
│ │ ├── beijing2x.jpg
│ │ ├── ic_launcher.png
│ │ └── start_logo_group.png
│ │ ├── mipmap-xxhdpi
│ │ ├── alipay_home_bg.jpg
│ │ ├── app_download.png
│ │ ├── banner_point_disabled.png
│ │ ├── banner_point_enabled.png
│ │ ├── car.png
│ │ ├── ic_add.png
│ │ ├── ic_camera_3x.png
│ │ ├── ic_card.png
│ │ ├── ic_contact.png
│ │ ├── ic_launcher.png
│ │ ├── ic_payment.png
│ │ ├── ic_scan.png
│ │ ├── ic_search.png
│ │ ├── ic_transfer.png
│ │ ├── icon_img1.png
│ │ ├── icon_img2.jpg
│ │ ├── icon_vote_check.png
│ │ ├── icon_vote_unchecked.png
│ │ ├── live_bg.jpeg
│ │ └── progress_tip_icon.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── beijing.jpg
│ │ └── ic_launcher.png
│ │ ├── values-w820dp
│ │ └── dimens.xml
│ │ └── values
│ │ ├── attrs.xml
│ │ ├── colors.xml
│ │ ├── dimens.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── allen
│ └── androidcustomview
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── pay_psd_input_view.md
├── progress.md
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | .DS_Store
5 | /build
6 | .idea
7 | /captures
8 | .externalNativeBuild
9 |
--------------------------------------------------------------------------------
/.idea/compiler.xml:
--------------------------------------------------------------------------------
1 |
2 |
9 |
20 |
25 |
35 |
4 |
5 | 或者手动加QQ群:688433795
6 |
7 | ## Demo示例下载
8 | [点击下载demo体验](http://d.firim.top/whez)
9 |
10 | # [**炫酷的提交按钮**](https://github.com/lygttpod/AndroidCustomView/blob/master/animation_button.md)
11 | 
12 |
13 |
14 | # [**仿微信支付宝等风格的支付密码输入框的实现**](https://github.com/lygttpod/AndroidCustomView/blob/master/pay_psd_input_view.md)
15 | 
16 |
17 | # [**炫酷的进度条**](https://github.com/lygttpod/AndroidCustomView/blob/master/progress.md)
18 | 
19 |
20 | # [**TextView实现打印机逐个显示的效果**](http://www.jianshu.com/p/4d987769785c)
21 | 
22 |
23 | # [**水波动画效果多种实现方式详解**](http://www.jianshu.com/p/0cd1c1d47f4a)
24 | 
25 |
26 | # [**仿QQ未读消息拖拽效果详解**](http://www.jianshu.com/p/ed2721286778)
27 | 
28 |
29 | # [**炫酷的欢迎页**]
30 | 
31 |
32 | # [**进度条**]
33 | 
34 |
35 | # [**一行代码实现吸顶悬停效果**]
36 | 
37 |
38 |
39 | # [**支付宝首页效果**]
40 | 
41 |
42 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 | apply plugin: 'kotlin-android'
3 |
4 | apply plugin: 'kotlin-android-extensions'
5 |
6 | android {
7 | compileSdkVersion 27
8 | defaultConfig {
9 | applicationId "com.allen.androidcustomview"
10 | targetSdkVersion 27
11 | minSdkVersion 17
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 | productFlavors {
23 | }
24 | }
25 |
26 | dependencies {
27 | implementation fileTree(include: ['*.jar'], dir: 'libs')
28 | androidTestImplementation('com.android.support.test.espresso:espresso-core:2.2.2', {
29 | exclude group: 'com.android.support', module: 'support-annotations'
30 | })
31 | implementation"org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
32 | implementation 'com.android.support:appcompat-v7:27.1.1'
33 | implementation 'com.android.support:design:27.1.1'
34 | implementation 'com.android.support:recyclerview-v7:27.1.1'
35 | testImplementation 'junit:junit:4.12'
36 | implementation 'com.github.CymChad:BaseRecyclerViewAdapterHelper:2.9.40'
37 | }
38 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in D:\Android\sdk/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/allen/androidcustomview/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview;
2 |
3 | import android.content.Context;
4 | import android.support.test.InstrumentationRegistry;
5 | import android.support.test.runner.AndroidJUnit4;
6 |
7 | import org.junit.Test;
8 | import org.junit.runner.RunWith;
9 |
10 | import static org.junit.Assert.*;
11 |
12 | /**
13 | * Instrumentation test, which will execute on an Android device.
14 | *
15 | * @see Testing documentation
16 | */
17 | @RunWith(AndroidJUnit4.class)
18 | public class ExampleInstrumentedTest {
19 | @Test
20 | public void useAppContext() throws Exception {
21 | // Context of the app under test.
22 | Context appContext = InstrumentationRegistry.getTargetContext();
23 |
24 | assertEquals("com.allen.androidcustomview", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
14 | * @author : Allen 15 | * date : 2018/09/30 16 | * desc : 支付宝首页 来源 https://mp.weixin.qq.com/s/GegMt7GDBCFVoUgFQWG3Sw 17 | * version : 1.0 18 | *19 | */ 20 | public class AliPayHomeActivity extends AppCompatActivity implements AppBarLayout.OnOffsetChangedListener { 21 | 22 | 23 | private AppBarLayout mAppBarLayout; 24 | private View mToolbarOpenBgView; 25 | private View mToolbarCloseBgView; 26 | private View mToolbarOpenLayout; 27 | private View mToolbarCloseLayout; 28 | private View contentBgView; 29 | @Override 30 | protected void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | 33 | setContentView(R.layout.activity_alipay_home); 34 | initView(); 35 | mAppBarLayout.addOnOffsetChangedListener(this); 36 | } 37 | 38 | private void initView() { 39 | 40 | mToolbarOpenBgView = findViewById(R.id.toolbar_open_bg_view); 41 | mToolbarOpenLayout = findViewById(R.id.include_toolbar_open); 42 | 43 | mToolbarCloseBgView = findViewById(R.id.bg_toolbar_close); 44 | mToolbarCloseLayout = findViewById(R.id.include_toolbar_close); 45 | contentBgView = findViewById(R.id.content_bg_view); 46 | 47 | mAppBarLayout = findViewById(R.id.app_bar_layout); 48 | } 49 | 50 | @Override 51 | public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { 52 | 53 | //垂直方向偏移量 54 | int offset = Math.abs(verticalOffset); 55 | //最大偏移距离 56 | int scrollRange = appBarLayout.getTotalScrollRange(); 57 | if (offset <= scrollRange / 2) {//当滑动没超过一半,展开状态下toolbar显示内容,根据收缩位置,改变透明值 58 | mToolbarOpenLayout.setVisibility(View.VISIBLE); 59 | mToolbarCloseLayout.setVisibility(View.GONE); 60 | //根据偏移百分比 计算透明值 61 | float scale2 = (float) offset / (scrollRange / 2); 62 | int alpha2 = (int) (255 * scale2); 63 | mToolbarOpenBgView.setBackgroundColor(Color.argb(alpha2, 25, 131, 209)); 64 | } else {//当滑动超过一半,收缩状态下toolbar显示内容,根据收缩位置,改变透明值 65 | mToolbarOpenLayout.setVisibility(View.GONE); 66 | mToolbarCloseLayout.setVisibility(View.VISIBLE); 67 | float scale3 = (float) (scrollRange - offset) / (scrollRange / 2); 68 | int alpha3 = (int) (255 * scale3); 69 | mToolbarCloseBgView.setBackgroundColor(Color.argb(alpha3, 25, 131, 209)); 70 | } 71 | //根据偏移百分比计算扫一扫布局的透明度值 72 | float scale = (float) offset / scrollRange; 73 | int alpha = (int) (255 * scale); 74 | contentBgView.setBackgroundColor(Color.argb(alpha, 25, 131, 209)); 75 | } 76 | 77 | @Override 78 | protected void onDestroy() { 79 | super.onDestroy(); 80 | mAppBarLayout.removeOnOffsetChangedListener(this); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/AnimationBtnActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.widget.Toast; 6 | 7 | import com.allen.androidcustomview.R; 8 | import com.allen.androidcustomview.widget.AnimationButton; 9 | 10 | public class AnimationBtnActivity extends AppCompatActivity { 11 | 12 | private AnimationButton animationButton; 13 | 14 | @Override 15 | protected void onCreate(Bundle savedInstanceState) { 16 | super.onCreate(savedInstanceState); 17 | setContentView(R.layout.activity_animation_btn); 18 | animationButton = (AnimationButton) findViewById(R.id.animation_btn); 19 | animationButton.setAnimationButtonListener(new AnimationButton.AnimationButtonListener() { 20 | @Override 21 | public void onClickListener() { 22 | animationButton.start(); 23 | } 24 | 25 | @Override 26 | public void animationFinish() { 27 | Toast.makeText(AnimationBtnActivity.this,"动画执行完毕",Toast.LENGTH_SHORT).show(); 28 | // finish(); 29 | animationButton.reset(); 30 | } 31 | }); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/AnimationViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.view.View; 6 | import android.widget.Toast; 7 | 8 | import com.allen.androidcustomview.R; 9 | import com.allen.androidcustomview.widget.FadeInTextView; 10 | import com.allen.androidcustomview.widget.LoadingButton; 11 | 12 | public class AnimationViewActivity extends AppCompatActivity { 13 | 14 | private FadeInTextView fadeInTextView; 15 | private LoadingButton loadingButton; 16 | 17 | @Override 18 | protected void onCreate(Bundle savedInstanceState) { 19 | super.onCreate(savedInstanceState); 20 | setContentView(R.layout.activity_animation_view); 21 | 22 | fadeInTextView = (FadeInTextView) findViewById(R.id.fade_in_tv); 23 | loadingButton = (LoadingButton) findViewById(R.id.loading_btn); 24 | 25 | fadeInTextView 26 | .setTextString("自定义view实现字符串逐字显示,后边的文字是为了测试换行是否正常显示!") 27 | .setTextAnimationListener(new FadeInTextView.TextAnimationListener() { 28 | @Override 29 | public void animationFinish() { 30 | loadingButton.stopLoading(); 31 | } 32 | }); 33 | 34 | loadingButton.setOnClickListener(new View.OnClickListener() { 35 | @Override 36 | public void onClick(View v) { 37 | loadingButton.startLoading(); 38 | fadeInTextView.startFadeInAnimation(); 39 | } 40 | }); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/BannerActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.content.Context; 4 | import android.graphics.Color; 5 | import android.os.Bundle; 6 | import android.support.annotation.Nullable; 7 | import android.support.v4.view.ViewPager; 8 | import android.support.v7.app.AppCompatActivity; 9 | import android.view.LayoutInflater; 10 | import android.view.View; 11 | import android.widget.ImageView; 12 | import android.widget.Toast; 13 | 14 | import com.allen.androidcustomview.R; 15 | import com.allen.androidcustomview.widget.banner.BannerView; 16 | import com.allen.androidcustomview.widget.banner.listener.OnPageChangeListener; 17 | import com.allen.androidcustomview.widget.banner.listener.OnPageClickListener; 18 | import com.allen.androidcustomview.widget.banner.PagerOptions; 19 | import com.allen.androidcustomview.widget.banner.holder.BannerViewHolder; 20 | import com.allen.androidcustomview.widget.banner.holder.BannerViewHolderCreator; 21 | 22 | import java.util.ArrayList; 23 | import java.util.List; 24 | 25 | /** 26 | *
27 | * @author : xiaoyao 28 | * e-mail : xiaoyao@51vest.com 29 | * date : 2018/03/09 30 | * desc : 31 | * version : 1.0 32 | *33 | */ 34 | 35 | public class BannerActivity extends AppCompatActivity { 36 | 37 | private BannerView bannerView; 38 | private List
13 | * author : Allen 14 | * date : 2021/1/28 15 | * desc : 16 | *17 | */ 18 | class ClearScreenActivity : AppCompatActivity(), ClearScreenView.OnClearScreenListener { 19 | 20 | override fun onCreate(savedInstanceState: Bundle?) { 21 | super.onCreate(savedInstanceState) 22 | setContentView(R.layout.activity_clear_screen) 23 | 24 | clear_screen_container.addClearView(iv_clear_content) 25 | 26 | clear_screen_container.setOnClearScreenListener(this) 27 | 28 | btn_quick_clear.setOnClickListener { clear_screen_container.clearScreenMode = ClearScreenMode.QUICK_SCROLL } 29 | btn_slow_clear.setOnClickListener { clear_screen_container.clearScreenMode = ClearScreenMode.SLOW_SCROLL } 30 | } 31 | 32 | override fun onCleared() { 33 | Toast.makeText(this, "清屏了", Toast.LENGTH_SHORT).show() 34 | } 35 | 36 | override fun onRestored() { 37 | Toast.makeText(this, "恢复了", Toast.LENGTH_SHORT).show() 38 | } 39 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/DragBallActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.text.TextUtils; 7 | import android.view.View; 8 | import android.widget.Button; 9 | import android.widget.EditText; 10 | import android.widget.Toast; 11 | 12 | import com.allen.androidcustomview.R; 13 | import com.allen.androidcustomview.widget.DragBallView; 14 | 15 | 16 | public class DragBallActivity extends AppCompatActivity { 17 | 18 | 19 | private Button resetBtn, msgCountBtn; 20 | private DragBallView dragBallView; 21 | private EditText msgCountEt; 22 | 23 | @Override 24 | protected void onCreate(@Nullable Bundle savedInstanceState) { 25 | super.onCreate(savedInstanceState); 26 | setContentView(R.layout.activity_drag_ball); 27 | resetBtn = (Button) findViewById(R.id.reset_btn); 28 | msgCountBtn = (Button) findViewById(R.id.msg_count_btn); 29 | dragBallView = (DragBallView) findViewById(R.id.drag_ball_view); 30 | 31 | msgCountEt = (EditText) findViewById(R.id.msg_count_et); 32 | 33 | resetBtn.setOnClickListener(new View.OnClickListener() { 34 | @Override 35 | public void onClick(View v) { 36 | dragBallView.reset(); 37 | } 38 | }); 39 | 40 | msgCountBtn.setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | if (!TextUtils.isEmpty(msgCountEt.getText().toString().trim())) { 44 | int count = Integer.valueOf(msgCountEt.getText().toString().trim()); 45 | dragBallView.setMsgCount(count); 46 | } 47 | } 48 | }); 49 | 50 | dragBallView.setOnDragBallListener(new DragBallView.OnDragBallListener() { 51 | @Override 52 | public void onDisappear() { 53 | Toast.makeText(DragBallActivity.this, "消失了", Toast.LENGTH_SHORT).show(); 54 | } 55 | }); 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/FingerprintActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v4.hardware.fingerprint.FingerprintManagerCompat; 6 | import android.support.v7.app.AppCompatActivity; 7 | import android.util.Log; 8 | import android.view.View; 9 | import android.widget.TextView; 10 | import android.widget.Toast; 11 | 12 | import com.allen.androidcustomview.R; 13 | import com.allen.androidcustomview.utils.FingerprintUtil; 14 | 15 | /** 16 | * Created by xiaoyao on 2017/9/14. 17 | */ 18 | 19 | public class FingerprintActivity extends AppCompatActivity { 20 | 21 | private static final String TAG = "allen"; 22 | 23 | 24 | TextView resultTv; 25 | @Override 26 | protected void onCreate(@Nullable Bundle savedInstanceState) { 27 | super.onCreate(savedInstanceState); 28 | 29 | setContentView(R.layout.activity_finger_print); 30 | 31 | resultTv = (TextView) findViewById(R.id.result_tv); 32 | findViewById(R.id.open_finger_btn).setOnClickListener(new View.OnClickListener() { 33 | @Override 34 | public void onClick(View v) { 35 | openFinger(); 36 | } 37 | }); 38 | 39 | 40 | findViewById(R.id.cancel_finger_btn).setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | FingerprintUtil.cancel(); 44 | } 45 | }); 46 | 47 | 48 | } 49 | 50 | private void openFinger() { 51 | 52 | FingerprintUtil.callFingerPrint(this, new FingerprintUtil.OnCallBackListener() { 53 | @Override 54 | public void onSupportFailed() { 55 | Toast.makeText(FingerprintActivity.this, "当前设备不支持指纹", Toast.LENGTH_LONG).show(); 56 | Log.e(TAG, "当前设备不支持指纹"); 57 | } 58 | 59 | @Override 60 | public void onInsecurity() { 61 | Toast.makeText(FingerprintActivity.this, "当前设备未处于安全保护中", Toast.LENGTH_LONG).show(); 62 | Log.e(TAG, "当前设备未处于安全保护中"); 63 | } 64 | 65 | @Override 66 | public void onEnrollFailed() { 67 | Toast.makeText(FingerprintActivity.this, "请到设置中设置指纹", Toast.LENGTH_LONG).show(); 68 | Log.e(TAG, "请到设置中设置指纹"); 69 | } 70 | 71 | @Override 72 | public void onAuthenticationStart() { 73 | Toast.makeText(FingerprintActivity.this, "验证开始", Toast.LENGTH_LONG).show(); 74 | 75 | Log.e(TAG, "onAuthenticationStart: "); 76 | } 77 | 78 | @Override 79 | public void onAuthenticationError(int errMsgId, CharSequence errString) { 80 | Toast.makeText(FingerprintActivity.this, errString, Toast.LENGTH_LONG).show(); 81 | Log.e(TAG, "onAuthenticationError: "); 82 | } 83 | 84 | @Override 85 | public void onAuthenticationFailed() { 86 | Toast.makeText(FingerprintActivity.this, "解锁失败", Toast.LENGTH_LONG).show(); 87 | 88 | Log.e(TAG, "解锁失败"); 89 | } 90 | 91 | @Override 92 | public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { 93 | Toast.makeText(FingerprintActivity.this, helpString, Toast.LENGTH_LONG).show(); 94 | 95 | Log.e(TAG, "onAuthenticationHelp: "); 96 | } 97 | 98 | @Override 99 | public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) { 100 | Toast.makeText(FingerprintActivity.this, "解锁成功", Toast.LENGTH_LONG).show(); 101 | Log.e(TAG, "解锁成功"); 102 | resultTv.setText(result.getClass().getName()); 103 | } 104 | }); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/HoverItemActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.os.Bundle; 4 | import android.support.annotation.Nullable; 5 | import android.support.v7.app.AppCompatActivity; 6 | import android.support.v7.widget.LinearLayoutManager; 7 | import android.support.v7.widget.RecyclerView; 8 | import android.widget.TextView; 9 | 10 | import com.allen.androidcustomview.R; 11 | import com.allen.androidcustomview.adapter.HoverAdapter; 12 | import com.allen.androidcustomview.bean.UserBean; 13 | import com.allen.androidcustomview.utils.CharacterParser; 14 | import com.allen.androidcustomview.utils.PinyinComparator; 15 | import com.allen.androidcustomview.widget.HoverItemDecoration; 16 | import com.allen.androidcustomview.widget.IndexView; 17 | 18 | import java.util.ArrayList; 19 | import java.util.Collections; 20 | import java.util.List; 21 | 22 | /** 23 | *
24 | * @author : xiaoyao 25 | * e-mail : xiaoyao@51vest.com 26 | * date : 2018/04/16 27 | * desc : 28 | * version : 1.0 29 | *30 | */ 31 | 32 | public class HoverItemActivity extends AppCompatActivity { 33 | private RecyclerView recyclerView; 34 | private IndexView indexView; 35 | private TextView showTextDialog; 36 | 37 | private HoverAdapter adapter; 38 | 39 | private List
10 | * @author : Allen 11 | * date : 2019/07/23 12 | * desc : 13 | *14 | */ 15 | class PathActivity : AppCompatActivity() { 16 | 17 | override fun onCreate(savedInstanceState: Bundle?) { 18 | super.onCreate(savedInstanceState) 19 | setContentView(R.layout.activity_path) 20 | start_btn.setOnClickListener { 21 | car_anim_view.startAnim() 22 | } 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/PayPsdViewActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.widget.Toast; 6 | 7 | import com.allen.androidcustomview.R; 8 | import com.allen.androidcustomview.widget.PayPsdInputView; 9 | 10 | public class PayPsdViewActivity extends AppCompatActivity { 11 | private PayPsdInputView passwordInputView; 12 | 13 | @Override 14 | protected void onCreate(Bundle savedInstanceState) { 15 | super.onCreate(savedInstanceState); 16 | setContentView(R.layout.activity_pay_psd_view); 17 | 18 | passwordInputView = (PayPsdInputView) findViewById(R.id.password); 19 | 20 | passwordInputView.setComparePassword( new PayPsdInputView.onPasswordListener() { 21 | 22 | @Override 23 | public void onDifference(String oldPsd, String newPsd) { 24 | // TODO: 2018/1/22 和上次输入的密码不一致 做相应的业务逻辑处理 25 | Toast.makeText(PayPsdViewActivity.this, "两次密码输入不同" + oldPsd + "!=" + newPsd, Toast.LENGTH_SHORT).show(); 26 | passwordInputView.cleanPsd(); 27 | } 28 | 29 | @Override 30 | public void onEqual(String psd) { 31 | // TODO: 2017/5/7 两次输入密码相同,那就去进行支付楼 32 | Toast.makeText(PayPsdViewActivity.this, "密码相同" + psd, Toast.LENGTH_SHORT).show(); 33 | passwordInputView.setComparePassword(""); 34 | passwordInputView.cleanPsd(); 35 | } 36 | 37 | @Override 38 | public void inputFinished(String inputPsd) { 39 | // TODO: 2018/1/3 输完逻辑 40 | Toast.makeText(PayPsdViewActivity.this, "输入完毕:" + inputPsd, Toast.LENGTH_SHORT).show(); 41 | passwordInputView.setComparePassword(inputPsd); 42 | } 43 | }); 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/ProgressBarActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.util.Log; 6 | import android.view.View; 7 | import android.widget.Button; 8 | import android.widget.TextView; 9 | 10 | import com.allen.androidcustomview.R; 11 | import com.allen.androidcustomview.widget.CircleProgressBarView; 12 | import com.allen.androidcustomview.widget.HorizontalProgressBar; 13 | import com.allen.androidcustomview.widget.LoadingLineView; 14 | import com.allen.androidcustomview.widget.LoadingView; 15 | import com.allen.androidcustomview.widget.ProductProgressBar; 16 | import com.allen.androidcustomview.widget.StudyPlanProgressView; 17 | 18 | import java.util.ArrayList; 19 | import java.util.List; 20 | 21 | public class ProgressBarActivity extends AppCompatActivity { 22 | 23 | CircleProgressBarView circleProgressBarView; 24 | HorizontalProgressBar horizontalProgressBar; 25 | ProductProgressBar productProgressBar; 26 | LoadingView loadingView; 27 | TextView textView; 28 | LoadingLineView loadingLineView; 29 | 30 | Button button; 31 | StudyPlanProgressView studyPlanProgressView; 32 | 33 | @Override 34 | protected void onCreate(Bundle savedInstanceState) { 35 | super.onCreate(savedInstanceState); 36 | setContentView(R.layout.activity_pregress_bar); 37 | 38 | circleProgressBarView = (CircleProgressBarView) findViewById(R.id.circle_progress_view); 39 | 40 | horizontalProgressBar = (HorizontalProgressBar) findViewById(R.id.horizontal_progress_view); 41 | productProgressBar = (ProductProgressBar) findViewById(R.id.product_progress_view); 42 | loadingView = (LoadingView) findViewById(R.id.loading_view); 43 | loadingLineView = (LoadingLineView) findViewById(R.id.loading_line_view); 44 | 45 | textView = (TextView) findViewById(R.id.progress_tv); 46 | button = (Button) findViewById(R.id.startAnimationBtn); 47 | studyPlanProgressView = findViewById(R.id.study_plan_progress_view); 48 | 49 | circleProgressBarView.setProgressWithAnimation(60); 50 | circleProgressBarView.setProgressListener(new CircleProgressBarView.ProgressListener() { 51 | @Override 52 | public void currentProgressListener(float currentProgress) { 53 | textView.setText("当前进度:" + currentProgress); 54 | } 55 | }); 56 | circleProgressBarView.startProgressAnimation(); 57 | 58 | horizontalProgressBar.setProgressWithAnimation(60).setProgressListener(new HorizontalProgressBar.ProgressListener() { 59 | @Override 60 | public void currentProgressListener(float currentProgress) { 61 | } 62 | }); 63 | horizontalProgressBar.startProgressAnimation(); 64 | 65 | productProgressBar.setProgress(60).setProgressListener(new ProductProgressBar.ProgressListener() { 66 | @Override 67 | public void currentProgressListener(float currentProgress) { 68 | Log.e("allen", "currentProgressListener: " + currentProgress); 69 | } 70 | }); 71 | 72 | loadingView.startAnimation(); 73 | 74 | button.setOnClickListener(new View.OnClickListener() { 75 | @Override 76 | public void onClick(View v) { 77 | loadingLineView.startLoading(); 78 | loadingView.startAnimation(); 79 | horizontalProgressBar.setProgressWithAnimation(100); 80 | productProgressBar.setProgress(100); 81 | circleProgressBarView.setProgressWithAnimation(60).startProgressAnimation(); 82 | circleProgressBarView.setProgressListener(new CircleProgressBarView.ProgressListener() { 83 | @Override 84 | public void currentProgressListener(float currentProgress) { 85 | textView.setText("当前进度:" + currentProgress); 86 | } 87 | }); 88 | studyPlanProgressView.setData(getPlanData(true)); 89 | } 90 | }); 91 | studyPlanProgressView.setData(getPlanData(false)); 92 | 93 | } 94 | 95 | private List
19 | * @author : Allen 20 | * e-mail : lygttpod@163.com 21 | * date : 2019/05/11 22 | * desc : 23 | *24 | */ 25 | class RecyclerViewItemAnimActivity : AppCompatActivity() { 26 | 27 | var adapter: ItemAnimAdapter? = null 28 | 29 | override fun onCreate(savedInstanceState: Bundle?) { 30 | super.onCreate(savedInstanceState) 31 | setContentView(R.layout.activity_recycler_view_item_anim) 32 | initListener() 33 | initView() 34 | initData() 35 | } 36 | 37 | private fun initView() { 38 | adapter = ItemAnimAdapter(arrayListOf()) 39 | recycler_view.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, false) 40 | recycler_view.adapter = adapter 41 | recycler_view.itemAnimator = DefaultItemAnimator() 42 | } 43 | 44 | private fun initListener() { 45 | normal_btn.setOnClickListener { setReverseLayout(false) } 46 | reverse_btn.setOnClickListener { setReverseLayout(true) } 47 | scale_btn.setOnClickListener { setItemAnimation(ScaleItemAnimation()) } 48 | slide_btn.setOnClickListener { setItemAnimation(SlideItemAnimation()) } 49 | rotate_x_btn.setOnClickListener { setItemAnimation(RotateXItemAnimation()) } 50 | rotate_y_btn.setOnClickListener { setItemAnimation(RotateYItemAnimation()) } 51 | 52 | add_btn.setOnClickListener { 53 | adapter?.addData(0, getItemData()) 54 | (recycler_view.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(0, 0) 55 | } 56 | 57 | remove_btn.setOnClickListener { 58 | if (adapter?.data?.size ?: 0 > 0) { 59 | adapter?.remove(0) 60 | (recycler_view.layoutManager as LinearLayoutManager).scrollToPositionWithOffset(0, 0) 61 | } 62 | } 63 | } 64 | 65 | private fun setReverseLayout(reverseLayout: Boolean) { 66 | recycler_view.layoutManager = LinearLayoutManager(this, RecyclerView.VERTICAL, reverseLayout) 67 | adapter?.data?.clear() 68 | adapter?.notifyDataSetChanged() 69 | } 70 | 71 | private fun setItemAnimation(itemAnimation: RecyclerView.ItemAnimator) { 72 | adapter?.data?.clear() 73 | adapter?.notifyDataSetChanged() 74 | recycler_view.itemAnimator = itemAnimation 75 | } 76 | 77 | private fun initData(): ArrayList
17 | * @author : xiaoyao 18 | * e-mail : xiaoyao@51vest.com 19 | * date : 2018/08/24 20 | * desc : 揭露动画 21 | * version : 1.0 22 | *23 | */ 24 | public class RevealAnimationActivity extends AppCompatActivity { 25 | 26 | private ImageView imageView; 27 | private Button startBtn; 28 | 29 | @Override 30 | protected void onCreate(@Nullable Bundle savedInstanceState) { 31 | super.onCreate(savedInstanceState); 32 | setContentView(R.layout.activity_reveal_animation); 33 | 34 | imageView = findViewById(R.id.img_iv); 35 | startBtn = findViewById(R.id.start_btn); 36 | 37 | 38 | final int centerX = 0; 39 | final int centerY = 0; 40 | startBtn.setOnClickListener(new View.OnClickListener() { 41 | @Override 42 | public void onClick(View v) { 43 | final float radius = (float) Math.hypot(imageView.getWidth(), imageView.getHeight()); 44 | 45 | if (imageView.getVisibility() == View.VISIBLE) { 46 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 47 | Animator animator = ViewAnimationUtils.createCircularReveal(imageView, centerX, centerY, radius, 0); 48 | animator.setDuration(3000); 49 | animator.addListener(new Animator.AnimatorListener() { 50 | @Override 51 | public void onAnimationStart(Animator animation) { 52 | 53 | } 54 | 55 | @Override 56 | public void onAnimationEnd(Animator animation) { 57 | imageView.setVisibility(View.GONE); 58 | } 59 | 60 | @Override 61 | public void onAnimationCancel(Animator animation) { 62 | 63 | } 64 | 65 | @Override 66 | public void onAnimationRepeat(Animator animation) { 67 | 68 | } 69 | }); 70 | animator.start(); 71 | } 72 | 73 | } else { 74 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { 75 | Animator animator = ViewAnimationUtils.createCircularReveal(imageView, centerX, centerY, 0, radius); 76 | animator.setDuration(3000); 77 | imageView.setVisibility(View.VISIBLE); 78 | animator.start(); 79 | } 80 | } 81 | } 82 | }); 83 | 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/activity/SinaVoteActivity.kt: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.activity 2 | 3 | import android.os.Bundle 4 | import android.support.v7.app.AppCompatActivity 5 | import com.allen.androidcustomview.R 6 | import com.allen.androidcustomview.bean.VoteBean 7 | import com.allen.androidcustomview.bean.VoteOption 8 | import com.allen.androidcustomview.data.getMockData 9 | import com.allen.androidcustomview.widget.vote.VoteLayoutAdapter 10 | import kotlinx.android.synthetic.main.activity_sina_vote.* 11 | 12 | /** 13 | *
14 | * @author : Allen 15 | * date : 2019/08/06 16 | * desc : 17 | *18 | */ 19 | class SinaVoteActivity : AppCompatActivity(), VoteLayoutAdapter.OnVoteClickListener { 20 | 21 | var voteLayoutAdapter: VoteLayoutAdapter? = null 22 | 23 | override fun onCreate(savedInstanceState: Bundle?) { 24 | super.onCreate(savedInstanceState) 25 | setContentView(R.layout.activity_sina_vote) 26 | voteLayoutAdapter = VoteLayoutAdapter(vote_ll) 27 | voteLayoutAdapter?.setData(getMockData()) 28 | voteLayoutAdapter?.onVoteClickListener = this 29 | } 30 | 31 | override fun onDestroy() { 32 | super.onDestroy() 33 | voteLayoutAdapter?.onDestroy() 34 | } 35 | 36 | override fun onVoteCommitBtnClick(mainVote: VoteBean?, optionIds: ArrayList
14 | * @author : xiaoyao 15 | * e-mail : xiaoyao@51vest.com 16 | * date : 2018/04/16 17 | * desc : 18 | * version : 1.0 19 | *20 | */ 21 | 22 | public class HoverAdapter extends BaseQuickAdapter
9 | * @author : Allen 10 | * e-mail :lygttpod@163.com 11 | * date : 2019/05/11 12 | * desc : 13 | *14 | */ 15 | class ItemAnimAdapter(list: ArrayList
14 | * @author : xiaoyao 15 | * e-mail : xiaoyao@51vest.com 16 | * date : 2018/05/14 17 | * desc : 18 | * version : 1.0 19 | *20 | */ 21 | 22 | public class MainAdapter extends BaseQuickAdapter
8 | * @author : Allen 9 | * e-mail : lygttpod@163.com 10 | * date : 2019/05/15 11 | * desc : 12 | *13 | */ 14 | class RotateXItemAnimation(animDuration: Long = 500) : SuperItemAnimation(animDuration) { 15 | 16 | init { 17 | addDuration = animDuration 18 | removeDuration = animDuration 19 | } 20 | 21 | override fun setAddItemAnimInit(holder: RecyclerView.ViewHolder?) { 22 | holder?.itemView?.rotationX = -90f 23 | } 24 | 25 | override fun setAddItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 26 | animator?.rotationX(0f) 27 | } 28 | 29 | override fun setAddItemAnimCancel(holder: RecyclerView.ViewHolder?) { 30 | holder?.itemView?.rotationX = 0f 31 | } 32 | 33 | override fun setRemoveItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 34 | animator?.rotationX(-90f) 35 | } 36 | 37 | override fun setRemoveItemAnimEnd(holder: RecyclerView.ViewHolder?) { 38 | holder?.itemView?.rotationX = 0f 39 | } 40 | 41 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/anim/RotateYItemAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.anim 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.view.ViewPropertyAnimator 5 | 6 | /** 7 | *
8 | * @author : Allen 9 | * e-mail : lygttpod@163.com 10 | * date : 2019/05/15 11 | * desc : 12 | *13 | */ 14 | class RotateYItemAnimation(animDuration: Long = 500) : SuperItemAnimation(animDuration) { 15 | 16 | override fun setAddItemAnimInit(holder: RecyclerView.ViewHolder?) { 17 | holder?.itemView?.rotationY = -90f 18 | } 19 | 20 | override fun setAddItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 21 | animator?.rotationY(0f) 22 | } 23 | 24 | override fun setAddItemAnimCancel(holder: RecyclerView.ViewHolder?) { 25 | holder?.itemView?.rotationY = 0f 26 | } 27 | 28 | override fun setRemoveItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 29 | animator?.rotationY(-90f) 30 | } 31 | 32 | override fun setRemoveItemAnimEnd(holder: RecyclerView.ViewHolder?) { 33 | holder?.itemView?.rotationY = 0f 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/anim/ScaleItemAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.anim 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.view.ViewPropertyAnimator 5 | 6 | /** 7 | *
8 | * @author : Allen 9 | * e-mail : lygttpod@163.com 10 | * date : 2019/05/15 11 | * desc : 12 | *13 | */ 14 | class ScaleItemAnimation(animDuration: Long = 500) : SuperItemAnimation(animDuration) { 15 | 16 | override fun setAddItemAnimInit(holder: RecyclerView.ViewHolder?) { 17 | holder?.itemView?.scaleX = 0f 18 | holder?.itemView?.scaleY = 0f 19 | } 20 | 21 | override fun setAddItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 22 | holder?.itemView?.pivotX = 0f 23 | holder?.itemView?.pivotY = 0f 24 | animator?.scaleX(1f)?.scaleY(1f) 25 | } 26 | 27 | override fun setAddItemAnimCancel(holder: RecyclerView.ViewHolder?) { 28 | holder?.itemView?.scaleX = 1f 29 | holder?.itemView?.scaleY = 1f 30 | } 31 | 32 | override fun setRemoveItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 33 | holder?.itemView?.pivotX = 1f 34 | holder?.itemView?.pivotY = 1f 35 | animator?.scaleX(0f)?.scaleY(0f) 36 | } 37 | 38 | override fun setRemoveItemAnimEnd(holder: RecyclerView.ViewHolder?) { 39 | holder?.itemView?.scaleX = 1f 40 | holder?.itemView?.scaleY = 1f 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/anim/SlideItemAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.anim 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.view.ViewPropertyAnimator 5 | 6 | /** 7 | *
8 | * @author : Allen 9 | * e-mail : lygttpod@163.com 10 | * date : 2019/05/15 11 | * desc : 12 | *13 | */ 14 | class SlideItemAnimation(animDuration: Long = 500) : SuperItemAnimation(animDuration) { 15 | 16 | override fun setAddItemAnimInit(holder: RecyclerView.ViewHolder?) { 17 | val with = holder?.itemView?.width ?: 0 18 | holder?.itemView?.translationX = -with.toFloat() 19 | } 20 | 21 | override fun setAddItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 22 | animator?.translationX(0f) 23 | } 24 | 25 | override fun setAddItemAnimCancel(holder: RecyclerView.ViewHolder?) { 26 | holder?.itemView?.translationX = 0f 27 | } 28 | 29 | override fun setRemoveItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 30 | val with = holder?.itemView?.width ?: 0 31 | animator?.translationX(-with.toFloat()) 32 | } 33 | 34 | override fun setRemoveItemAnimEnd(holder: RecyclerView.ViewHolder?) { 35 | holder?.itemView?.translationX = 0f 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/anim/SuperItemAnimation.kt: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.anim 2 | 3 | import android.support.v7.widget.RecyclerView 4 | import android.view.ViewPropertyAnimator 5 | 6 | /** 7 | *
8 | * @author : Allen 9 | * e-mail : lygttpod@163.com 10 | * date : 2019/05/15 11 | * desc : 12 | *13 | */ 14 | abstract class SuperItemAnimation(animDuration: Long = 200) : BaseItemAnimation() { 15 | 16 | init { 17 | addDuration = animDuration 18 | removeDuration = animDuration 19 | } 20 | 21 | abstract fun setAddItemAnimInit(holder: RecyclerView.ViewHolder?) 22 | abstract fun setAddItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) 23 | abstract fun setAddItemAnimCancel(holder: RecyclerView.ViewHolder?) 24 | 25 | abstract fun setRemoveItemAnim(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) 26 | abstract fun setRemoveItemAnimEnd(holder: RecyclerView.ViewHolder?) 27 | 28 | 29 | override fun setAddItemAnimationInit(holder: RecyclerView.ViewHolder?) { 30 | setAddItemAnimInit(holder) 31 | } 32 | 33 | override fun setAddItemAnimation(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 34 | setAddItemAnim(holder, animator) 35 | } 36 | 37 | override fun setAddItemAnimationCancel(holder: RecyclerView.ViewHolder?) { 38 | setAddItemAnimCancel(holder) 39 | } 40 | 41 | override fun setRemoveAnimation(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 42 | setRemoveItemAnim(holder, animator) 43 | } 44 | 45 | override fun setRemoveAnimationEnd(holder: RecyclerView.ViewHolder?) { 46 | setRemoveItemAnimEnd(holder) 47 | } 48 | 49 | 50 | override fun setOldChangeAnimation(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 51 | animator?.alpha(0f) 52 | } 53 | 54 | override fun setOldChangeAnimationEnd(holder: RecyclerView.ViewHolder?) { 55 | holder?.itemView?.alpha = 1f 56 | } 57 | 58 | override fun setNewChangeAnimationInit(holder: RecyclerView.ViewHolder?) { 59 | holder?.itemView?.alpha = 0f 60 | } 61 | 62 | override fun setNewChangeAnimation(holder: RecyclerView.ViewHolder?, animator: ViewPropertyAnimator?) { 63 | animator?.alpha(1f) 64 | } 65 | 66 | override fun setNewChangeAnimationEnd(holder: RecyclerView.ViewHolder?) { 67 | holder?.itemView?.alpha = 1f 68 | } 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/bean/CircleBean.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.bean; 2 | 3 | import android.graphics.PointF; 4 | 5 | /** 6 | * Created by allen on 2016/12/9. 7 | */ 8 | 9 | public class CircleBean { 10 | 11 | /** 12 | * 真实轨迹坐标点 13 | */ 14 | PointF p; 15 | /** 16 | * 起点坐标 17 | */ 18 | PointF p0; 19 | /** 20 | * 进入动画的控制点坐标 21 | */ 22 | PointF p1; 23 | /** 24 | * 到达中心点做坐标 25 | */ 26 | PointF p2; 27 | /** 28 | * 飞出动画控制点的坐标 29 | */ 30 | PointF p3; 31 | /** 32 | * 结束位置坐标 33 | */ 34 | PointF p4; 35 | 36 | /** 37 | * 小球半径 38 | */ 39 | private float radius; 40 | /** 41 | * 圆圈的透明度 42 | */ 43 | private int alpha; 44 | 45 | 46 | public CircleBean(PointF p0, PointF p1, PointF p2, PointF p3, PointF p4, float radius, int alpha) { 47 | this.p0 = p0; 48 | this.p1 = p1; 49 | this.p2 = p2; 50 | this.p3 = p3; 51 | this.p4 = p4; 52 | this.radius = radius; 53 | this.alpha = alpha; 54 | } 55 | 56 | public int getAlpha() { 57 | return alpha; 58 | } 59 | 60 | public void setAlpha(int alpha) { 61 | this.alpha = alpha; 62 | } 63 | 64 | public PointF getP4() { 65 | return p4; 66 | } 67 | 68 | public void setP4(PointF p4) { 69 | this.p4 = p4; 70 | } 71 | 72 | public PointF getP3() { 73 | return p3; 74 | } 75 | 76 | public void setP3(PointF p3) { 77 | this.p3 = p3; 78 | } 79 | 80 | public PointF getP2() { 81 | return p2; 82 | } 83 | 84 | public void setP2(PointF p2) { 85 | this.p2 = p2; 86 | } 87 | 88 | public PointF getP1() { 89 | return p1; 90 | } 91 | 92 | public void setP1(PointF p1) { 93 | this.p1 = p1; 94 | } 95 | 96 | public PointF getP0() { 97 | return p0; 98 | } 99 | 100 | public void setP0(PointF p0) { 101 | this.p0 = p0; 102 | } 103 | 104 | public PointF getP() { 105 | return p; 106 | } 107 | 108 | public void setP(PointF p) { 109 | this.p = p; 110 | } 111 | 112 | public float getRadius() { 113 | return radius; 114 | } 115 | 116 | public void setRadius(float radius) { 117 | this.radius = radius; 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/bean/TypeBean.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.bean; 2 | 3 | /** 4 | *
5 | * @author : xiaoyao 6 | * e-mail : xiaoyao@51vest.com 7 | * date : 2018/05/14 8 | * desc : 9 | * version : 1.0 10 | *11 | */ 12 | 13 | public class TypeBean { 14 | private String title; 15 | private int type; 16 | 17 | public TypeBean(String title, int type) { 18 | this.title = title; 19 | this.type = type; 20 | } 21 | 22 | public String getTitle() { 23 | return title; 24 | } 25 | 26 | public void setTitle(String title) { 27 | this.title = title; 28 | } 29 | 30 | public int getType() { 31 | return type; 32 | } 33 | 34 | public void setType(int type) { 35 | this.type = type; 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/bean/UserBean.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.bean; 2 | 3 | /** 4 | *
5 | * @author : xiaoyao 6 | * e-mail : xiaoyao@51vest.com 7 | * date : 2018/04/16 8 | * desc : 9 | * version : 1.0 10 | *11 | */ 12 | 13 | public class UserBean { 14 | private String userName; 15 | private String sortLetters=""; 16 | 17 | 18 | public String getUserName() { 19 | return userName; 20 | } 21 | 22 | public void setUserName(String userName) { 23 | this.userName = userName; 24 | } 25 | 26 | public String getSortLetters() { 27 | return sortLetters; 28 | } 29 | 30 | public void setSortLetters(String sortLetters) { 31 | this.sortLetters = sortLetters; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/bean/VoteBean.kt: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.bean 2 | 3 | 4 | /** 5 | *
6 | * @author : Allen 7 | * date : 2019/08/01 8 | * desc : 9 | *10 | */ 11 | 12 | class VoteBean(val id: Int = 0, 13 | val title: String?, 14 | val choiceType: String?, 15 | val maxSelect: Int?, 16 | var voted: Boolean?, 17 | val sumVoteCount: Int?, 18 | val options: ArrayList
9 | * @author : Allen 10 | * date : 2019/08/06 11 | * desc : 12 | *13 | */ 14 | 15 | fun getMockData(): ArrayList
15 | * @author : Allen 16 | * e-mail : lygttpod@163.com 17 | * date : 2019/03/14 18 | * desc : 拖拽view辅助类 19 | *20 | */ 21 | object DragViewHelper { 22 | 23 | @SuppressLint("ClickableViewAccessibility") 24 | fun addDragView(context: Context, 25 | parent: ViewGroup, 26 | imgUrl: String, 27 | defaultImgResId: Int = R.mipmap.ic_launcher, 28 | dragViewSize: Float = 60f, 29 | dragViewOriginalMarginRight: Float = 20f, 30 | dragViewOriginalMarginBottom: Float = 20f, 31 | autoPullToBorder: Boolean = true, 32 | onClick: (() -> Unit)? = null): ImageView { 33 | val dragView = ImageView(context) 34 | parent.post { 35 | val onDragTouchListener = OnDragTouchListener() 36 | onDragTouchListener.clickListener = { 37 | onClick?.invoke() 38 | } 39 | onDragTouchListener.mMaxWidth = parent.width 40 | onDragTouchListener.mMaxHeight = parent.height 41 | onDragTouchListener.mBorderMargin = DisplayUtils.dip2px(context, 15f).toFloat() 42 | onDragTouchListener.mIsAutoToBorder = autoPullToBorder 43 | dragView.scaleType = ImageView.ScaleType.CENTER_CROP 44 | dragView.setOnTouchListener(onDragTouchListener) 45 | val layoutParams = RelativeLayout.LayoutParams(DisplayUtils.dip2px(context, dragViewSize), DisplayUtils.dip2px(context, dragViewSize)) 46 | layoutParams.leftMargin = parent.width - DisplayUtils.dip2px(context, dragViewSize + dragViewOriginalMarginRight) 47 | layoutParams.topMargin = parent.height - DisplayUtils.dip2px(context, dragViewSize + dragViewOriginalMarginBottom) 48 | // GlideApp.with(context).load(imgUrl).into(dragView) 49 | dragView.setBackgroundResource(defaultImgResId) 50 | parent.addView(dragView, layoutParams) 51 | } 52 | 53 | return dragView 54 | } 55 | 56 | fun removeDragView(parent: ViewGroup, view: View?) { 57 | if (view != null) { 58 | parent.removeView(view) 59 | } 60 | } 61 | 62 | fun updateDragView(context: Context, dragView: ImageView?, imgUrl: String) { 63 | if (dragView != null) { 64 | // GlideApp.with(context).load(imgUrl).into(dragView) 65 | } 66 | } 67 | 68 | 69 | } -------------------------------------------------------------------------------- /app/src/main/java/com/allen/androidcustomview/tagview/TagActivity.java: -------------------------------------------------------------------------------- 1 | package com.allen.androidcustomview.tagview; 2 | 3 | import android.support.v7.app.AppCompatActivity; 4 | import android.os.Bundle; 5 | import android.support.v7.widget.GridLayoutManager; 6 | import android.support.v7.widget.RecyclerView; 7 | 8 | import com.allen.androidcustomview.R; 9 | 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class TagActivity extends AppCompatActivity { 14 | 15 | private RecyclerView tagRecyclerView; 16 | 17 | private static final int MAX = 9; 18 | private List
8 | * 贝塞尔曲线计算工具类
9 | */
10 |
11 | public class BezierUtil {
12 |
13 |
14 | /**
15 | * 二阶贝塞尔曲线
16 | * B(t) = Po*(1-t)^2 + 2*p1*t*(1-t)+t^2*p2
17 | *
18 | * @param t 曲线长度比例
19 | * @param p0 起始点
20 | * @param p1 控制点
21 | * @param p2 终止点
22 | * @return t对应的点
23 | */
24 | public static PointF CalculateBezierPointForQuadratic(float t, PointF p0, PointF p1, PointF p2) {
25 | PointF point = new PointF();
26 | float temp = 1 - t;
27 | // point.x = temp * temp * p0.x + 2 * t * temp * p1.x + t * t * p2.x;
28 | // point.y = temp * temp * p0.y + 2 * t * temp * p1.y + t * t * p2.y;
29 | point.x = (float) (Math.pow(temp, 2) * p0.x + 2 * t * temp * p1.x + Math.pow(t, 2) * p2.x);
30 | point.y = (float) (Math.pow(temp, 2) * p0.y + 2 * t * temp * p1.y + Math.pow(t, 2) * p2.y);
31 | return point;
32 | }
33 |
34 | /**
35 | * 三
36 | * 阶贝塞尔曲线
37 | * B(t) = Po*(1-t)^3 + 3*p1*t*(1-t)^2+3*p2*t^2*(1-t)+p3*t^3,
38 | *
39 | * @param t 曲线长度比例
40 | * @param p0 起始点
41 | * @param p1 控制点1
42 | * @param p2 控制点2
43 | * @param p3 终止点
44 | * @return t对应的点
45 | */
46 | public static PointF CalculateBezierPointForCubic(float t, PointF p0, PointF p1, PointF p2, PointF p3) {
47 | PointF point = new PointF();
48 | float temp = 1 - t;
49 | // point.x = p0.x * temp * temp * temp + 3 * p1.x * t * temp * temp + 3 * p2.x * t * t * temp + p3.x * t * t * t;
50 | // point.y = p0.y * temp * temp * temp + 3 * p1.y * t * temp * temp + 3 * p2.y * t * t * temp + p3.y * t * t * t;
51 | point.x = (float) (p0.x * Math.pow(temp, 3) + 3 * p1.x * t * Math.pow(temp, 2) + 3 * p2.x * Math.pow(t, 2) * temp + p3.x * Math.pow(t, 3));
52 | point.y = (float) (p0.y * Math.pow(temp, 3) + 3 * p1.y * t * Math.pow(temp, 2) + 3 * p2.y * Math.pow(t, 2) * temp + p3.y * Math.pow(t, 3));
53 | return point;
54 | }
55 |
56 | }
57 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/utils/DisplayUtils.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.utils;
2 |
3 | import android.content.Context;
4 | import android.util.DisplayMetrics;
5 | import android.view.WindowManager;
6 |
7 | /**
8 | * 与屏幕信息有关的类,包括屏幕的长宽、分辨率、长度换算
9 | *
10 | */
11 | public class DisplayUtils {
12 |
13 |
14 | /**
15 | * 获取屏幕分辨率
16 | * @param context
17 | * @return
18 | */
19 | public static int[] getScreenDispaly(Context context) {
20 | WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
21 | int width = windowManager.getDefaultDisplay().getWidth();// 手机屏幕的宽度
22 | int height = windowManager.getDefaultDisplay().getHeight();// 手机屏幕的高度
23 | int result[] = { width, height };
24 | return result;
25 | }
26 |
27 | /** 获取屏幕宽度 */
28 | public static int getDisplayWidth(Context context) {
29 | if (context != null) {
30 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
31 | int w_screen = dm.widthPixels;
32 | // int h_screen = dm.heightPixels;
33 | return w_screen;
34 | }
35 | return 720;
36 | }
37 |
38 | /** 获取屏幕高度 */
39 | public static int getDisplayHight(Context context) {
40 | if (context != null) {
41 | DisplayMetrics dm = context.getResources().getDisplayMetrics();
42 | // int w_screen = dm.widthPixels;
43 | int h_screen = dm.heightPixels;
44 | return h_screen;
45 | }
46 | return 1280;
47 | }
48 |
49 | public static int dip2px(Context context, float dipValue) {
50 | final float scale = context.getResources().getDisplayMetrics().density;
51 | return (int) (dipValue * scale + 0.5f);
52 | }
53 |
54 | public static int px2dip(Context context, float pxValue) {
55 | final float scale = context.getResources().getDisplayMetrics().density;
56 | return (int) (pxValue / scale + 0.5f);
57 | }
58 |
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/utils/FingerprintUtil.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.utils;
2 |
3 | import android.app.KeyguardManager;
4 | import android.content.Context;
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.support.v4.hardware.fingerprint.FingerprintManagerCompat;
8 | import android.support.v4.os.CancellationSignal;
9 |
10 | /**
11 | * Created by xiaoyao on 2017/9/14.
12 | * 指纹识别工具类
13 | */
14 |
15 | public class FingerprintUtil {
16 |
17 | private static CancellationSignal cancellationSignal;
18 |
19 | public static void callFingerPrint(Context context, final OnCallBackListener listener) {
20 |
21 | if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
22 | return;
23 | }
24 | FingerprintManagerCompat managerCompat = FingerprintManagerCompat.from(context);
25 | if (!managerCompat.isHardwareDetected()) { //判断设备是否支持
26 | if (listener != null)
27 | listener.onSupportFailed();
28 | return;
29 | }
30 |
31 | KeyguardManager keyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
32 | if (!keyguardManager.isKeyguardSecure()) {//判断设备是否处于安全保护中
33 | if (listener != null)
34 | listener.onInsecurity();
35 | return;
36 | }
37 |
38 | if (!managerCompat.hasEnrolledFingerprints()) { //判断设备是否已经注册过指纹
39 | if (listener != null)
40 | listener.onEnrollFailed(); //未注册
41 | return;
42 | }
43 |
44 | if (listener != null)
45 | listener.onAuthenticationStart(); //开始指纹识别
46 |
47 | cancellationSignal = new CancellationSignal(); //必须重新实例化,否则cancel 过一次就不能再使用了
48 |
49 | managerCompat.authenticate(null, 0, cancellationSignal, new FingerprintManagerCompat.AuthenticationCallback() {
50 | // 当出现错误的时候回调此函数,比如多次尝试都失败了的时候,errString是错误信息,比如华为的提示就是:尝试次数过多,请稍后再试。
51 | @Override
52 | public void onAuthenticationError(int errMsgId, CharSequence errString) {
53 | if (listener != null)
54 | listener.onAuthenticationError(errMsgId, errString);
55 | }
56 |
57 | // 当指纹验证失败的时候会回调此函数,失败之后允许多次尝试,失败次数过多会停止响应一段时间然后再停止sensor的工作
58 | @Override
59 | public void onAuthenticationFailed() {
60 | if (listener != null)
61 | listener.onAuthenticationFailed();
62 | }
63 |
64 | @Override
65 | public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) {
66 | if (listener != null)
67 | listener.onAuthenticationHelp(helpMsgId, helpString);
68 | }
69 |
70 | // 当验证的指纹成功时会回调此函数,然后不再监听指纹sensor
71 | @Override
72 | public void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result) {
73 | if (listener != null)
74 | listener.onAuthenticationSucceeded(result);
75 | }
76 | }, null);
77 |
78 | }
79 |
80 | public interface OnCallBackListener {
81 | void onSupportFailed();
82 |
83 | void onInsecurity();
84 |
85 | void onEnrollFailed();
86 |
87 | void onAuthenticationStart();
88 |
89 | void onAuthenticationError(int errMsgId, CharSequence errString);
90 |
91 | void onAuthenticationFailed();
92 |
93 | void onAuthenticationHelp(int helpMsgId, CharSequence helpString);
94 |
95 | void onAuthenticationSucceeded(FingerprintManagerCompat.AuthenticationResult result);
96 | }
97 |
98 | public static void cancel() {
99 | if (cancellationSignal != null)
100 | cancellationSignal.cancel();
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/utils/PinyinComparator.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.utils;
2 |
3 |
4 | import com.allen.androidcustomview.bean.UserBean;
5 |
6 | import java.util.Comparator;
7 |
8 | public class PinyinComparator implements Comparator
11 | * @author : Allen
12 | * e-mail : lygttpod@163.com
13 | * date : 2019/07/07
14 | * desc :
15 | *
16 | */
17 | class ArcView : View {
18 | private var mWidth = 0
19 | private var mHeight = 0
20 | /**
21 | * 弧形高度
22 | */
23 | private var mArcHeight = 0
24 | /**
25 | * 背景颜色
26 | */
27 | private var mBgColor = Color.WHITE
28 | private var mPaint = Paint()
29 | private var mContext: Context? = null
30 |
31 | private var mPath = Path()
32 |
33 | constructor(context: Context) : this(context, null)
34 | constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
35 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
36 | initView(context, attrs, defStyleAttr)
37 | }
38 |
39 | private fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
40 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ArcView)
41 | mArcHeight = typedArray.getDimensionPixelSize(R.styleable.ArcView_arcHeight, 0)
42 | mBgColor = typedArray.getColor(R.styleable.ArcView_bgColor, Color.WHITE)
43 | typedArray.recycle()
44 |
45 | mContext = context
46 | mPaint.style = Paint.Style.FILL_AND_STROKE
47 | mPaint.color = mBgColor
48 | mPaint.isAntiAlias = true
49 | mPaint.strokeWidth = 1f
50 | }
51 |
52 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
53 | super.onSizeChanged(w, h, oldw, oldh)
54 | mWidth = w
55 | mHeight = h
56 | resetPath()
57 | }
58 |
59 | private fun resetPath() {
60 | mPath.reset()
61 | mPath.moveTo(0f, 0f)
62 | mPath.lineTo(0f, (mHeight - mArcHeight).toFloat())
63 | mPath.quadTo((mWidth / 2).toFloat(), (mHeight + mArcHeight).toFloat(), mWidth.toFloat(), (mHeight - mArcHeight).toFloat())
64 | mPath.lineTo(mWidth.toFloat(), 0f)
65 | mPath.close()
66 | }
67 |
68 | override fun onDraw(canvas: Canvas?) {
69 | super.onDraw(canvas)
70 | canvas?.drawPath(mPath, mPaint)
71 | }
72 |
73 | fun setArcViewBgColor(color: Int) {
74 | mBgColor = color
75 | mPaint.color = color
76 | invalidate()
77 | }
78 |
79 | fun getArcViewBgColor() = mBgColor
80 |
81 | fun setArcViewHeight(height: Int) {
82 | if (height == mHeight) return
83 | mHeight = height
84 | resetPath()
85 | invalidate()
86 | }
87 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/BaseView.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Paint;
5 | import android.support.annotation.Nullable;
6 | import android.util.AttributeSet;
7 | import android.util.TypedValue;
8 | import android.view.View;
9 |
10 | /**
11 | * Created by xiaoyao on 2017/5/23.
12 | */
13 |
14 | public class BaseView extends View {
15 |
16 | public int mWidth;
17 | public int mHeight;
18 | public int mViewHeight;
19 |
20 |
21 | public BaseView(Context context) {
22 | this(context, null);
23 |
24 | mViewHeight = dp2px(45);
25 | }
26 |
27 | public BaseView(Context context, @Nullable AttributeSet attrs) {
28 | super(context, attrs);
29 | }
30 |
31 | @Override
32 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
33 | int widthMode = MeasureSpec.getMode(widthMeasureSpec);
34 | int width = MeasureSpec.getSize(widthMeasureSpec);
35 |
36 | int heightMode = MeasureSpec.getMode(heightMeasureSpec);
37 | int height = MeasureSpec.getSize(heightMeasureSpec);
38 |
39 | setMeasuredDimension(measureWidth(widthMode, width), measureHeight(heightMode, height));
40 | }
41 |
42 | /**
43 | * 测量宽度
44 | *
45 | * @param mode
46 | * @param width
47 | * @return
48 | */
49 | private int measureWidth(int mode, int width) {
50 | switch (mode) {
51 | case MeasureSpec.UNSPECIFIED:
52 | case MeasureSpec.AT_MOST:
53 | break;
54 | case MeasureSpec.EXACTLY:
55 | mWidth = width;
56 | break;
57 | }
58 | return mWidth;
59 | }
60 |
61 | /**
62 | * 测量高度
63 | *
64 | * @param mode
65 | * @param height
66 | * @return
67 | */
68 | private int measureHeight(int mode, int height) {
69 | switch (mode) {
70 | case MeasureSpec.UNSPECIFIED:
71 | case MeasureSpec.AT_MOST:
72 | mHeight = mViewHeight;
73 | break;
74 | case MeasureSpec.EXACTLY:
75 | mHeight = height;
76 | break;
77 | }
78 | return mHeight;
79 | }
80 |
81 | /**
82 | * 统一处理paint
83 | * @param strokeWidth
84 | * @param color
85 | * @param style
86 | * @return
87 | */
88 | public Paint getPaint(int strokeWidth, int color, Paint.Style style) {
89 | Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
90 | paint.setStrokeWidth(strokeWidth);
91 | paint.setColor(color);
92 | paint.setAntiAlias(true);
93 | paint.setStrokeCap(Paint.Cap.ROUND);
94 | paint.setStyle(style);
95 | return paint;
96 | }
97 |
98 |
99 | /**
100 | * dp 2 px
101 | *
102 | * @param dpVal
103 | */
104 | protected int dp2px(int dpVal) {
105 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
106 | dpVal, getResources().getDisplayMetrics());
107 | }
108 |
109 | /**
110 | * sp 2 px
111 | *
112 | * @param spVal
113 | * @return
114 | */
115 | protected int sp2px(int spVal) {
116 | return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,
117 | spVal, getResources().getDisplayMetrics());
118 |
119 | }
120 |
121 | }
122 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/CarMoveView.kt:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget
2 |
3 | import android.animation.Animator
4 | import android.animation.ValueAnimator
5 | import android.content.Context
6 | import android.graphics.*
7 | import android.graphics.drawable.BitmapDrawable
8 | import android.graphics.drawable.Drawable
9 | import android.util.AttributeSet
10 | import android.view.MotionEvent
11 | import android.view.View
12 | import com.allen.androidcustomview.R
13 | import kotlin.math.atan2
14 |
15 |
16 | /**
17 | *
18 | * @author : Allen
19 | * date : 2019/07/23
20 | * desc : 小汽车跟随轨迹运动
21 | *
22 | */
23 | class CarMoveView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : View(context, attrs, defStyleAttr) {
24 |
25 | private var mWidth = 0
26 | private var mHeight = 0
27 |
28 | /**
29 | * 背景颜色
30 | */
31 | private var mPathColor = Color.RED
32 | private var mPaint = Paint()
33 | private var mCarPaint = Paint()
34 |
35 | private var mRect = Rect()
36 | private var mMovePath = Path()
37 |
38 | private var mStartX = 0f
39 | private var mStartY = 0f
40 |
41 | private var pathMeasure: PathMeasure = PathMeasure()
42 |
43 | private val pos = FloatArray(2)
44 | private val tan = FloatArray(2)
45 |
46 | private var isMoveCar = false
47 |
48 | private var mRectWidth = 30
49 |
50 | private var mDuration = 5
51 | private var mCarDrawableRes: Drawable? = null
52 | private var mCarBitmapRes: Bitmap? = null
53 |
54 | init {
55 | initView(context, attrs, defStyleAttr)
56 | initPaint()
57 | mCarBitmapRes = (mCarDrawableRes as? BitmapDrawable)?.bitmap
58 | }
59 |
60 | private fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) {
61 | val typedArray = context.obtainStyledAttributes(attrs, R.styleable.CarMoveView)
62 | mPathColor = typedArray.getColor(R.styleable.CarMoveView_carMovePathColor, mPathColor)
63 | mDuration = typedArray.getInt(R.styleable.CarMoveView_carMoveDuration, mDuration)
64 | mCarDrawableRes = typedArray.getDrawable(R.styleable.CarMoveView_carMoveDrawableRes)
65 | typedArray.recycle()
66 | }
67 |
68 | private fun initPaint() {
69 | mPaint.color = mPathColor
70 | mPaint.style = Paint.Style.STROKE
71 | mPaint.isAntiAlias = true
72 |
73 | mCarPaint.color = mPathColor
74 | mCarPaint.style = Paint.Style.FILL
75 | mCarPaint.isAntiAlias = true
76 | }
77 |
78 | override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
79 | super.onSizeChanged(w, h, oldw, oldh)
80 | mWidth = w
81 | mHeight = h
82 | }
83 |
84 | override fun onDraw(canvas: Canvas?) {
85 | super.onDraw(canvas)
86 | drawPath(canvas)
87 | drawMoveCar(canvas)
88 | }
89 |
90 | private fun drawPath(canvas: Canvas?) {
91 | canvas?.drawPath(mMovePath, mPaint)
92 | }
93 |
94 | private fun drawMoveCar(canvas: Canvas?) {
95 | pathMeasure.setPath(mMovePath, false)
96 | if (isMoveCar) {
97 | // 计算图片旋转角度
98 | val degrees = (atan2(tan[1].toDouble(), tan[0].toDouble()) * 180.0 / Math.PI).toFloat()
99 | canvas?.rotate(degrees, pos[0], pos[1])
100 | //小车中心点在运行轨道上
101 | mRect.set((pos[0] - mRectWidth).toInt(), (pos[1] - mRectWidth).toInt(), (pos[0] + mRectWidth).toInt(), (pos[1] + mRectWidth).toInt())
102 | //小车轮子在运行轨道上
103 | //mRect.set((pos[0] - mRectWidth).toInt(), (pos[1] - mRectWidth * 2).toInt(), (pos[0] + mRectWidth).toInt(), (pos[1]).toInt())
104 | if (mCarBitmapRes == null) {
105 | canvas?.drawRect(mRect, mCarPaint)
106 | } else {
107 | canvas?.drawBitmap(mCarBitmapRes, null, mRect, mPaint)
108 | }
109 | }
110 | }
111 |
112 | override fun onTouchEvent(event: MotionEvent): Boolean {
113 | when (event.action) {
114 | MotionEvent.ACTION_DOWN -> {
115 | mStartX = event.x
116 | mStartY = event.y
117 | mMovePath.reset()
118 | mMovePath.moveTo(mStartX, mStartY)
119 | return true
120 | }
121 | MotionEvent.ACTION_MOVE -> {
122 | val endX = (mStartX + event.x) / 2
123 | val endY = (mStartY + event.y) / 2
124 | mMovePath.quadTo(mStartX, mStartY, endX, endY)
125 | mStartX = event.x
126 | mStartY = event.y
127 | invalidate()
128 | return true
129 | }
130 | }
131 | return super.onTouchEvent(event)
132 | }
133 |
134 | fun startAnim() {
135 | isMoveCar = true
136 | val valueAnimator = ValueAnimator.ofFloat(0f, pathMeasure.length)
137 | valueAnimator.duration = mDuration * 1000L
138 | valueAnimator.addUpdateListener {
139 | val distance: Float = it.animatedValue as Float
140 | pathMeasure.getPosTan(distance, pos, tan)
141 | invalidate()
142 | }
143 | valueAnimator.addListener(object : Animator.AnimatorListener {
144 | override fun onAnimationRepeat(animation: Animator?) {}
145 |
146 | override fun onAnimationEnd(animation: Animator?) {
147 | isMoveCar = false
148 | }
149 |
150 | override fun onAnimationCancel(animation: Animator?) {
151 | isMoveCar = false
152 | }
153 |
154 | override fun onAnimationStart(animation: Animator?) {}
155 |
156 | })
157 | valueAnimator.start()
158 | }
159 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/DividerItemDecoration.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Canvas;
6 | import android.graphics.Rect;
7 | import android.graphics.drawable.Drawable;
8 | import android.support.v7.widget.LinearLayoutManager;
9 | import android.support.v7.widget.RecyclerView;
10 | import android.view.View;
11 |
12 | /**
13 | *
14 | * @author : xiaoyao
15 | * e-mail : xiaoyao@51vest.com
16 | * date : 2018/02/05
17 | * desc : recyclerview的分割线
18 | * version : 1.0
19 | *
20 | */
21 |
22 | public class DividerItemDecoration extends RecyclerView.ItemDecoration {
23 | private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
24 |
25 | public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
26 |
27 | public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
28 |
29 |
30 | private Drawable mDivider;
31 |
32 | private int mOrientation;
33 |
34 | private Context context;
35 |
36 | public DividerItemDecoration(Context context, int orientation) {
37 | final TypedArray a = context.obtainStyledAttributes(ATTRS);
38 | mDivider = a.getDrawable(0);
39 | this.context = context;
40 | a.recycle();
41 | setOrientation(orientation);
42 | }
43 |
44 | public void setOrientation(int orientation) {
45 | if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
46 | throw new IllegalArgumentException("invalid orientation");
47 | }
48 | mOrientation = orientation;
49 | }
50 |
51 | @Override
52 | public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
53 | super.onDraw(c, parent, state);
54 | if (mOrientation == VERTICAL_LIST) {
55 | drawVertical(c, parent);
56 | } else {
57 | drawHorizontal(c, parent);
58 | }
59 | }
60 |
61 | public void drawVertical(Canvas c, RecyclerView parent) {
62 | final int left = parent.getPaddingLeft() + dip2px(context, 0);
63 | final int right = parent.getWidth() - parent.getPaddingRight() - dip2px(context, 0);
64 |
65 | final int childCount = parent.getChildCount();
66 |
67 | for (int i = 0; i < childCount; i++) {
68 | final View child = parent.getChildAt(i);
69 | android.support.v7.widget.RecyclerView v = new android.support.v7.widget.RecyclerView(
70 | parent.getContext());
71 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
72 | .getLayoutParams();
73 | final int top = child.getBottom() + params.bottomMargin;
74 | final int bottom = top + mDivider.getIntrinsicHeight();
75 | mDivider.setBounds(left, top, right, bottom);
76 | mDivider.draw(c);
77 | }
78 | }
79 |
80 | public void drawHorizontal(Canvas c, RecyclerView parent) {
81 | final int top = parent.getPaddingTop();
82 | final int bottom = parent.getHeight() - parent.getPaddingBottom();
83 |
84 | final int childCount = parent.getChildCount();
85 | for (int i = 0; i < childCount; i++) {
86 | final View child = parent.getChildAt(i);
87 | final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
88 | .getLayoutParams();
89 | final int left = child.getRight() + params.rightMargin;
90 | final int right = left + mDivider.getIntrinsicHeight();
91 | mDivider.setBounds(left, top, right, bottom);
92 | mDivider.draw(c);
93 | }
94 | }
95 |
96 | @Override
97 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
98 | super.getItemOffsets(outRect, view, parent, state);
99 | if (mOrientation == VERTICAL_LIST) {
100 | outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
101 | } else {
102 | outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
103 | }
104 | }
105 |
106 | /**
107 | * 单位转换工具类
108 | *
109 | * @param context 上下文对象
110 | * @param dipValue 值
111 | * @return 返回值
112 | */
113 | private int dip2px(Context context, float dipValue) {
114 | final float scale = context.getResources().getDisplayMetrics().density;
115 | return (int) (dipValue * scale + 0.5f);
116 | }
117 | }
118 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/IndexView.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import android.util.AttributeSet;
7 | import android.view.MotionEvent;
8 | import android.view.View;
9 | import android.widget.TextView;
10 |
11 | /**
12 | * Created by allen on 2016/10/26.
13 | */
14 |
15 | public class IndexView extends View {
16 |
17 | private Context mContext;
18 | private TextView mShowTextDialog;
19 |
20 |
21 | private Paint mPaint;
22 |
23 | private int mWidth;
24 | private int mHeight;
25 |
26 | private int mCellWidth;
27 | private int mCellHeight;
28 |
29 | private int mWordSize;
30 | private int mwordColor;
31 | private int mChoose = -1;// 选中
32 |
33 |
34 | private int GRAY = 0xFFe8e8e8;
35 | private int DEFAULT_TEXT_COLOR = 0xFF999999;
36 |
37 | private static final String[] WORDS = new String[]{
38 | "↑", "☆", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K",
39 | "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W",
40 | "X", "Y", "Z", "#"
41 | };
42 |
43 | private OnTouchingLetterChangedListener mOnTouchingLetterChangedListener;
44 |
45 | public IndexView(Context context) {
46 | this(context, null);
47 | }
48 |
49 | public IndexView(Context context, AttributeSet attrs) {
50 | this(context, attrs, 0);
51 | }
52 |
53 | public IndexView(Context context, AttributeSet attrs, int defStyleAttr) {
54 | super(context, attrs, defStyleAttr);
55 | mContext = context;
56 | mWordSize = sp2px(mContext, 12);
57 | mwordColor = 0;
58 | initPaint();
59 | }
60 |
61 |
62 | public void setShowTextDialog(TextView textDialog) {
63 | this.mShowTextDialog = textDialog;
64 | }
65 |
66 | private void initPaint() {
67 | mPaint = new Paint();
68 | mPaint.setColor(DEFAULT_TEXT_COLOR);
69 | mPaint.setAntiAlias(true);
70 | mPaint.setTextSize(mWordSize);
71 | }
72 |
73 | @Override
74 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
75 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
76 | mWidth = getMeasuredWidth();
77 | mHeight = getMeasuredHeight();
78 |
79 | mCellHeight = mHeight / WORDS.length;
80 | }
81 |
82 | @Override
83 | protected void onDraw(Canvas canvas) {
84 | super.onDraw(canvas);
85 | for (int i = 0; i < WORDS.length; i++) {
86 | float xPos = mWidth / 2 - mPaint.measureText(WORDS[i]) / 2;
87 | float yPos = mCellHeight * i + mCellHeight;
88 | canvas.drawText(WORDS[i], xPos, yPos, mPaint);
89 | }
90 |
91 | }
92 |
93 | @Override
94 | public boolean onTouchEvent(MotionEvent event) {
95 | final int action = event.getAction();
96 | final float y = event.getY();// 点击y坐标
97 | final int oldChoose = mChoose;
98 | final int c = (int) (y / getHeight() * WORDS.length);// 点击y坐标所占总高度的比例*b数组的长度就等于点击b中的个数.
99 |
100 |
101 | switch (action) {
102 | case MotionEvent.ACTION_UP:
103 | setBackgroundColor(0x00000000);
104 | mChoose = -1;//
105 | invalidate();
106 | if (mShowTextDialog != null) {
107 | mShowTextDialog.setVisibility(View.INVISIBLE);
108 | }
109 | break;
110 |
111 | default:
112 | setBackgroundColor(GRAY);
113 | if (oldChoose != c) {
114 | if (c >= 0 && c < WORDS.length) {
115 | if (mOnTouchingLetterChangedListener != null) {
116 | mOnTouchingLetterChangedListener.onTouchingLetterChanged(WORDS[c]);
117 | }
118 | if (mShowTextDialog != null) {
119 | mShowTextDialog.setText(WORDS[c]);
120 | mShowTextDialog.setVisibility(View.VISIBLE);
121 | }
122 |
123 | mChoose = c;
124 | invalidate();
125 | }
126 | }
127 |
128 | break;
129 | }
130 | return true;
131 | }
132 |
133 |
134 | public void setOnTouchingLetterChangedListener(OnTouchingLetterChangedListener letterChangedListener) {
135 | mOnTouchingLetterChangedListener = letterChangedListener;
136 |
137 | }
138 |
139 | public interface OnTouchingLetterChangedListener {
140 | void onTouchingLetterChanged(String letter);
141 | }
142 |
143 | /**
144 | * 文字字体大小sp转换px
145 | *
146 | * @param context 上下文对象
147 | * @param spValue sp的值
148 | * @return 返回值
149 | */
150 | public int sp2px(Context context, float spValue) {
151 | final float scale = context.getResources().getDisplayMetrics().scaledDensity;
152 | return (int) (spValue * scale + 0.5f);
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/banner/adapter/BannerViewPagerAdapter.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget.banner.adapter;
2 |
3 | import android.support.annotation.NonNull;
4 | import android.support.v4.view.PagerAdapter;
5 | import android.view.View;
6 | import android.view.ViewGroup;
7 |
8 | import com.allen.androidcustomview.widget.banner.listener.OnPageClickListener;
9 | import com.allen.androidcustomview.widget.banner.holder.BannerViewHolder;
10 | import com.allen.androidcustomview.widget.banner.holder.BannerViewHolderCreator;
11 |
12 | import java.util.ArrayList;
13 | import java.util.List;
14 |
15 | /**
16 | *
17 | * @author : xiaoyao
18 | * e-mail : xiaoyao@51vest.com
19 | * date : 2018/03/02
20 | * desc :
21 | * version : 1.0
22 | *
23 | */
24 |
25 | public class BannerViewPagerAdapter
8 | * @author : xiaoyao
9 | * e-mail : xiaoyao@51vest.com
10 | * date : 2018/03/02
11 | * desc :
12 | * version : 1.0
13 | *
14 | */
15 |
16 | public interface BannerViewHolder
5 | * @author : xiaoyao
6 | * e-mail : xiaoyao@51vest.com
7 | * date : 2018/03/02
8 | * desc :
9 | * version : 1.0
10 | *
11 | */
12 |
13 | public interface BannerViewHolderCreator
5 | * @author : xiaoyao
6 | * e-mail : xiaoyao@51vest.com
7 | * date : 2018/03/09
8 | * desc :
9 | * version : 1.0
10 | *
11 | */
12 |
13 | public interface OnPageChangeListener {
14 |
15 | /**
16 | * item 选中事件
17 | *
18 | * @param position position
19 | */
20 | void onPageSelected(int position);
21 | }
22 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/banner/listener/OnPageClickListener.java:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget.banner.listener;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | *
7 | * @author : xiaoyao
8 | * e-mail : xiaoyao@51vest.com
9 | * date : 2018/03/02
10 | * desc :
11 | * version : 1.0
12 | *
13 | */
14 |
15 | public interface OnPageClickListener {
16 |
17 | /**
18 | * item 点击事件
19 | *
20 | * @param view view
21 | * @param position position
22 | */
23 | void onPageClick(View view, int position);
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/status/StatusBuilder.kt:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget.status
2 |
3 | import android.view.View
4 |
5 | /**
6 | *
7 | * @author : Allen
8 | * e-mail : lygttpod@163.com
9 | * date : 2019/03/19
10 | * desc :
11 | *
12 | */
13 | class StatusBuilder {
14 |
15 | class Builder{
16 |
17 | var contentView: View? = null
18 | var errorView: View? = null
19 | var emptyView: View? = null
20 | var loadingView: View? = null
21 |
22 | fun setContentView(contentView: View):Builder {
23 | this.contentView = contentView
24 | return this
25 | }
26 | fun setContentView(layoutResId: Int):Builder {
27 | this.contentView = contentView
28 | return this
29 | }
30 |
31 | fun setErrorView(errorView: View):Builder {
32 | this.errorView = errorView
33 | return this
34 | }
35 |
36 | fun setEmptyView(emptyView: View):Builder {
37 | this.emptyView = emptyView
38 | return this
39 | }
40 |
41 | fun setLoadingView(loadingView: View):Builder {
42 | this.loadingView = loadingView
43 | return this
44 | }
45 |
46 | fun build(){
47 |
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/status/StatusLayout.kt:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget.status
2 |
3 | import android.content.Context
4 | import android.util.AttributeSet
5 | import android.widget.FrameLayout
6 |
7 | /**
8 | *
9 | * @author : Allen
10 | * e-mail : lygttpod@163.com
11 | * date : 2019/03/19
12 | * desc : 状态布局
13 | *
14 | */
15 |
16 | class StatusLayout : FrameLayout {
17 |
18 | constructor(context: Context) : this(context, null)
19 | constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
20 | constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
21 | initAttrs(attrs)
22 | }
23 |
24 | private fun initAttrs(attrs: AttributeSet?) {
25 |
26 | }
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/status/StatusManager.kt:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget.status
2 |
3 | /**
4 | *
5 | * @author : Allen
6 | * e-mail : lygttpod@163.com
7 | * date : 2019/03/19
8 | * desc :
9 | *
10 | */
11 | object StatusManager {
12 |
13 |
14 | fun setEmptyView(){
15 |
16 | }
17 |
18 | fun setErrorView(){
19 |
20 | }
21 |
22 | fun setContentView() {
23 |
24 | }
25 |
26 | fun setLoadingView() {
27 |
28 | }
29 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/allen/androidcustomview/widget/vote/VoteLayoutAdapter.kt:
--------------------------------------------------------------------------------
1 | package com.allen.androidcustomview.widget.vote
2 |
3 | import android.view.View
4 | import android.view.ViewGroup
5 | import com.allen.androidcustomview.bean.VoteBean
6 | import com.allen.androidcustomview.bean.VoteOption
7 | import java.lang.ref.WeakReference
8 |
9 | /**
10 | *
11 | * @author : Allen
12 | * date : 2019/08/03
13 | * desc :
14 | *
15 | */
16 | class VoteLayoutAdapter(private val viewGroup: ViewGroup) {
17 |
18 | private var viewHolders = mutableListOf