├── .gitignore
├── README.md
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── simple
│ │ └── view
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── java
│ │ └── com
│ │ │ └── simple
│ │ │ └── view
│ │ │ ├── CardActivity.java
│ │ │ ├── CheckViewActivity.java
│ │ │ ├── MainActivity.java
│ │ │ ├── RefreshActivity.java
│ │ │ ├── RefreshSmtFragment.java
│ │ │ ├── TabSmartActivity.java
│ │ │ └── ViewApplication.java
│ └── res
│ │ ├── layout
│ │ ├── ac_card.xml
│ │ ├── ac_checkview.xml
│ │ ├── ac_hfadapter.xml
│ │ ├── ac_message.xml
│ │ ├── ac_permission.xml
│ │ ├── ac_refresh.xml
│ │ ├── ac_tab.xml
│ │ ├── ac_upload.xml
│ │ ├── activity_main.xml
│ │ ├── empty.xml
│ │ ├── fr_tab.xml
│ │ ├── header.xml
│ │ └── layout_smart_refresh.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ ├── ic_launcher_round.png
│ │ └── shadow_134239.9.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── simple
│ └── view
│ └── ExampleUnitTest.java
├── build.gradle
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── library
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ └── main
│ ├── AndroidManifest.xml
│ ├── java
│ └── com
│ │ └── xcheng
│ │ └── view
│ │ ├── EasyView.java
│ │ ├── adapter
│ │ ├── EasyAdapter.java
│ │ ├── EasyFragmentAdapter.java
│ │ ├── EasyHolder.java
│ │ ├── IAdapterDelegate.java
│ │ ├── SpaceDecoration.java
│ │ └── TabInfo.java
│ │ ├── autosize
│ │ ├── AutoSize.java
│ │ └── ResourcesWrapper.java
│ │ ├── controller
│ │ ├── ActionBarSupportActivity.java
│ │ ├── EasyActivity.java
│ │ ├── EasyFragment.java
│ │ ├── EasyPagerActivity.java
│ │ ├── EasyPagerFragment.java
│ │ ├── GlobalLifecycleCallbacks.java
│ │ ├── IEasyView.java
│ │ ├── ILoadingView.java
│ │ ├── IPullRefreshView.java
│ │ ├── SmartRefreshFragment.java
│ │ └── dialog
│ │ │ ├── BottomDialog.java
│ │ │ ├── BottomOptionDialog.java
│ │ │ ├── EasyDialog.java
│ │ │ └── LoadingDialog.java
│ │ ├── divider
│ │ ├── DividerContainer.java
│ │ ├── DividerHelper.java
│ │ ├── DividerLayout.java
│ │ ├── DividerTextView.java
│ │ └── IDividerView.java
│ │ ├── enums
│ │ └── SmartState.java
│ │ ├── round
│ │ ├── RoundButton.java
│ │ ├── RoundDrawableHelper.java
│ │ ├── RoundEditText.java
│ │ ├── RoundFrameLayout.java
│ │ ├── RoundLinearLayout.java
│ │ ├── RoundRelativeLayout.java
│ │ └── RoundTextView.java
│ │ ├── util
│ │ ├── ColorUtil.java
│ │ ├── KeyboardUtil.java
│ │ ├── LocalDisplay.java
│ │ ├── NumberTextWatcher.java
│ │ ├── Router.java
│ │ └── ViewUtil.java
│ │ └── widget
│ │ ├── CheckView.java
│ │ ├── CommonView.java
│ │ ├── FragmentTabHost.java
│ │ ├── GalleryLayoutManager.java
│ │ ├── LoadingView.java
│ │ ├── ProgressView.java
│ │ ├── ScaleTransformer.java
│ │ ├── TopBarLayout.java
│ │ └── smarttab
│ │ ├── SmartTabIndicationInterpolator.java
│ │ ├── SmartTabLayout.java
│ │ ├── SmartTabStrip.java
│ │ └── Utils.java
│ └── res
│ ├── anim
│ ├── ev_dialog_bottom_enter.xml
│ └── ev_dialog_bottom_exit.xml
│ ├── drawable-xhdpi
│ ├── ev_ic_empty_data.png
│ ├── ev_ic_network_error.png
│ └── ic_check_white_18dp.png
│ ├── drawable-xxhdpi
│ ├── ev_enter_arrow.png
│ ├── ev_nav_back_arrow.png
│ └── ic_check_white_18dp.png
│ ├── drawable
│ └── ev_shape_bg_dialog_loading.xml
│ ├── layout
│ ├── ev_commom_view.xml
│ ├── ev_dialog_loading.xml
│ ├── ev_dialog_option_bottom.xml
│ ├── ev_item_module.xml
│ ├── ev_item_text.xml
│ ├── ev_pager.xml
│ ├── ev_smart_refresh.xml
│ └── ev_toolbar.xml
│ └── values
│ ├── attrs.xml
│ ├── colors.xml
│ ├── dimens.xml
│ ├── ids.xml
│ ├── strings.xml
│ ├── styles.xml
│ └── themes.xml
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/workspace.xml
5 | /.idea/libraries
6 | .DS_Store
7 | /.idea
8 | /build
9 | /captures
10 | .externalNativeBuild
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | //noinspection GradleDependency
2 | apply plugin: 'com.android.application'
3 |
4 | android {
5 | compileSdkVersion 28
6 | buildToolsVersion "28.0.3"
7 | lintOptions {
8 | abortOnError false
9 | }
10 | defaultConfig {
11 | applicationId "com.simple.view"
12 | minSdkVersion 14
13 | targetSdkVersion 28
14 | versionCode 1
15 | versionName "1.0"
16 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
17 | }
18 | buildTypes {
19 | release {
20 | minifyEnabled false
21 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
22 | }
23 | }
24 | }
25 | dependencies {
26 | implementation fileTree(include: ['*.jar'], dir: 'libs')
27 | testImplementation 'junit:junit:4.12'
28 | androidTestImplementation 'androidx.test:runner:1.2.0'
29 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
30 | implementation 'androidx.appcompat:appcompat:1.1.0'
31 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
32 | implementation project(':library')
33 | implementation "com.squareup.picasso:picasso:2.71828"
34 | implementation "com.github.bumptech.glide:glide:3.7.0"
35 | implementation 'androidx.recyclerview:recyclerview:1.1.0'
36 | //implementation 'androidx.lifecycle:lifecycle-extensions:2.0.0'
37 | implementation 'com.github.zcweng:switch-button:0.0.3@aar'
38 | // compileOnly 'com.github.Jay-Goo:RangeSeekBar:v3.0.0'
39 | // SmartRefreshLayout需要
40 | implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
41 |
42 | }
43 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/chengxin/Documents/Android/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 |
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/simple/view/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import android.content.Context;
4 | import androidx.test.InstrumentationRegistry;
5 | import androidx.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.simple.view", appContext.getPackageName());
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
19 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
34 |
37 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simple/view/CardActivity.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import android.os.Bundle;
4 | import androidx.annotation.Nullable;
5 | import android.view.View;
6 |
7 | import com.xcheng.view.controller.EasyActivity;
8 | import com.xcheng.view.widget.CheckView;
9 | import com.xcheng.view.widget.CommonView;
10 | import com.xcheng.view.widget.ProgressView;
11 |
12 | public class CardActivity extends EasyActivity {
13 |
14 | public CommonView commonView;
15 | public ProgressView progressView;
16 |
17 | @Override
18 | public int getLayoutId() {
19 | return R.layout.ac_card;
20 | }
21 |
22 | @Override
23 | public void initView(@Nullable Bundle savedInstanceState) {
24 | super.initView(savedInstanceState);
25 | commonView = findViewById(R.id.cv);
26 | commonView.setOnClickListener(new View.OnClickListener() {
27 | @Override
28 | public void onClick(View v) {
29 | int mode = commonView.getMode();
30 | if (mode == CommonView.INPUT) {
31 | commonView.setMode(CommonView.DISPLAY);
32 | } else {
33 | commonView.setMode(CommonView.INPUT);
34 | }
35 | }
36 | });
37 | progressView = findViewById(R.id.progressView);
38 | progressView.setProgressViewTextGenerator(new ProgressView.ProgressViewTextGenerator() {
39 | @Override
40 | public String generateText(ProgressView progressBar, int value, int maxValue) {
41 | return "测试text";
42 | }
43 | });
44 | final CheckView checkView = findViewById(R.id.tv_uncheck);
45 | checkView.setOnClickListener(new View.OnClickListener() {
46 | @Override
47 | public void onClick(View v) {
48 | checkView.toggle();
49 | }
50 | });
51 | final CheckView checkView1 = findViewById(R.id.tv_uncheck1);
52 | checkView1.setOnClickListener(new View.OnClickListener() {
53 | @Override
54 | public void onClick(View v) {
55 | checkView1.toggle();
56 | }
57 | });
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simple/view/CheckViewActivity.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import android.os.Bundle;
4 | import android.util.Log;
5 |
6 | import androidx.annotation.Nullable;
7 |
8 | import com.xcheng.view.controller.EasyActivity;
9 | import com.xcheng.view.widget.CheckView;
10 | import com.xcheng.view.widget.ProgressView;
11 |
12 | public class CheckViewActivity extends EasyActivity {
13 |
14 | public ProgressView progressView;
15 | CheckView cvCheckView;
16 |
17 | @Override
18 | public int getLayoutId() {
19 | return R.layout.ac_checkview;
20 | }
21 |
22 | @Override
23 | public void initView(@Nullable Bundle savedInstanceState) {
24 | super.initView(savedInstanceState);
25 | //cvCheckView=findViewById(R.id.cv_checkView);
26 | Log.e("print", "1\n2\n\n\n3");
27 | Log.e("print", "\n\n\n13");
28 | System.out.println(1);
29 | System.out.println(2);
30 | System.out.println(3);
31 | System.out.println();
32 | System.out.println();
33 | System.out.print(5);
34 | // System.out.println(4);
35 |
36 | System.out.print(6);
37 |
38 | }
39 |
40 | public static void main(String[] args) {
41 | System.out.println(1);
42 | System.out.println(2);
43 | System.out.println(3);
44 | System.out.println();
45 | System.out.println();
46 | System.out.println();
47 | System.out.println();
48 | System.out.println();
49 | System.out.println();
50 | System.out.println();
51 |
52 | System.out.print(5);
53 | // System.out.println(4);
54 |
55 | System.out.print(6);
56 | }
57 |
58 | @Override
59 | protected void onStop() {
60 | super.onStop();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simple/view/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import android.app.ListActivity;
4 | import android.content.Context;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.util.Log;
8 | import android.view.View;
9 | import android.widget.ArrayAdapter;
10 | import android.widget.ListView;
11 |
12 | import androidx.annotation.NonNull;
13 |
14 | import com.scwang.smartrefresh.layout.SmartRefreshLayout;
15 | import com.scwang.smartrefresh.layout.api.DefaultRefreshHeaderCreator;
16 | import com.scwang.smartrefresh.layout.api.RefreshHeader;
17 | import com.scwang.smartrefresh.layout.api.RefreshLayout;
18 | import com.scwang.smartrefresh.layout.constant.SpinnerStyle;
19 | import com.scwang.smartrefresh.layout.header.ClassicsHeader;
20 | import com.xcheng.view.EasyView;
21 | import com.xcheng.view.autosize.AutoSize;
22 | import com.xcheng.view.controller.dialog.BottomOptionDialog;
23 | import com.xcheng.view.util.Router;
24 |
25 | import java.util.Arrays;
26 | import java.util.HashMap;
27 | import java.util.Map;
28 |
29 | import es.dmoral.toasty.Toasty;
30 |
31 | public class MainActivity extends ListActivity {
32 | static {
33 | //设置全局的Header构建器o
34 | SmartRefreshLayout.setDefaultRefreshHeaderCreator(new DefaultRefreshHeaderCreator() {
35 | @NonNull
36 | @Override
37 | public RefreshHeader createRefreshHeader(@NonNull Context context, @NonNull RefreshLayout layout) {
38 | ClassicsHeader header = new ClassicsHeader(context).setSpinnerStyle(SpinnerStyle.Translate);
39 | header.setPrimaryColorId(R.color.ev_holo_red_light);
40 | header.setTextSizeTitle(14);
41 | header.setFinishDuration(200);
42 | //header.setAccentColorId(android.R.color.white);
43 | return header;//指定为经典Header,默认是 贝塞尔雷达Header
44 | }
45 | });
46 |
47 | EasyView.AUTOSIZE = new AutoSize(740, true);
48 | }
49 |
50 | @Override
51 | protected void onCreate(Bundle savedInstanceState) {
52 | super.onCreate(savedInstanceState);
53 | String[] items = getResources().getStringArray(R.array.sample_list);
54 |
55 | ArrayAdapter adapter =
56 | new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, items);
57 | setListAdapter(adapter);
58 |
59 | }
60 |
61 | private Map values = new HashMap<>();
62 |
63 | @Override
64 | protected void onListItemClick(ListView l, View v, int position, long id) {
65 | Toasty.info(this, "点击操作").show();
66 |
67 | switch (position) {
68 | case 0:
69 | // startSignInActivity();
70 | EasyView.success("123");
71 | EasyView.error("456");
72 | EasyView.info("789");
73 | EasyView.warning("123");
74 | break;
75 | case 1:
76 | Router.build(CheckViewActivity.class).navigation(this);
77 | break;
78 | case 3:
79 | break;
80 | case 4:
81 | BottomOptionDialog dialog = new BottomOptionDialog.Builder(this)
82 | // .bottomText(null)
83 | .tipText("请先登录或注册")
84 | .tipTextColor(Color.RED)
85 | .dividerColor(Color.GREEN)
86 | // .bottomTextColor(Color.YELLOW)
87 | // .optionTextColor(Color.RED)
88 | // .dividerColor(Color.GREEN)
89 | // .solidColor(Color.MAGENTA)
90 | // .textSize(30)
91 | // .optionHeight(200)
92 | // .radius(LocalDisplay.dp2px(10))
93 | // .bottomText("底部测试")
94 | .optionTexts("登录", "注册", "忘记密码")
95 | .onSelectListener(new BottomOptionDialog.OnSelectListener() {
96 | @Override
97 | public void onBottomSelect(View view) {
98 | Log.e("print", "底部点击");
99 | }
100 |
101 | @Override
102 | public void onOptionSelect(View view, int position) {
103 | Log.e("print", "列表点击:" + position);
104 | }
105 | })
106 | .create();
107 | dialog.show();
108 | break;
109 | case 5:
110 | startTabActivity();
111 | break;
112 | case 6:
113 | Router.build(RefreshActivity.class).navigation(this);
114 | break;
115 | case 7:
116 | Router.build(CardActivity.class).navigation(this);
117 |
118 | break;
119 | case 8:
120 |
121 | break;
122 | }
123 | }
124 |
125 | private void startTabActivity() {
126 | Router.build(TabSmartActivity.class).navigation(this);
127 | }
128 |
129 | public void testAndroidR() {
130 | try {
131 | Class c = Class.forName("android.R$styleable");
132 | int[] value = (int[]) c.getField("ProgressBar").get(null);
133 |
134 | Log.e("print", "value" + Arrays.toString(value));
135 | Log.e("print", "maxHeight:" + android.R.attr.maxHeight);
136 |
137 | Class c2 = Class.forName("com.android.internal.R$styleable");
138 | int[] value2 = (int[]) c.getField("ProgressBar").get(null);
139 | Object value3 = Class.forName("com.android.internal.R$attr").getField("maxHeight").get(null);
140 |
141 | Log.e("print", "value2" + Arrays.toString(value2));
142 | Log.e("print", "maxHeight2:" + value3);
143 |
144 | } catch (ClassNotFoundException e) {
145 | Log.e("print", "", e);
146 | e.printStackTrace();
147 | } catch (IllegalAccessException e) {
148 | e.printStackTrace();
149 | } catch (NoSuchFieldException e) {
150 | e.printStackTrace();
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simple/view/RefreshActivity.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import com.xcheng.view.controller.EasyActivity;
4 |
5 |
6 | public class RefreshActivity extends EasyActivity {
7 |
8 | @Override
9 | public int getLayoutId() {
10 | return R.layout.ac_refresh;
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simple/view/RefreshSmtFragment.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import android.os.Bundle;
4 | import android.os.Handler;
5 | import android.util.Log;
6 | import android.widget.TextView;
7 |
8 | import androidx.annotation.NonNull;
9 |
10 | import com.xcheng.view.adapter.EasyAdapter;
11 | import com.xcheng.view.adapter.EasyHolder;
12 | import com.xcheng.view.adapter.SpaceDecoration;
13 | import com.xcheng.view.controller.SmartRefreshFragment;
14 | import com.xcheng.view.util.LocalDisplay;
15 |
16 | import java.util.ArrayList;
17 | import java.util.List;
18 |
19 | /**
20 | * Created by chengxin on 2017/9/3.
21 | */
22 | public class RefreshSmtFragment extends SmartRefreshFragment {
23 | @Override
24 | public int getLayoutId() {
25 | return R.layout.layout_smart_refresh;
26 | }
27 |
28 | @Override
29 | public void initView(Bundle savedInstanceState) {
30 | super.initView(savedInstanceState);
31 | mAdapter.setOnItemClickListener(new EasyAdapter.OnItemClickListener() {
32 | @Override
33 | public void onItemClick(EasyHolder holder, int position) {
34 | // ToastLess.showToast(position + "==position:");
35 | // mAdapter.notifyFooter();
36 | int beforeAp = holder.getAdapterPosition();
37 | Log.e("print", "beforeAp:" + beforeAp);
38 | int beforeLp = holder.getLayoutPosition();
39 | Log.e("print", "beforeLp:" + beforeLp);
40 |
41 |
42 | int afterAp = holder.getAdapterPosition();
43 | Log.e("print", "afterAp:" + afterAp);
44 |
45 | int afterLp = holder.getLayoutPosition();
46 | Log.e("print", "afterLp:" + afterLp);
47 | }
48 | });
49 | mRecyclerView.addItemDecoration(new SpaceDecoration(LocalDisplay.dp2px(10)));
50 | }
51 |
52 | @NonNull
53 | @Override
54 | protected Config getConfig() {
55 | return new Config(200, 8);
56 | }
57 |
58 | @Override
59 | public void requestData(final boolean isRefresh) {
60 | new Handler().postDelayed(new Runnable() {
61 | @Override
62 | public void run() {
63 | if (isRefresh) {
64 | List data = new ArrayList<>();
65 | for (int index = 0; index < 8; index++) {
66 | data.add("数据:" + index);
67 | }
68 | refreshView(true, data);
69 | } else {
70 | List data = new ArrayList<>();
71 | if (mAdapter.getDataCount() < 40) {
72 | for (int index = 0; index < 8; index++) {
73 | data.add("数据:" + index);
74 | }
75 | } else {
76 | for (int index = 0; index < 2; index++) {
77 | data.add("数据:" + index);
78 | }
79 | }
80 | refreshView(false, data);
81 | }
82 | }
83 | }, 500);
84 | }
85 |
86 | @NonNull
87 | @Override
88 | public EasyAdapter createAdapter() {
89 | return new EasyAdapter(getContext(), R.layout.ev_item_text) {
90 | @Override
91 | public void convert(EasyHolder holder, String s, int position) {
92 | // Log.e("print", "adapterPosition:" + holder.getAdapterPosition());
93 | TextView textView = (TextView) holder.itemView;
94 | textView.setText(s);
95 | }
96 | };
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simple/view/TabSmartActivity.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import android.os.Bundle;
4 | import androidx.annotation.Nullable;
5 |
6 | import com.xcheng.view.adapter.TabInfo;
7 | import com.xcheng.view.controller.EasyPagerActivity;
8 |
9 | import java.util.List;
10 |
11 |
12 | public class TabSmartActivity extends EasyPagerActivity {
13 |
14 |
15 | @Override
16 | public int getLayoutId() {
17 | return R.layout.ac_tab;
18 | }
19 |
20 | @Override
21 | public void initView(@Nullable Bundle savedInstanceState) {
22 | super.initView(savedInstanceState);
23 | // mIndicator.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
24 | // @Override
25 | // public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
26 | //
27 | // }
28 | //
29 | // @Override
30 | // public void onPageSelected(int position) {
31 | // if (position == 0) {
32 | // mIndicator.setIndicatorColor(Color.YELLOW);
33 | // mIndicator.setIndicatorHeight(20);
34 | // mIndicator.setDividerColor(Color.BLUE);
35 | // } else if (position == 1) {
36 | // mIndicator.setIndicatorColor(Color.GREEN);
37 | // mIndicator.setIndicatorHeight(15);
38 | // mIndicator.setDividerColor(Color.CYAN);
39 | //
40 | //
41 | // } else if (position == 2) {
42 | // mIndicator.setIndicatorColor(Color.RED);
43 | // mIndicator.setIndicatorHeight(10);
44 | // mIndicator.setDividerColor(Color.LTGRAY);
45 | // }
46 | // }
47 | //
48 | // @Override
49 | // public void onPageScrollStateChanged(int state) {
50 | //
51 | // }
52 | // });
53 | }
54 |
55 | @Override
56 | protected void getTabInfos(List tabInfos) {
57 | tabInfos.add(new TabInfo("0", "新闻", RefreshSmtFragment.class));
58 | tabInfos.add(new TabInfo("1", "咨询", RefreshSmtFragment.class));
59 | tabInfos.add(new TabInfo("2", "视频", RefreshSmtFragment.class));
60 | tabInfos.add(new TabInfo("3", "本地", RefreshSmtFragment.class));
61 | tabInfos.add(new TabInfo("4", "小说", RefreshSmtFragment.class));
62 | tabInfos.add(new TabInfo("5", "阅读", RefreshSmtFragment.class));
63 | tabInfos.add(new TabInfo("6", "本地", RefreshSmtFragment.class));
64 | tabInfos.add(new TabInfo("7", "贴吧", RefreshSmtFragment.class));
65 | tabInfos.add(new TabInfo("8", "评论", RefreshSmtFragment.class));
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/app/src/main/java/com/simple/view/ViewApplication.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import android.app.Application;
4 |
5 | import com.xcheng.view.util.LocalDisplay;
6 |
7 | /**
8 | * 创建时间:2020-05-07
9 | * 编写人: chengxin
10 | * 功能描述:
11 | */
12 | public class ViewApplication extends Application {
13 | @Override
14 | public void onCreate() {
15 | super.onCreate();
16 | LocalDisplay.init(this);
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ac_card.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
16 |
17 |
25 |
26 |
33 |
34 |
40 |
41 |
47 |
48 |
53 |
59 |
60 |
66 |
67 |
73 |
74 |
75 |
80 |
81 |
90 |
91 |
99 |
100 |
101 |
102 |
117 |
118 |
133 |
134 |
150 |
151 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ac_hfadapter.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ac_message.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
19 |
20 |
27 |
28 |
39 |
40 |
57 |
58 |
63 |
64 |
65 |
74 |
75 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ac_permission.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
13 |
14 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ac_refresh.xml:
--------------------------------------------------------------------------------
1 |
5 |
6 |
7 |
8 |
13 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ac_tab.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
20 |
21 |
26 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/ac_upload.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/empty.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/fr_tab.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
15 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/header.xml:
--------------------------------------------------------------------------------
1 |
8 |
9 |
16 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/layout_smart_refresh.xml:
--------------------------------------------------------------------------------
1 |
2 |
15 |
16 |
20 |
21 |
28 |
29 |
36 |
37 |
43 |
44 |
51 |
52 |
59 |
60 |
61 |
65 |
66 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/shadow_134239.9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-hdpi/shadow_134239.9.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | EasyView
3 | Settings
4 | jondoe@gmail.com
5 | 123456789
6 | Sign in
7 | Success
8 | Loading..
9 | How are you?
10 | Send
11 | Done
12 | Upload
13 | Beautiful Picture
14 | Uploading
15 | Loading Complete, button is disabled
16 |
17 |
18 | - Action Button Progress/EndLess
19 | - checkView sample
20 | - Generate Button Progress sample
21 | - Button State sample
22 | - 底部弹出Dialog
23 | - Tab导航
24 | - 刷新列表
25 | - 卡片
26 | - Adapter
27 |
28 |
29 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
--------------------------------------------------------------------------------
/app/src/test/java/com/simple/view/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.simple.view;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() throws Exception {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 |
3 | buildscript {
4 | repositories {
5 | google()
6 | jcenter()
7 | }
8 | dependencies {
9 | classpath 'com.android.tools.build:gradle:3.5.4'
10 | //我的jitPack地址
11 | //https://www.jitpack.io/#xchengDroid/EasyView
12 | //https://issuetracker.google.com/issues/37115549
13 | //移动到jitPack详解
14 | //https://www.jianshu.com/p/154ddd631927
15 | //https://blog.csdn.net/zhangfengwu2014/article/details/98478469
16 | // or no service of type org.gradle.internal.Factory
17 | classpath 'com.github.dcendents:android-maven-gradle-plugin:2.1'
18 | // NOTE: Do not place your application dependencies here; they belong
19 | // in the individual module build.gradle files
20 | }
21 | }
22 |
23 | allprojects {
24 | repositories {
25 | google()
26 | jcenter()
27 | maven { url "https://jitpack.io" }
28 | }
29 | tasks.withType(Javadoc) {
30 | options.addStringOption('Xdoclint:none', '-quiet')
31 | options.addStringOption('encoding', 'UTF-8')
32 | }
33 | }
34 |
35 | task clean(type: Delete) {
36 | delete rootProject.buildDir
37 | }
38 |
--------------------------------------------------------------------------------
/gradle.properties:
--------------------------------------------------------------------------------
1 | # Project-wide Gradle settings.
2 |
3 | # IDE (e.g. Android Studio) users:
4 | # Gradle settings configured through the IDE *will override*
5 | # any settings specified in this file.
6 |
7 | # For more details on how to configure your build environment visit
8 | # http://www.gradle.org/docs/current/userguide/build_environment.html
9 |
10 | # Specifies the JVM arguments used for the daemon process.
11 | # The setting is particularly useful for tweaking memory settings.
12 | android.enableJetifier=true
13 | android.useAndroidX=true
14 | org.gradle.jvmargs=-Xmx1536m
15 |
16 | # When configured, Gradle will run in incubating parallel mode.
17 | # This option should only be used with decoupled projects. More details, visit
18 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
19 | # org.gradle.parallel=true
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Thu May 07 11:58:39 CST 2020
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
10 | DEFAULT_JVM_OPTS=""
11 |
12 | APP_NAME="Gradle"
13 | APP_BASE_NAME=`basename "$0"`
14 |
15 | # Use the maximum available, or set MAX_FD != -1 to use that value.
16 | MAX_FD="maximum"
17 |
18 | warn ( ) {
19 | echo "$*"
20 | }
21 |
22 | die ( ) {
23 | echo
24 | echo "$*"
25 | echo
26 | exit 1
27 | }
28 |
29 | # OS specific support (must be 'true' or 'false').
30 | cygwin=false
31 | msys=false
32 | darwin=false
33 | case "`uname`" in
34 | CYGWIN* )
35 | cygwin=true
36 | ;;
37 | Darwin* )
38 | darwin=true
39 | ;;
40 | MINGW* )
41 | msys=true
42 | ;;
43 | esac
44 |
45 | # Attempt to set APP_HOME
46 | # Resolve links: $0 may be a link
47 | PRG="$0"
48 | # Need this for relative symlinks.
49 | while [ -h "$PRG" ] ; do
50 | ls=`ls -ld "$PRG"`
51 | link=`expr "$ls" : '.*-> \(.*\)$'`
52 | if expr "$link" : '/.*' > /dev/null; then
53 | PRG="$link"
54 | else
55 | PRG=`dirname "$PRG"`"/$link"
56 | fi
57 | done
58 | SAVED="`pwd`"
59 | cd "`dirname \"$PRG\"`/" >/dev/null
60 | APP_HOME="`pwd -P`"
61 | cd "$SAVED" >/dev/null
62 |
63 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
64 |
65 | # Determine the Java command to use to start the JVM.
66 | if [ -n "$JAVA_HOME" ] ; then
67 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
68 | # IBM's JDK on AIX uses strange locations for the executables
69 | JAVACMD="$JAVA_HOME/jre/sh/java"
70 | else
71 | JAVACMD="$JAVA_HOME/bin/java"
72 | fi
73 | if [ ! -x "$JAVACMD" ] ; then
74 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
75 |
76 | Please set the JAVA_HOME variable in your environment to match the
77 | location of your Java installation."
78 | fi
79 | else
80 | JAVACMD="java"
81 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
82 |
83 | Please set the JAVA_HOME variable in your environment to match the
84 | location of your Java installation."
85 | fi
86 |
87 | # Increase the maximum file descriptors if we can.
88 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
89 | MAX_FD_LIMIT=`ulimit -H -n`
90 | if [ $? -eq 0 ] ; then
91 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
92 | MAX_FD="$MAX_FD_LIMIT"
93 | fi
94 | ulimit -n $MAX_FD
95 | if [ $? -ne 0 ] ; then
96 | warn "Could not set maximum file descriptor limit: $MAX_FD"
97 | fi
98 | else
99 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
100 | fi
101 | fi
102 |
103 | # For Darwin, add options to specify how the application appears in the dock
104 | if $darwin; then
105 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
106 | fi
107 |
108 | # For Cygwin, switch paths to Windows format before running java
109 | if $cygwin ; then
110 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
111 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
112 | JAVACMD=`cygpath --unix "$JAVACMD"`
113 |
114 | # We build the pattern for arguments to be converted via cygpath
115 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
116 | SEP=""
117 | for dir in $ROOTDIRSRAW ; do
118 | ROOTDIRS="$ROOTDIRS$SEP$dir"
119 | SEP="|"
120 | done
121 | OURCYGPATTERN="(^($ROOTDIRS))"
122 | # Add a user-defined pattern to the cygpath arguments
123 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
124 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
125 | fi
126 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
127 | i=0
128 | for arg in "$@" ; do
129 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
130 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
131 |
132 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
133 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
134 | else
135 | eval `echo args$i`="\"$arg\""
136 | fi
137 | i=$((i+1))
138 | done
139 | case $i in
140 | (0) set -- ;;
141 | (1) set -- "$args0" ;;
142 | (2) set -- "$args0" "$args1" ;;
143 | (3) set -- "$args0" "$args1" "$args2" ;;
144 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
145 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
146 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
147 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
148 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
149 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
150 | esac
151 | fi
152 |
153 | # Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
154 | function splitJvmOpts() {
155 | JVM_OPTS=("$@")
156 | }
157 | eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
158 | JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
159 |
160 | exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
161 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
12 | set DEFAULT_JVM_OPTS=
13 |
14 | set DIRNAME=%~dp0
15 | if "%DIRNAME%" == "" set DIRNAME=.
16 | set APP_BASE_NAME=%~n0
17 | set APP_HOME=%DIRNAME%
18 |
19 | @rem Find java.exe
20 | if defined JAVA_HOME goto findJavaFromJavaHome
21 |
22 | set JAVA_EXE=java.exe
23 | %JAVA_EXE% -version >NUL 2>&1
24 | if "%ERRORLEVEL%" == "0" goto init
25 |
26 | echo.
27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
28 | echo.
29 | echo Please set the JAVA_HOME variable in your environment to match the
30 | echo location of your Java installation.
31 |
32 | goto fail
33 |
34 | :findJavaFromJavaHome
35 | set JAVA_HOME=%JAVA_HOME:"=%
36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
37 |
38 | if exist "%JAVA_EXE%" goto init
39 |
40 | echo.
41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
42 | echo.
43 | echo Please set the JAVA_HOME variable in your environment to match the
44 | echo location of your Java installation.
45 |
46 | goto fail
47 |
48 | :init
49 | @rem Get command-line arguments, handling Windowz variants
50 |
51 | if not "%OS%" == "Windows_NT" goto win9xME_args
52 | if "%@eval[2+2]" == "4" goto 4NT_args
53 |
54 | :win9xME_args
55 | @rem Slurp the command line arguments.
56 | set CMD_LINE_ARGS=
57 | set _SKIP=2
58 |
59 | :win9xME_args_slurp
60 | if "x%~1" == "x" goto execute
61 |
62 | set CMD_LINE_ARGS=%*
63 | goto execute
64 |
65 | :4NT_args
66 | @rem Get arguments from the 4NT Shell from JP Software
67 | set CMD_LINE_ARGS=%$
68 |
69 | :execute
70 | @rem Setup the command line
71 |
72 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
73 |
74 | @rem Execute Gradle
75 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
76 |
77 | :end
78 | @rem End local scope for the variables with windows NT shell
79 | if "%ERRORLEVEL%"=="0" goto mainEnd
80 |
81 | :fail
82 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
83 | rem the _cmd.exe /c_ return code!
84 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
85 | exit /b 1
86 |
87 | :mainEnd
88 | if "%OS%"=="Windows_NT" endlocal
89 |
90 | :omega
91 |
--------------------------------------------------------------------------------
/library/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/library/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 | apply plugin: 'com.github.dcendents.android-maven'
3 | group = 'com.github.xchengDroid'//必加,com.github.<用户名>(也就是你GtiHub上的地址)
4 | android {
5 | compileSdkVersion 28
6 | buildToolsVersion "28.0.3"
7 | resourcePrefix "ev_"
8 | defaultConfig {
9 | minSdkVersion 14
10 | targetSdkVersion 28
11 | versionCode 1
12 | versionName "1.0"
13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
14 | }
15 | buildTypes {
16 | release {
17 | minifyEnabled false
18 | proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
19 | }
20 | }
21 | lintOptions {
22 | abortOnError false
23 | }
24 | }
25 |
26 | dependencies {
27 | api fileTree(dir: 'libs', include: ['*.jar'])
28 | //com.novoda.bintray-release 打包aar上传时,由于依赖其资源无法设置为compileOnly
29 | compileOnly 'androidx.appcompat:appcompat:1.1.0'
30 | //可以设置compileOnly
31 | compileOnly 'androidx.recyclerview:recyclerview:1.1.0'
32 | //api 'com.wang.avi:library:2.1.3'
33 | // api 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.0-andx-14'
34 | // https://www.jianshu.com/p/03ddb527ac92
35 | //必须添加 implementation 'androidx.legacy:legacy-support-core-ui:1.0.0'
36 | api 'com.scwang.smartrefresh:SmartRefreshLayout:1.1.3'
37 | //不添加依赖,只需要@aar,因为appcompat设置compileOnly 导致其依赖的support的classpath无法找到,基于运行时
38 | //api 'com.github.GrenderG:Toasty:1.4.2@aar'
39 | //下面这样剔除support也可以解决classPath问题,主要是应为因为上面compileOnly导致的
40 | api("com.github.GrenderG:Toasty:1.4.2", {
41 | exclude group: 'androidx.appcompat', module: 'appcompat'
42 | })
43 | }
44 |
45 | //---------------------------------------------下面的必加,加上下面的作用是在上传后会带上注释,不然会发现没有注释
46 | // 指定编码
47 | tasks.withType(JavaCompile) {
48 | options.encoding = "UTF-8"
49 | }
50 |
51 | // 打包源码
52 | task sourcesJar(type: Jar) {
53 | from android.sourceSets.main.java.srcDirs
54 | classifier = 'sources'
55 | }
56 |
57 | task javadoc(type: Javadoc) {
58 | failOnError false
59 | source = android.sourceSets.main.java.sourceFiles
60 | classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
61 | classpath += configurations.compile
62 | }
63 |
64 | // 制作文档(Javadoc)
65 | task javadocJar(type: Jar, dependsOn: javadoc) {
66 | classifier = 'javadoc'
67 | from javadoc.destinationDir
68 | }
69 |
70 | artifacts {
71 | archives sourcesJar
72 | archives javadocJar
73 | }
--------------------------------------------------------------------------------
/library/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # By default, the flags in this file are appended to flags specified
3 | # in /Users/chengxin/Documents/Android/android-sdk-macosx/tools/proguard/proguard-android.txt
4 | # You can edit the include path and order by changing the proguardFiles
5 | # directive in build.gradle.
6 | #
7 | # For more details, see
8 | # http://developer.android.com/guide/developing/tools/proguard.html
9 |
10 | # Add any project specific keep options here:
11 |
12 | # If your project uses WebView with JS, uncomment the following
13 | # and specify the fully qualified class name to the JavaScript interface
14 | # class:
15 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
16 | # public *;
17 | #}
18 |
19 | # Uncomment this to preserve the line number information for
20 | # debugging stack traces.
21 | #-keepattributes SourceFile,LineNumberTable
22 |
23 | # If you keep the line number information, uncomment this to
24 | # hide the original source file name.
25 | #-renamesourcefileattribute SourceFile
26 | -keep class com.wang.avi.** { *; }
27 | -keep class com.wang.avi.indicators.** { *; }
28 |
29 |
--------------------------------------------------------------------------------
/library/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/EasyView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.app.Dialog;
5 | import android.content.Context;
6 | import android.os.Handler;
7 | import android.os.Looper;
8 | import android.util.Log;
9 |
10 | import androidx.annotation.NonNull;
11 | import androidx.annotation.StringRes;
12 | import androidx.core.util.Preconditions;
13 |
14 | import com.xcheng.view.autosize.AutoSize;
15 | import com.xcheng.view.controller.dialog.LoadingDialog;
16 | import com.xcheng.view.util.LocalDisplay;
17 |
18 | /**
19 | * Easy工具类,引用全局Context ,提供子线程刷新UI方法等
20 | * Created by chengxin on 2017/8/24.
21 | */
22 | public class EasyView {
23 | private static final Handler HANDLER_UI = new Handler(Looper.getMainLooper());
24 | //默认不适配
25 | public static AutoSize AUTOSIZE = null;
26 | // by default
27 | public static DialogFactory FACTORY = new DialogFactory() {
28 | @NonNull
29 | @Override
30 | public Dialog create(Context context, String fromClazz) {
31 | return new LoadingDialog(context);
32 | }
33 | };
34 |
35 | public static MsgDispatcher DISPATCHER = new MsgDispatcher() {
36 | static final String TAG = "Msg";
37 |
38 | @Override
39 | public void onError(CharSequence msg) {
40 | Log.e(TAG, msg.toString());
41 | }
42 |
43 | @Override
44 | public void onWarning(CharSequence msg) {
45 | Log.w(TAG, msg.toString());
46 | }
47 |
48 | @Override
49 | public void onSuccess(CharSequence msg) {
50 | Log.d(TAG, msg.toString());
51 | }
52 |
53 | @Override
54 | public void onInfo(CharSequence msg) {
55 | Log.d(TAG, msg.toString());
56 | }
57 | };
58 |
59 | private static Context appContext;
60 |
61 | @SuppressLint("RestrictedApi")
62 | public static void init(Context context) {
63 | Preconditions.checkNotNull(context, "context==null");
64 | appContext = context.getApplicationContext();
65 | LocalDisplay.init(appContext);
66 | }
67 |
68 | /**
69 | * 不要用此context做 View 初始化,inflate等操作,否则会使用系统默认的主题样式,如果你自定义了某些样式可能不会被使用。
70 | *
71 | * @return applicationContext 对象
72 | */
73 | public static Context getContext() {
74 | return appContext;
75 | }
76 |
77 | public static String getString(@StringRes int stringId) {
78 | return appContext.getString(stringId);
79 | }
80 |
81 | /**
82 | * @param action the action to run on the UI thread
83 | */
84 | public static void runOnUiThread(Runnable action) {
85 | HANDLER_UI.post(action);
86 | }
87 |
88 | /**
89 | * Returns {@code true} if called on the main thread, {@code false} otherwise.
90 | */
91 | public static boolean isOnMainThread() {
92 | return Looper.myLooper() == Looper.getMainLooper();
93 | }
94 |
95 | public static void error(final CharSequence msg) {
96 | if (isOnMainThread()) {
97 | DISPATCHER.onError(msg);
98 | } else {
99 | runOnUiThread(new Runnable() {
100 | @Override
101 | public void run() {
102 | error(msg);
103 | }
104 | });
105 | }
106 | }
107 |
108 | public static void warning(final CharSequence msg) {
109 | if (isOnMainThread()) {
110 | DISPATCHER.onWarning(msg);
111 | } else {
112 | runOnUiThread(new Runnable() {
113 | @Override
114 | public void run() {
115 | warning(msg);
116 | }
117 | });
118 | }
119 | }
120 |
121 | public static void info(final CharSequence msg) {
122 | if (isOnMainThread()) {
123 | DISPATCHER.onInfo(msg);
124 | } else {
125 | runOnUiThread(new Runnable() {
126 | @Override
127 | public void run() {
128 | info(msg);
129 | }
130 | });
131 | }
132 | }
133 |
134 | public static void success(final CharSequence msg) {
135 | if (isOnMainThread()) {
136 | DISPATCHER.onSuccess(msg);
137 | } else {
138 | runOnUiThread(new Runnable() {
139 | @Override
140 | public void run() {
141 | success(msg);
142 | }
143 | });
144 | }
145 | }
146 |
147 | /**
148 | * 创建LoadingDialog的工厂类
149 | */
150 | public interface DialogFactory {
151 | /**
152 | * 为每隔需要记载的页面创建Dialog
153 | *
154 | * @param context 当前的Context对象
155 | * @param fromClazz 哪个页面需要创建
156 | * @return 加载的Dialog对象
157 | */
158 | @NonNull
159 | Dialog create(Context context, String fromClazz);
160 | }
161 |
162 | /**
163 | * 全局的消息分发
164 | */
165 | public interface MsgDispatcher {
166 |
167 | void onError(CharSequence msg);
168 |
169 | void onWarning(CharSequence msg);
170 |
171 | void onSuccess(CharSequence msg);
172 |
173 | void onInfo(CharSequence msg);
174 | }
175 | }
176 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/adapter/EasyAdapter.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.adapter;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.content.res.Resources;
6 | import android.view.LayoutInflater;
7 | import android.view.View;
8 | import android.view.ViewGroup;
9 |
10 | import androidx.annotation.IntRange;
11 | import androidx.annotation.LayoutRes;
12 | import androidx.annotation.NonNull;
13 | import androidx.annotation.Nullable;
14 | import androidx.core.util.Preconditions;
15 | import androidx.recyclerview.widget.RecyclerView;
16 |
17 | import java.util.ArrayList;
18 | import java.util.Collection;
19 | import java.util.List;
20 |
21 | /**
22 | * RecyclerView 所需Adapter基类,抽离一些基础方法
23 | *
24 | * @param
25 | */
26 | public abstract class EasyAdapter extends RecyclerView.Adapter implements IAdapterDelegate {
27 | private OnItemClickListener mOnItemClickListener;
28 | private OnItemLongClickListener mOnItemLongClickListener;
29 |
30 | protected final Context mContext;
31 | protected final Resources mResources;
32 | protected final LayoutInflater mInflater;
33 | //默认布局ID
34 | @LayoutRes
35 | protected final int mLayoutId;
36 | protected final List mData;
37 |
38 | public EasyAdapter(Context context, @Nullable List data) {
39 | this(context, data, 0);
40 | }
41 |
42 | public EasyAdapter(Context context, @LayoutRes int layoutId) {
43 | this(context, null, layoutId);
44 | }
45 |
46 | public EasyAdapter(Context context, @Nullable List data, @LayoutRes int layoutId) {
47 | if (data == null) {
48 | data = new ArrayList<>();
49 | }
50 | mData = data;
51 | mContext = context;
52 | mResources = context.getResources();
53 | mInflater = LayoutInflater.from(context);
54 | mLayoutId = layoutId;
55 | }
56 |
57 | /**
58 | * 刷新数据
59 | */
60 | public void refresh(@Nullable Collection extends T> newData) {
61 | mData.clear();
62 | if (newData != null && newData.size() > 0) {
63 | /*刷新数据 */
64 | mData.addAll(newData);
65 | }
66 | notifyDataSetChanged();
67 | }
68 |
69 | /**
70 | * notifyItemRangeInserted notifyItemRemoved notifyItemChanged 时必须要保持数据修改和操作的一致性,否则会越位时会报错,
71 | * // boolean validateViewHolderForOffsetPosition(ViewHolder holder),每次都会检测
72 | * if (holder.mPosition < 0 || holder.mPosition >= mAdapter.getItemCount()) {
73 | * throw new IndexOutOfBoundsException("Inconsistency detected. Invalid view holder "
74 | * + "adapter position" + holder);
75 | * }
76 | *
77 | * add new data to the end of mData
78 | *
79 | * @param loadMore the new data collection
80 | */
81 | public void addData(Collection extends T> loadMore) {
82 | addData(getDataCount(), loadMore);
83 | }
84 |
85 | /**
86 | * add new data in to certain locations
87 | *
88 | * @param position the position insert into mData
89 | */
90 | public void addData(@IntRange(from = 0) int position, Collection extends T> loadMore) {
91 | if (loadMore != null && loadMore.size() > 0) {
92 | mData.addAll(position, loadMore);
93 | notifyItemRangeInserted(position, loadMore.size());
94 | }
95 | }
96 |
97 | @Override
98 | public int getItemCount() {
99 | return getDataCount();
100 | }
101 |
102 | /**
103 | * 如果需要覆盖此方法,请重写{@link #getDelegateType(T, int)}
104 | */
105 | @Override
106 | public int getItemViewType(int position) {
107 | return getDelegateType(getItem(position), position);
108 | }
109 |
110 | /**
111 | * 如果需要覆盖此方法,请重写{@link #getDelegateView(ViewGroup, int)},
112 | * holder 在onCreateViewHolder 和 onBindViewHolder时 holder.itemView no parent
113 | */
114 | @SuppressLint("RestrictedApi")
115 | @NonNull
116 | @Override
117 | public EasyHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
118 | View itemView = getDelegateView(parent, viewType);
119 | Preconditions.checkState(itemView != null, "you can set a layoutId in construct method or override getDelegateView(parent,viewType) and return a NonNull itemView");
120 | EasyHolder holder = new EasyHolder(itemView);
121 | bindClickListener(holder);
122 | return holder;
123 | }
124 |
125 | /**
126 | * 如果需要覆盖此方法,请重写{@link #convert(RecyclerView.ViewHolder, T, int)}}
127 | */
128 | @Override
129 | public void onBindViewHolder(@NonNull EasyHolder holder, int position) {
130 | convert(holder, getItem(position), position);
131 | }
132 |
133 | @Override
134 | public int getDelegateType(T t, int position) {
135 | return 0;
136 | }
137 |
138 | @Override
139 | public View getDelegateView(ViewGroup parent, int viewType) {
140 | return mLayoutId != 0 ? inflater(mLayoutId, parent) : null;
141 | }
142 |
143 | public View inflater(int layoutId, ViewGroup parent) {
144 | return mInflater.inflate(layoutId, parent, false);
145 | }
146 |
147 | @Override
148 | public long getItemId(int position) {
149 | return position;
150 | }
151 |
152 | /**
153 | * @param position 在mData列表中的位置,注意如果有header或camera按钮等的话处理后调用
154 | * @return bindData
155 | */
156 | public final T getItem(int position) {
157 | if (position >= 0 && position < mData.size()) {
158 | return mData.get(position);
159 | }
160 | return null;
161 | }
162 |
163 | /**
164 | * 获取mData数据的长度
165 | **/
166 | public final int getDataCount() {
167 | return mData.size();
168 | }
169 |
170 | public List getData() {
171 | return mData;
172 | }
173 |
174 | /**
175 | * mData数据是否为空
176 | *
177 | * @return
178 | */
179 | public final boolean isEmpty() {
180 | return mData == null || mData.size() == 0;
181 | }
182 |
183 | private void bindClickListener(final EasyHolder easyHolder) {
184 | if (mOnItemClickListener != null) {
185 | easyHolder.itemView.setOnClickListener(new View.OnClickListener() {
186 | @Override
187 | public void onClick(View v) {
188 | if (mOnItemClickListener != null) {
189 | mOnItemClickListener.onItemClick(easyHolder, easyHolder.getAdapterPosition());
190 | }
191 | }
192 | });
193 | }
194 | if (mOnItemLongClickListener != null) {
195 | easyHolder.itemView.setOnLongClickListener(new View.OnLongClickListener() {
196 | @Override
197 | public boolean onLongClick(View v) {
198 | return mOnItemLongClickListener != null &&
199 | mOnItemLongClickListener.onItemLongClick(easyHolder, easyHolder.getAdapterPosition());
200 | }
201 | });
202 | }
203 | }
204 |
205 | public interface OnItemClickListener {
206 | void onItemClick(EasyHolder holder, int adapterPosition);
207 | }
208 |
209 | public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
210 | this.mOnItemClickListener = onItemClickListener;
211 | }
212 |
213 | public interface OnItemLongClickListener {
214 | boolean onItemLongClick(EasyHolder holder, int adapterPosition);
215 | }
216 |
217 | public void setOnItemLongClickListener(OnItemLongClickListener onItemLongClickListener) {
218 | this.mOnItemLongClickListener = onItemLongClickListener;
219 | }
220 | }
221 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/adapter/EasyFragmentAdapter.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.adapter;
2 |
3 | import android.content.Context;
4 | import androidx.annotation.Nullable;
5 | import androidx.fragment.app.Fragment;
6 | import androidx.fragment.app.FragmentManager;
7 | import androidx.fragment.app.FragmentPagerAdapter;
8 | import androidx.fragment.app.FragmentTransaction;
9 | import androidx.viewpager.widget.PagerAdapter;
10 | import android.view.ViewGroup;
11 |
12 | import java.util.List;
13 |
14 | public class EasyFragmentAdapter extends FragmentPagerAdapter {
15 | private Context mContext;
16 | private final List mTabInfos;
17 | private FragmentManager mFragmentManager;
18 |
19 | public EasyFragmentAdapter(FragmentManager fm, Context context,
20 | List tabs) {
21 | super(fm);
22 | if (tabs == null) {
23 | throw new IllegalArgumentException(
24 | "tabs can not be null,please initialized it");
25 | }
26 | mFragmentManager = fm;
27 | mTabInfos = tabs;
28 | mContext = context;
29 | }
30 |
31 | public TabInfo getTabInfo(int position) {
32 | return mTabInfos.get(position);
33 | }
34 |
35 | /**
36 | * called {@link #notifyDataSetChanged()} if tabInfos has changed
37 | */
38 | public List getTabInfos() {
39 | return mTabInfos;
40 | }
41 |
42 | @Override
43 | public int getCount() {
44 | // TODO Auto-generated method stub
45 | return mTabInfos.size();
46 | }
47 |
48 |
49 | @Override
50 | public int getItemPosition(Object object) {
51 | /*每次 notifyDataSetChanged的时候刷新**/
52 | return PagerAdapter.POSITION_NONE;
53 | }
54 |
55 | @Override
56 | public Fragment getItem(int position) {
57 | TabInfo info = mTabInfos.get(position);
58 | return Fragment.instantiate(mContext, info.clazz.getName(), info.args);
59 | }
60 |
61 | @Override
62 | public CharSequence getPageTitle(int position) {
63 | return mTabInfos.get(position).title;
64 | }
65 |
66 | @Override
67 | public void destroyItem(ViewGroup container, int position, Object object) {
68 | // 注释自带的销毁方法防止页面被销毁
69 | super.destroyItem(container, position, object);
70 | }
71 |
72 |
73 | public void removeFragment(ViewGroup container, int index, boolean allowingStateLoss) {
74 | Fragment fragment = findFragment(container, index);
75 | if (fragment == null)
76 | return;
77 | FragmentTransaction ft = mFragmentManager.beginTransaction();
78 | ft.remove(fragment);
79 | if (allowingStateLoss) {
80 | ft.commitAllowingStateLoss();
81 | } else {
82 | ft.commit();
83 | }
84 | mFragmentManager.executePendingTransactions();
85 | }
86 |
87 | public void removeAllFragment(ViewGroup container, boolean allowingStateLoss) {
88 | for (int index = 0; index < getCount(); index++) {
89 | removeFragment(container, index, allowingStateLoss);
90 | }
91 | }
92 |
93 | /**
94 | * @param container ViewPager
95 | * @param position 位置
96 | * @return Fragment
97 | */
98 | @Nullable
99 | public Fragment findFragment(ViewGroup container, int position) {
100 | String tag = "android:switcher:" + container.getId() + ":" + getItemId(position);
101 | return mFragmentManager.findFragmentByTag(tag);
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/adapter/EasyHolder.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.adapter;
2 |
3 | import android.content.Context;
4 | import android.graphics.Bitmap;
5 | import android.graphics.drawable.Drawable;
6 | import android.os.Build;
7 | import androidx.annotation.ColorInt;
8 | import androidx.annotation.ColorRes;
9 | import androidx.annotation.DimenRes;
10 | import androidx.annotation.DrawableRes;
11 | import androidx.annotation.IdRes;
12 | import androidx.annotation.NonNull;
13 | import androidx.annotation.StringRes;
14 | import androidx.core.content.ContextCompat;
15 | import androidx.recyclerview.widget.RecyclerView;
16 | import android.text.util.Linkify;
17 | import android.util.SparseArray;
18 | import android.view.View;
19 | import android.view.ViewGroup;
20 | import android.view.animation.AlphaAnimation;
21 | import android.widget.ImageView;
22 | import android.widget.TextView;
23 |
24 | /**
25 | * 简单的ViewHolder对象
26 | * Created by cc on 2016/10/8.
27 | */
28 | public class EasyHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
29 | /**
30 | * Views indexed with their IDs
31 | */
32 | private final SparseArray mViews;
33 |
34 | public EasyHolder(View itemView) {
35 | super(itemView);
36 | this.mViews = new SparseArray<>();
37 | }
38 |
39 | public Context getContext() {
40 | return itemView.getContext();
41 | }
42 |
43 | /**
44 | * @param itemView 获取itemView的 在adapter中的位置
45 | */
46 | public static int getAdapterPosition(@NonNull View itemView) {
47 | RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) itemView.getLayoutParams();
48 | return lp.getViewAdapterPosition();
49 | }
50 |
51 | @Override
52 | public void onClick(View v) {
53 |
54 | }
55 |
56 | /**
57 | * 返回itemView最外层容器
58 | **/
59 | public ViewGroup getRootView() {
60 | if (itemView instanceof ViewGroup) {
61 | return (ViewGroup) itemView;
62 | }
63 | throw new IllegalStateException("itemView is not a ViewGroup");
64 | }
65 |
66 | public String getString(@StringRes int id) {
67 | return getContext().getString(id);
68 | }
69 |
70 | public int getColor(@ColorRes int colorRes) {
71 | return ContextCompat.getColor(getContext(), colorRes);
72 | }
73 |
74 | public int getDimen(@DimenRes int id) {
75 | return itemView.getResources().getDimensionPixelSize(id);
76 | }
77 |
78 | @SuppressWarnings("unchecked")
79 | public T getView(@IdRes int viewId) {
80 | View view = mViews.get(viewId);
81 | if (view == null) {
82 | view = itemView.findViewById(viewId);
83 | mViews.put(viewId, view);
84 | }
85 | return (T) view;
86 | }
87 |
88 | public EasyHolder setOnClickListener(@IdRes int viewId, View.OnClickListener l) {
89 | View view = getView(viewId);
90 | view.setOnClickListener(l);
91 | return this;
92 | }
93 |
94 | public EasyHolder setOnLongClickListener(@IdRes int viewId, View.OnLongClickListener l) {
95 | View view = getView(viewId);
96 | view.setOnLongClickListener(l);
97 | return this;
98 | }
99 |
100 | /**
101 | * Sets the tag of the view.
102 | *
103 | * @param viewId The view id.
104 | * @param key The key of tag;
105 | * @param tag The tag;
106 | * @return The BaseViewHolder for chaining.
107 | */
108 | public EasyHolder setTag(@IdRes int viewId, int key, Object tag) {
109 | View view = getView(viewId);
110 | view.setTag(key, tag);
111 | return this;
112 | }
113 |
114 | /**
115 | * Will set the text of a TextView.
116 | *
117 | * @param viewId The view id.
118 | * @param value The text to put in the text view.
119 | * @return The BaseViewHolder for chaining.
120 | */
121 | public EasyHolder setText(@IdRes int viewId, CharSequence value) {
122 | TextView view = getView(viewId);
123 | view.setText(value);
124 | return this;
125 | }
126 |
127 | public EasyHolder setText(@IdRes int viewId, @StringRes int strId) {
128 | TextView view = getView(viewId);
129 | view.setText(strId);
130 | return this;
131 | }
132 |
133 | /**
134 | * Add links into a TextView.
135 | *
136 | * @param viewId The id of the TextView to linkify.
137 | * @return The EasyHolder for chaining.
138 | */
139 | public EasyHolder linkify(@IdRes int viewId) {
140 | TextView view = getView(viewId);
141 | Linkify.addLinks(view, Linkify.ALL);
142 | return this;
143 | }
144 |
145 | /**
146 | * Will set the image of an ImageView from a resource id.
147 | *
148 | * @param viewId The view id.
149 | * @param imageResId The image resource id.
150 | * @return The BaseViewHolder for chaining.
151 | */
152 | public EasyHolder setImageResource(@IdRes int viewId, @DrawableRes int imageResId) {
153 | ImageView view = getView(viewId);
154 | view.setImageResource(imageResId);
155 | return this;
156 | }
157 |
158 | /**
159 | * Will set background color of a view.
160 | *
161 | * @param viewId The view id.
162 | * @param color A color, not a resource id.
163 | * @return The BaseViewHolder for chaining.
164 | */
165 | public EasyHolder setBackgroundColor(@IdRes int viewId, int color) {
166 | View view = getView(viewId);
167 | view.setBackgroundColor(color);
168 | return this;
169 | }
170 |
171 | /**
172 | * Will set background of a view.
173 | *
174 | * @param viewId The view id.
175 | * @param backgroundRes A resource to use as a background.
176 | * @return The BaseViewHolder for chaining.
177 | */
178 | public EasyHolder setBackgroundRes(@IdRes int viewId, @DrawableRes int backgroundRes) {
179 | View view = getView(viewId);
180 | view.setBackgroundResource(backgroundRes);
181 | return this;
182 | }
183 |
184 | /**
185 | * Will set text color of a TextView.
186 | *
187 | * @param viewId The view id.
188 | * @param textColor The text color (not a resource id).
189 | * @return The BaseViewHolder for chaining.
190 | */
191 | public EasyHolder setTextColor(@IdRes int viewId, @ColorInt int textColor) {
192 | TextView view = getView(viewId);
193 | view.setTextColor(textColor);
194 | return this;
195 | }
196 |
197 | public EasyHolder setTextColorRes(int viewId, @ColorRes int colorId) {
198 | TextView view = getView(viewId);
199 | view.setTextColor(ContextCompat.getColorStateList(getContext(), colorId));
200 | return this;
201 | }
202 |
203 | /**
204 | * Will set the image of an ImageView from a drawable.
205 | *
206 | * @param viewId The view id.
207 | * @param drawable The image drawable.
208 | * @return The BaseViewHolder for chaining.
209 | */
210 | public EasyHolder setImageDrawable(@IdRes int viewId, Drawable drawable) {
211 | ImageView view = getView(viewId);
212 | view.setImageDrawable(drawable);
213 | return this;
214 | }
215 |
216 | /**
217 | * Add an action to set the image of an image view. Can be called multiple times.
218 | */
219 | public EasyHolder setImageBitmap(@IdRes int viewId, Bitmap bitmap) {
220 | ImageView view = getView(viewId);
221 | view.setImageBitmap(bitmap);
222 | return this;
223 | }
224 |
225 | /**
226 | * Add an action to set the alpha of a view. Can be called multiple times.
227 | * Alpha between 0-1.
228 | */
229 | public EasyHolder setAlpha(@IdRes int viewId, float value) {
230 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
231 | getView(viewId).setAlpha(value);
232 | } else {
233 | // Pre-honeycomb hack to set Alpha value
234 | AlphaAnimation alpha = new AlphaAnimation(value, value);
235 | alpha.setDuration(0);
236 | alpha.setFillAfter(true);
237 | getView(viewId).startAnimation(alpha);
238 | }
239 | return this;
240 | }
241 |
242 | public EasyHolder setVisible(@IdRes int viewId, int visibility) {
243 | View view = getView(viewId);
244 | view.setVisibility(visibility);
245 | return this;
246 | }
247 |
248 | public EasyHolder setEnabled(@IdRes int viewId, boolean enabled) {
249 | View view = getView(viewId);
250 | view.setEnabled(enabled);
251 | return this;
252 | }
253 | }
254 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/adapter/IAdapterDelegate.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.adapter;
2 |
3 | import android.view.View;
4 | import android.view.ViewGroup;
5 |
6 | import androidx.recyclerview.widget.RecyclerView;
7 |
8 | /**
9 | * 抽离Adapter适配器接口
10 | * Created by chengxin on 2017/9/5.
11 | */
12 | interface IAdapterDelegate {
13 | /**
14 | * 获取 itemView布局,这里不直接用getLayoutId的好处是可以兼容在代码里面构建的View,
15 | * 而且可以做一些不用重复初始化的设置,如设置背景、字体、监听等,
16 | * 无需在绑定数据复用的时候重新设置*
17 | *
18 | * @return itemView
19 | * @see RecyclerView.Adapter#onBindViewHolder(RecyclerView.ViewHolder, int)
20 | */
21 | View getDelegateView(ViewGroup parent, int viewType);
22 |
23 | /**
24 | * 获取 对应position中的View类型
25 | *
26 | * @param t 对应位置上的数据
27 | * @param position position in data
28 | * @return viewType
29 | * @see RecyclerView.Adapter#getItemViewType(int)
30 | */
31 | int getDelegateType(T t, int position);
32 |
33 | /**
34 | * 绑定列表数据
35 | *
36 | * @param position position in data
37 | * @see RecyclerView.Adapter#onBindViewHolder(RecyclerView.ViewHolder, int)
38 | */
39 | void convert(VH holder, T t, int position);
40 |
41 | }
42 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/adapter/SpaceDecoration.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.adapter;
2 |
3 | import android.graphics.Canvas;
4 | import android.graphics.Color;
5 | import android.graphics.Paint;
6 | import android.graphics.Rect;
7 | import android.view.View;
8 |
9 | import androidx.annotation.ColorInt;
10 | import androidx.recyclerview.widget.RecyclerView;
11 |
12 | public class SpaceDecoration extends RecyclerView.ItemDecoration {
13 | private int mSpaceColor;
14 | private int mSpaceSize;
15 | private boolean hasEndSpace;
16 | private Paint mPaint;
17 |
18 | public SpaceDecoration(int spaceSize) {
19 | this(Color.parseColor("#dae1e5"), spaceSize);
20 | }
21 |
22 | public SpaceDecoration(@ColorInt int spaceColor, int spaceSize) {
23 | this(spaceColor, spaceSize, false);
24 | }
25 |
26 | /**
27 | * @param spaceColor 分割线颜色
28 | * @param spaceSize 分割线高度
29 | * @param hasEndSpace 最后一项是否有分割线
30 | */
31 | public SpaceDecoration(@ColorInt int spaceColor, int spaceSize, boolean hasEndSpace) {
32 | this.mSpaceColor = spaceColor;
33 | this.mSpaceSize = spaceSize;
34 | this.hasEndSpace = hasEndSpace;
35 | init();
36 | }
37 |
38 | private void init() {
39 | mPaint = new Paint();
40 | mPaint.setColor(mSpaceColor);
41 | mPaint.setStrokeWidth(mSpaceSize);
42 | }
43 |
44 | @Override
45 | public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
46 | int position = parent.getChildAdapterPosition(view);
47 | if (hasEndSpace || position != parent.getAdapter().getItemCount() - 1) {
48 | outRect.set(0, 0, 0, mSpaceSize);
49 | }
50 | }
51 |
52 | @Override
53 | public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
54 | final int childCount = parent.getChildCount();
55 | final int itemCount = parent.getAdapter().getItemCount();
56 | for (int i = 0; i < childCount; i++) {
57 | View view = parent.getChildAt(i);
58 | int position = parent.getChildAdapterPosition(view);
59 | if (hasEndSpace || position != itemCount - 1)
60 | c.drawLine(0, view.getBottom() + mSpaceSize / 2, parent.getRight(), view.getBottom() + mSpaceSize / 2, mPaint);
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/adapter/TabInfo.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.adapter;
2 |
3 | import android.os.Bundle;
4 | import androidx.annotation.DrawableRes;
5 |
6 | public final class TabInfo {
7 | public final CharSequence title;
8 | public final String tag;
9 | public final Class> clazz;
10 | public final Bundle args;
11 |
12 | public final int iconResId;
13 | /**
14 | * Tab背景
15 | */
16 | public final int bgResId;
17 |
18 | public TabInfo(String _tag, @DrawableRes int _iconResId, CharSequence _title, @DrawableRes int _bgResId, Class> _clazz, Bundle bundle) {
19 | tag = _tag;
20 | title = _title;
21 | clazz = _clazz;
22 | iconResId = _iconResId;
23 | bgResId = _bgResId;
24 | args = bundle != null ? bundle : new Bundle();
25 | args.putString("tag", _tag);
26 | args.putCharSequence("title", _title);
27 | }
28 |
29 | public TabInfo(String _tag, CharSequence _title, Class> _clazz, Bundle _args) {
30 | this(_tag, 0, _title, 0, _clazz, _args);
31 | }
32 |
33 | public TabInfo(String _tag, CharSequence _title, Class> _clazz) {
34 | this(_tag, 0, _title, 0, _clazz, null);
35 | }
36 | /**
37 | * 如果没有DrawableRes 传入 0
38 | *
39 | * @param _iconResId icon资源
40 | */
41 | public TabInfo(String _tag, @DrawableRes int _iconResId, CharSequence _title, Class> _clazz) {
42 | this(_tag, _iconResId, _title, 0, _clazz, null);
43 | }
44 |
45 | /**
46 | * 如果没有DrawableRes 传入 0
47 | *
48 | * @param _bgResId 背景资源
49 | */
50 | public TabInfo(String _tag, CharSequence _title, @DrawableRes int _bgResId, Class> _clazz) {
51 | this(_tag, 0, _title, _bgResId, _clazz, null);
52 | }
53 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/autosize/AutoSize.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.autosize;
2 |
3 | /**
4 | * 创建时间:2018/11/12
5 | * 编写人: chengxin
6 | * 功能描述:适配实体类
7 | */
8 | public class AutoSize {
9 | /**
10 | * 默认的设计尺寸
11 | * >0 设置宽度
12 | * <0 设置高度
13 | */
14 | public final float designSizeInDp;
15 | public final boolean isSupportSp;
16 |
17 | /**
18 | * @param designSizeInDp 设计宽度货高度
19 | * @param isSupportSp 是否支持sp
20 | */
21 | public AutoSize(float designSizeInDp, boolean isSupportSp) {
22 | if (designSizeInDp == 0) {
23 | throw new IllegalArgumentException("designSizeInDp==0");
24 | }
25 | this.designSizeInDp = designSizeInDp;
26 | this.isSupportSp = isSupportSp;
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/autosize/ResourcesWrapper.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.autosize;
2 |
3 | import android.content.res.Resources;
4 | import android.util.DisplayMetrics;
5 |
6 | /**
7 | * 今日头条的适配方案
8 | */
9 | public class ResourcesWrapper extends Resources {
10 | private final AutoSize autoSize;
11 | private float targetDensity;
12 | private float targetScaledDensity;
13 | private int targetDensityDpi;
14 |
15 | public ResourcesWrapper(Resources resources, AutoSize autoSize) {
16 | super(resources.getAssets(), resources.getDisplayMetrics(), resources.getConfiguration());
17 | this.autoSize = autoSize;
18 | }
19 |
20 | @Override
21 | public DisplayMetrics getDisplayMetrics() {
22 | DisplayMetrics displayMetrics = super.getDisplayMetrics();
23 | initValue(displayMetrics);
24 | autoSize(displayMetrics);
25 | return displayMetrics;
26 | }
27 |
28 | private void initValue(DisplayMetrics displayMetrics) {
29 | if (targetDensity == 0) {
30 | float nonCompatDensity = displayMetrics.density;
31 | float nonCompatScaledDensity = displayMetrics.scaledDensity;
32 | float designSizeInDp = autoSize.designSizeInDp;
33 | if (designSizeInDp > 0) {
34 | targetDensity = displayMetrics.widthPixels / designSizeInDp;
35 | } else {
36 | targetDensity = displayMetrics.heightPixels / -designSizeInDp;
37 | }
38 | targetScaledDensity = targetDensity * (nonCompatScaledDensity / nonCompatDensity);
39 | targetDensityDpi = (int) (160 * targetDensity);
40 | }
41 | }
42 |
43 | private void autoSize(DisplayMetrics displayMetrics) {
44 | displayMetrics.density = targetDensity;
45 | displayMetrics.densityDpi = targetDensityDpi;
46 | if (autoSize.isSupportSp) {
47 | displayMetrics.scaledDensity = targetScaledDensity;
48 | }
49 | }
50 | }
51 |
52 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/ActionBarSupportActivity.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.view.View;
4 | import android.widget.TextView;
5 |
6 | import androidx.annotation.LayoutRes;
7 | import androidx.appcompat.app.AppCompatActivity;
8 | import androidx.appcompat.widget.Toolbar;
9 |
10 | import com.xcheng.view.R;
11 |
12 | /**
13 | * 通用的Toolbar 基类,
14 | * Toolbar id为ev_id_toolBar,
15 | * 标题TextView id为ev_id_titleView
16 | * Created by chengxin on 2017/5/2.
17 | */
18 | public abstract class ActionBarSupportActivity extends AppCompatActivity {
19 | protected Toolbar mToolbar;
20 | protected TextView mTitleView;
21 |
22 | @Override
23 | public void setContentView(@LayoutRes int layoutResID) {
24 | super.setContentView(layoutResID);
25 | mTitleView = findViewById(R.id.ev_id_titleView);
26 | mToolbar = findViewById(R.id.ev_id_toolBar);
27 | if (mToolbar != null) {
28 | if (isSupportActionBar()) {
29 | setSupportActionBar(mToolbar);
30 | //noinspection ConstantConditions
31 | getSupportActionBar().setDisplayShowTitleEnabled(false);
32 | }
33 | if (mToolbar.getNavigationIcon() != null) {
34 | //需要在setSupportActionBar之后执行,否则会被onOptionsItemSelected覆盖
35 | //默认的操作,如果需要可由子类覆盖
36 | mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
37 | @Override
38 | public void onClick(View v) {
39 | finish();
40 | }
41 | });
42 | }
43 | }
44 | }
45 |
46 | /***
47 | * ViewCompat.postOnAnimation(mDecorToolbar.getViewGroup(), mMenuInvalidator); 推送执行
48 | * onCreateOptionsMenu(Menu menu) 方法,该方法执行之前会把Menu清除
49 | * 所以在initView里面执行 mToolbar.inflateMenu后又被清除
50 | * 故添加是否设置支持ActionBar供子类动态去执行
51 | */
52 | protected boolean isSupportActionBar() {
53 | return true;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/EasyActivity.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.content.Intent;
6 | import android.content.res.Configuration;
7 | import android.content.res.Resources;
8 | import android.os.Bundle;
9 | import android.util.DisplayMetrics;
10 | import android.view.MotionEvent;
11 | import android.view.View;
12 |
13 | import androidx.annotation.Nullable;
14 |
15 | import com.xcheng.view.EasyView;
16 | import com.xcheng.view.autosize.AutoSize;
17 | import com.xcheng.view.autosize.ResourcesWrapper;
18 | import com.xcheng.view.util.KeyboardUtil;
19 |
20 | /**
21 | * 所有Activity的基类
22 | *
23 | * @author xincheng
24 | */
25 | public abstract class EasyActivity extends ActionBarSupportActivity implements IEasyView {
26 |
27 | private Dialog mLoadingDialog;
28 | private Resources mResources;
29 |
30 | @Override
31 | protected void onCreate(@Nullable Bundle savedInstanceState) {
32 | super.onCreate(savedInstanceState);
33 | //兼容重写onCreate
34 | if (getLayoutId() != 0) {
35 | setContentView(getLayoutId());
36 | initData();
37 | initView(savedInstanceState);
38 | setListener();
39 | }
40 | }
41 |
42 | @Override
43 | public void initData() {
44 |
45 | }
46 |
47 | @Override
48 | public void initView(@Nullable Bundle savedInstanceState) {
49 |
50 | }
51 |
52 | @Override
53 | public void setListener() {
54 |
55 | }
56 |
57 |
58 | @Override
59 | public void onClick(View v) {
60 | // TODO Auto-generated method stub
61 |
62 | }
63 |
64 | @Override
65 | public boolean dispatchTouchEvent(MotionEvent ev) {
66 | if (isHideKeyboardOnTouchOutSide()) {
67 | switch (ev.getAction()) {
68 | case MotionEvent.ACTION_DOWN:
69 | View view = getCurrentFocus();
70 | if (KeyboardUtil.isHideInput(view, ev)) {
71 | KeyboardUtil.hide(view);
72 | }
73 | break;
74 | default:
75 | break;
76 | }
77 | }
78 | try {
79 | //java.lang.IllegalArgumentException:pointerIndex out of range
80 | return super.dispatchTouchEvent(ev);
81 | } catch (IllegalArgumentException e) {
82 | return false;
83 | }
84 | }
85 |
86 | protected boolean isHideKeyboardOnTouchOutSide() {
87 | return false;
88 | }
89 |
90 | /**
91 | * 从传递的Intent中获取 根据
92 | * bundle获取值 获取从上一个界面传递的信息
93 | */
94 | protected Bundle getBundle() {
95 | return getIntent().getExtras();
96 | }
97 |
98 | public void showLoading() {
99 | if (mLoadingDialog == null) {
100 | mLoadingDialog = EasyView.FACTORY.create(this, getClass().getName());
101 | }
102 | mLoadingDialog.show();
103 | }
104 |
105 | public void hideLoading() {
106 | if (mLoadingDialog != null) {
107 | mLoadingDialog.dismiss();
108 | }
109 | }
110 |
111 | @Override
112 | public Resources getResources() {
113 | if (mResources == null) {
114 | final AutoSize autoSize = getAutoSize();
115 | if (autoSize != null) {
116 | mResources = new ResourcesWrapper(super.getResources(), autoSize);
117 | }
118 | }
119 | return mResources != null ? mResources : super.getResources();
120 | }
121 |
122 | @Override
123 | public void onConfigurationChanged(Configuration newConfig) {
124 | super.onConfigurationChanged(newConfig);
125 | if (mResources != null) {
126 | // The real (and thus managed) resources object was already updated
127 | // by ResourcesManager, so pull the current metrics from there.
128 | final DisplayMetrics newMetrics = super.getResources().getDisplayMetrics();
129 | mResources.updateConfiguration(newConfig, newMetrics);
130 | }
131 | }
132 |
133 | /**
134 | * 子类可重写适配
135 | **/
136 | @Nullable
137 | protected AutoSize getAutoSize() {
138 | return EasyView.AUTOSIZE;
139 | }
140 |
141 | @Override
142 | public void showMessage(CharSequence text) {
143 | EasyView.info(text);
144 | }
145 |
146 | @Override
147 | protected void onActivityResult(int requestCode, int resultCode, Intent data) {
148 | super.onActivityResult(requestCode, resultCode, data);
149 | if (resultCode == RESULT_OK)
150 | onActivityResultOk(requestCode, data);
151 | }
152 |
153 | //统一setResult里面的响应成功码为Activity.RESULT_OK,这样会少很多的代码
154 | protected void onActivityResultOk(int requestCode, Intent data) {
155 |
156 | }
157 |
158 | protected final Context getContext() {
159 | return this;
160 | }
161 |
162 | @Override
163 | protected void onDestroy() {
164 | super.onDestroy();
165 | hideLoading();
166 | }
167 | }
168 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/EasyFragment.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.app.Activity;
4 | import android.app.Dialog;
5 | import android.content.Intent;
6 | import android.os.Bundle;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 |
11 | import androidx.annotation.IdRes;
12 | import androidx.annotation.NonNull;
13 | import androidx.annotation.Nullable;
14 | import androidx.fragment.app.Fragment;
15 | import androidx.lifecycle.MutableLiveData;
16 | import androidx.lifecycle.Observer;
17 |
18 | import com.xcheng.view.EasyView;
19 |
20 | /**
21 | * 基础Fragment,提供公有方法
22 | * 1、支持缓存RootView
23 | * 2、支持ViewPager懒加载
24 | *
25 | * @author xincheng @date:2014-8-4
26 | */
27 | public abstract class EasyFragment extends Fragment implements IEasyView {
28 | /**
29 | * 需要缓存的RootView;
30 | */
31 | private View mRootView;
32 | private Dialog mLoadingDialog;
33 | public final MutableLiveData mLoadingLiveData = new MutableLiveData<>();
34 |
35 | {
36 | mLoadingLiveData.observe(this, new Observer() {
37 | @Override
38 | public void onChanged(Boolean aBoolean) {
39 | if (aBoolean) {
40 | showLoading();
41 | } else {
42 | hideLoading();
43 | }
44 | }
45 | });
46 | }
47 |
48 | @Nullable
49 | @Override
50 | public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
51 | boolean needInflater = !isCacheView() || mRootView == null;
52 | if (needInflater) {
53 | mRootView = inflater.inflate(getLayoutId(), container, false);
54 | initData();
55 | initView(savedInstanceState);
56 | setListener();
57 | } else {
58 | ViewGroup parent = (ViewGroup) mRootView.getParent();
59 | if (parent != null) {
60 | parent.removeView(mRootView);
61 | }
62 | }
63 | return mRootView;
64 | }
65 |
66 | @Override
67 | public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
68 | super.onViewCreated(view, savedInstanceState);
69 | if (canLazyLoad()) {
70 | onLazyLoad();
71 | }
72 | }
73 |
74 | @Override
75 | public void initData() {
76 | // TODO Auto-generated method stub
77 | }
78 |
79 | @Override
80 | public void initView(Bundle savedInstanceState) {
81 |
82 | }
83 |
84 | /**
85 | * 添加监听 initView() 之后被调用
86 | */
87 | @Override
88 | public void setListener() {
89 |
90 | }
91 |
92 | /**
93 | * 是否需要缓存rootView 防止onCreteView 重新执行后重新初始化视图
94 | *
95 | * @return
96 | */
97 | public boolean isCacheView() {
98 | return true;
99 | }
100 |
101 |
102 | protected void onLazyLoad() {
103 |
104 | }
105 |
106 | /**
107 | * @return true 视图已经初始化并对用户可见,满足此条件才会调用{@link #onLazyLoad()}
108 | */
109 | protected boolean canLazyLoad() {
110 | return getView() != null && getUserVisibleHint();
111 | }
112 |
113 | @Override
114 | public void setUserVisibleHint(boolean isVisibleToUser) {
115 | super.setUserVisibleHint(isVisibleToUser);
116 | if (canLazyLoad()) {
117 | onLazyLoad();
118 | }
119 | }
120 |
121 | @Override
122 | public void onDestroyView() {
123 | super.onDestroyView();
124 | if (!isCacheView()) {
125 | mRootView = null;
126 | }
127 | }
128 |
129 | @Override
130 | public void onDestroy() {
131 | // TODO Auto-generated method stub
132 | super.onDestroy();
133 | hideLoading();
134 | //页面销毁的时候,防止外部引用Fragment,导致mRootView一直被引用,并且只支持FragmentPagerAdapter的页面缓存
135 | mRootView = null;
136 | }
137 |
138 | public T findViewById(@IdRes int id) {
139 | final View view = getView();
140 | return view != null ? view.findViewById(id) : null;
141 | }
142 |
143 | @Nullable
144 | @Override
145 | public View getView() {
146 | View view = super.getView();
147 | return view != null ? view : mRootView;
148 | }
149 |
150 |
151 | @Override
152 | public void onClick(View v) {
153 | // TODO Auto-generated method stub
154 | }
155 |
156 | public void showLoading() {
157 | if (mLoadingDialog == null) {
158 | mLoadingDialog = EasyView.FACTORY.create(getContext(), getClass().getName());
159 | }
160 | mLoadingDialog.show();
161 | }
162 |
163 | public void hideLoading() {
164 | if (mLoadingDialog != null) {
165 | mLoadingDialog.dismiss();
166 | }
167 | }
168 |
169 | @Override
170 | public void showMessage(CharSequence text) {
171 | EasyView.info(text);
172 | }
173 |
174 | @Override
175 | public void onActivityResult(int requestCode, int resultCode, Intent data) {
176 | if (resultCode == Activity.RESULT_OK)
177 | onActivityResultOk(requestCode, data);
178 | }
179 |
180 | protected void onActivityResultOk(int requestCode, Intent data) {
181 |
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/EasyPagerActivity.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.os.Bundle;
4 | import androidx.viewpager.widget.ViewPager;
5 |
6 | import com.xcheng.view.R;
7 | import com.xcheng.view.adapter.EasyFragmentAdapter;
8 | import com.xcheng.view.adapter.TabInfo;
9 | import com.xcheng.view.widget.smarttab.SmartTabLayout;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * 约定大于配置,
16 | * 设置Viewpager 的id 为ev_id_viewpager,
17 | * 设置PagerSlidingTabStrip 的 id为ev_id_tab_indicator
18 | *
19 | * @author chengxin @date:2017-8-30
20 | */
21 | public abstract class EasyPagerActivity extends EasyActivity {
22 |
23 | protected ViewPager mViewPager;
24 | protected EasyFragmentAdapter mTabAdapter;
25 | protected SmartTabLayout mTabLayout;
26 |
27 | @Override
28 | public int getLayoutId() {
29 | return R.layout.ev_pager;
30 | }
31 |
32 | @Override
33 | public void initView(Bundle savedInstanceState) {
34 | // TODO Auto-generated method stub
35 | super.initView(savedInstanceState);
36 | mViewPager = findViewById(R.id.ev_id_viewpager);
37 | List tabInfos = new ArrayList<>();
38 | getTabInfos(tabInfos);
39 | mTabAdapter = new EasyFragmentAdapter(getSupportFragmentManager(), getContext(), tabInfos);
40 | mViewPager.setAdapter(mTabAdapter);
41 | mTabLayout = findViewById(R.id.ev_id_tabLayout);
42 | /**if call {@link SmartTabLayout#setCustomTabView(SmartTabLayout.TabProvider)}
43 | * {@link SmartTabLayout#setCustomTabView(int, int)},you must call{@link SmartTabLayout#setViewPager(ViewPager)} again
44 | */
45 | mTabLayout.setViewPager(mViewPager);
46 | }
47 |
48 | /**
49 | * 设置Tab页面加载的每个页面
50 | */
51 | protected void getTabInfos(final List tabInfos) {
52 |
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/EasyPagerFragment.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.os.Bundle;
4 | import androidx.viewpager.widget.ViewPager;
5 |
6 | import com.xcheng.view.R;
7 | import com.xcheng.view.adapter.EasyFragmentAdapter;
8 | import com.xcheng.view.adapter.TabInfo;
9 | import com.xcheng.view.widget.smarttab.SmartTabLayout;
10 |
11 | import java.util.ArrayList;
12 | import java.util.List;
13 |
14 | /**
15 | * 约定大于配置,
16 | * 设置Viewpager 的id 为ev_id_viewpager,
17 | * 设置PagerSlidingTabStrip 的 id为ev_id_tabLayout
18 | *
19 | * @author chengxin @date:2017-8-30
20 | */
21 | public abstract class EasyPagerFragment extends EasyFragment {
22 |
23 | protected ViewPager mViewPager;
24 | protected EasyFragmentAdapter mTabAdapter;
25 | protected SmartTabLayout mTabLayout;
26 |
27 | @Override
28 | public int getLayoutId() {
29 | return R.layout.ev_pager;
30 | }
31 |
32 | @Override
33 | public void initView(Bundle savedInstanceState) {
34 | // TODO Auto-generated method stub
35 | super.initView(savedInstanceState);
36 | mViewPager = findViewById(R.id.ev_id_viewpager);
37 | List tabInfos = new ArrayList<>();
38 | getTabInfos(tabInfos);
39 | mTabAdapter = new EasyFragmentAdapter(getChildFragmentManager(), getContext(), tabInfos);
40 | mViewPager.setAdapter(mTabAdapter);
41 | mTabLayout = findViewById(R.id.ev_id_tabLayout);
42 | mTabLayout.setViewPager(mViewPager);
43 | }
44 |
45 | /**
46 | * 设置Tab页面加载的每个页面
47 | */
48 | protected void getTabInfos(final List tabInfos) {
49 |
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/GlobalLifecycleCallbacks.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.app.Activity;
4 | import android.app.Application.ActivityLifecycleCallbacks;
5 | import android.os.Bundle;
6 |
7 | import androidx.annotation.CallSuper;
8 | import androidx.fragment.app.FragmentActivity;
9 | import androidx.fragment.app.FragmentManager;
10 |
11 | /**
12 | * 全局 Activity和Fragment 生命周期监听
13 | * Created by chengxin on 2017/9/29.
14 | */
15 | public class GlobalLifecycleCallbacks extends FragmentManager.FragmentLifecycleCallbacks implements ActivityLifecycleCallbacks {
16 | static String TAG = "GlobalLifecycleCallbacks";
17 |
18 | @CallSuper
19 | @Override
20 | public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
21 | if (activity instanceof FragmentActivity) {
22 | //此处为Fragment注册生命周期,并且只有一个监听实例
23 | ((FragmentActivity) activity).getSupportFragmentManager()
24 | .registerFragmentLifecycleCallbacks(this, true);
25 | }
26 | }
27 |
28 | @Override
29 | public void onActivityStarted(Activity activity) {
30 |
31 | }
32 |
33 | @Override
34 | public void onActivityResumed(Activity activity) {
35 |
36 | }
37 |
38 | @Override
39 | public void onActivityPaused(Activity activity) {
40 |
41 | }
42 |
43 | @Override
44 | public void onActivityStopped(Activity activity) {
45 |
46 | }
47 |
48 | @Override
49 | public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
50 |
51 | }
52 |
53 | @Override
54 | public void onActivityDestroyed(Activity activity) {
55 |
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/IEasyView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.os.Bundle;
4 | import android.view.View;
5 |
6 | import androidx.annotation.LayoutRes;
7 |
8 | /**
9 | * @author xincheng
10 | */
11 | public interface IEasyView extends View.OnClickListener, ILoadingView {
12 | /**
13 | * 获取布局Layout的id
14 | */
15 | @LayoutRes
16 | int getLayoutId();
17 |
18 | /**
19 | * 初始化传递过来的Bundle数据
20 | */
21 | void initData();
22 |
23 | /**
24 | * savedInstanceState If the activity is being re-initialized after
25 | * previously being shut down then this Bundle contains the data it most
26 | * recently supplied in android.app.Activity#onSaveInstanceState(Bundle).
27 | * Note: Otherwise it is null.
28 | * 初始化View控件
29 | *
30 | * @param savedInstanceState 销毁保存参数
31 | */
32 | void initView(Bundle savedInstanceState);
33 |
34 | /**
35 | * 设置监听
36 | */
37 | void setListener();
38 |
39 | /**
40 | * 显示消息提醒等,可以自己重写覆盖此方法
41 | *
42 | * @param text 消息内容
43 | */
44 | void showMessage(CharSequence text);
45 |
46 | }
47 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/ILoadingView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | /**
4 | * 显示加载
5 | *
6 | * @author xincheng
7 | */
8 | public interface ILoadingView {
9 | /**
10 | * 显示加载
11 | */
12 | void showLoading();
13 |
14 | /**
15 | * 隐藏加载
16 | */
17 | void hideLoading();
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/IPullRefreshView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import androidx.annotation.UiThread;
4 |
5 | import java.util.List;
6 |
7 | /**
8 | * T 代表http请求返回的数据
9 | * Created by cx on 2016/10/13.
10 | */
11 | public interface IPullRefreshView {
12 | /**
13 | * Http 请求
14 | *
15 | * @param isRefresh 是否为刷新
16 | */
17 | @UiThread
18 | void requestData(boolean isRefresh);
19 |
20 | @UiThread
21 | void refreshView(boolean isRefresh, List extends T> data);
22 |
23 | /**
24 | * @param isRefresh 是否为刷新
25 | * @param success 是否成功
26 | * @param noMoreData 是否已全部加在
27 | */
28 | void complete(boolean isRefresh, boolean success, boolean noMoreData);
29 | }
30 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/SmartRefreshFragment.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller;
2 |
3 | import android.os.Bundle;
4 |
5 | import androidx.annotation.CallSuper;
6 | import androidx.annotation.IntRange;
7 | import androidx.annotation.NonNull;
8 | import androidx.recyclerview.widget.LinearLayoutManager;
9 | import androidx.recyclerview.widget.RecyclerView;
10 |
11 | import com.scwang.smartrefresh.layout.SmartRefreshLayout;
12 | import com.scwang.smartrefresh.layout.api.RefreshFooter;
13 | import com.scwang.smartrefresh.layout.api.RefreshHeader;
14 | import com.scwang.smartrefresh.layout.api.RefreshLayout;
15 | import com.scwang.smartrefresh.layout.constant.RefreshState;
16 | import com.scwang.smartrefresh.layout.listener.OnRefreshLoadMoreListener;
17 | import com.scwang.smartrefresh.layout.listener.SimpleMultiPurposeListener;
18 | import com.xcheng.view.R;
19 | import com.xcheng.view.adapter.EasyAdapter;
20 | import com.xcheng.view.enums.SmartState;
21 |
22 | import java.util.List;
23 |
24 | /**
25 | * 刷新列表Fragment
26 | * 约定大于配置,
27 | * SmartRefreshLayout 的id ev_id_smartRefreshLayout,
28 | * 设置RecyclerView 的 id为ev_id_recyclerView
29 | *
30 | * @author xincheng @date:2017-9-4
31 | */
32 | public abstract class SmartRefreshFragment extends EasyFragment implements IPullRefreshView {
33 | protected SmartRefreshLayout mSmartRefreshLayout;
34 | protected RecyclerView mRecyclerView;
35 | protected EasyAdapter mAdapter;
36 | protected Config mConfig;
37 |
38 | @Override
39 | public int getLayoutId() {
40 | return R.layout.ev_smart_refresh;
41 | }
42 |
43 | @CallSuper
44 | @Override
45 | public void initView(Bundle savedInstanceState) {
46 | super.initView(savedInstanceState);
47 | //TODO 重写此方法设置RecyclerView 和 SmartRefreshLayout的属性
48 | mConfig = getConfig();
49 | mSmartRefreshLayout = findViewById(R.id.ev_id_smartRefreshLayout);
50 | mRecyclerView = findViewById(R.id.ev_id_recyclerView);
51 | mRecyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
52 | mRecyclerView.setAdapter(mAdapter = createAdapter());
53 | onSmartStateChanged(SmartState.NONE);
54 | }
55 |
56 | /**
57 | * 子类重写修改配置
58 | */
59 | @NonNull
60 | protected Config getConfig() {
61 | return Config.DEFAULT;
62 | }
63 |
64 | /**
65 | * 创建一个HFAdapter对象
66 | */
67 | @NonNull
68 | protected abstract EasyAdapter createAdapter();
69 |
70 |
71 | /**
72 | * 子类如果需要监听状态可以重写此函数
73 | */
74 | protected void onSmartStateChanged(SmartState smartState) {
75 | }
76 |
77 |
78 | @Override
79 | public void setListener() {
80 | super.setListener();
81 | mSmartRefreshLayout.setOnRefreshLoadMoreListener(new OnRefreshLoadMoreListener() {
82 | @Override
83 | public void onRefresh(RefreshLayout refreshlayout) {
84 | requestData(true);
85 | }
86 |
87 | @Override
88 | public void onLoadMore(RefreshLayout refreshlayout) {
89 | requestData(false);
90 | }
91 | });
92 | mSmartRefreshLayout.setOnMultiPurposeListener(new SimpleMultiPurposeListener() {
93 | @Override
94 | public void onRefresh(RefreshLayout refreshlayout) {
95 | onSmartStateChanged(SmartState.REFRESHING);
96 | }
97 |
98 | @Override
99 | public void onHeaderFinish(RefreshHeader header, boolean success) {
100 | onSmartStateChanged(SmartState.REFRESH_FINISHED);
101 | }
102 |
103 | @Override
104 | public void onLoadMore(RefreshLayout refreshlayout) {
105 | onSmartStateChanged(SmartState.LOADING_MORE);
106 |
107 | }
108 |
109 | @Override
110 | public void onFooterFinish(RefreshFooter footer, boolean success) {
111 | onSmartStateChanged(SmartState.LOADING_FINISHED);
112 | }
113 |
114 | @Override
115 | public void onStateChanged(RefreshLayout refreshLayout, RefreshState oldState, RefreshState newState) {
116 | if (newState == RefreshState.None) {
117 | onSmartStateChanged(SmartState.NONE);
118 | }
119 | }
120 | });
121 | }
122 |
123 | @Override
124 | protected void onLazyLoad() {
125 | if (!mConfig.autoRefresh)
126 | return;
127 | if (mAdapter == null || mAdapter.getDataCount() != 0)
128 | return;
129 | mSmartRefreshLayout.autoRefresh(mConfig.autoRefreshDelayed);
130 | }
131 |
132 | @Override
133 | public void refreshView(boolean isRefresh, List extends T> data) {
134 | if (isRefresh) {
135 | mAdapter.refresh(data);
136 | } else {
137 | mAdapter.addData(data);
138 | }
139 | boolean noMoreData = data == null || data.size() < mConfig.limit;
140 | complete(isRefresh, true, noMoreData);
141 | }
142 |
143 | @Override
144 | public void complete(boolean isRefresh, boolean success, boolean noMoreData) {
145 | if (isRefresh) {
146 | mSmartRefreshLayout.finishRefresh(0, success, noMoreData);
147 | } else {
148 | mSmartRefreshLayout.finishLoadMore(0, success, noMoreData);
149 | }
150 | }
151 |
152 | public static class Config {
153 | public static final Config DEFAULT = new Config();
154 | public final boolean autoRefresh;
155 | public final int autoRefreshDelayed;
156 | public final int limit;
157 |
158 | public Config(boolean autoRefresh, int autoRefreshDelayed, @IntRange(from = 1) int limit) {
159 | this.autoRefresh = autoRefresh;
160 | this.autoRefreshDelayed = autoRefreshDelayed;
161 | this.limit = limit;
162 | }
163 |
164 | public Config(int autoRefreshDelayed, @IntRange(from = 1) int limit) {
165 | this(true, autoRefreshDelayed, limit);
166 | }
167 |
168 | public Config() {
169 | this(true, 200, 10);
170 | }
171 | }
172 | }
173 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/dialog/BottomDialog.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller.dialog;
2 |
3 | import android.content.Context;
4 | import android.os.Bundle;
5 | import android.view.Gravity;
6 | import android.view.WindowManager;
7 |
8 | import androidx.annotation.Nullable;
9 |
10 | import com.xcheng.view.R;
11 | import com.xcheng.view.util.LocalDisplay;
12 |
13 | public abstract class BottomDialog extends EasyDialog {
14 |
15 | public BottomDialog(Context context) {
16 | super(context, R.style.ev_dialog_bottom_optionStyle/*默认样式*/);
17 | }
18 |
19 | public BottomDialog(Context context, int themeResId) {
20 | super(context, themeResId);
21 | }
22 |
23 | @SuppressWarnings("ConstantConditions")
24 | @Override
25 | protected void initDialog(@Nullable Bundle savedInstanceState) {
26 | super.initDialog(savedInstanceState);
27 | getWindow().setGravity(Gravity.BOTTOM);
28 | getWindow().setLayout(LocalDisplay.WIDTH_PIXEL, WindowManager.LayoutParams.WRAP_CONTENT);
29 | // WindowManager m = getWindow().getWindowManager();
30 | // Display d = m.getDefaultDisplay();
31 | // WindowManager.LayoutParams p = getWindow().getAttributes();
32 | // p.width = d.getWidth();
33 | // getWindow().setAttributes(p);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/dialog/BottomOptionDialog.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller.dialog;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Color;
6 | import android.os.Bundle;
7 | import android.view.Gravity;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 |
12 | import androidx.annotation.ColorInt;
13 | import androidx.annotation.LayoutRes;
14 | import androidx.annotation.Nullable;
15 | import androidx.annotation.Size;
16 | import androidx.core.content.ContextCompat;
17 | import androidx.core.util.Preconditions;
18 | import androidx.recyclerview.widget.LinearLayoutManager;
19 | import androidx.recyclerview.widget.RecyclerView;
20 |
21 | import com.xcheng.view.R;
22 | import com.xcheng.view.adapter.EasyAdapter;
23 | import com.xcheng.view.adapter.EasyHolder;
24 | import com.xcheng.view.adapter.SpaceDecoration;
25 | import com.xcheng.view.divider.DividerTextView;
26 | import com.xcheng.view.util.LocalDisplay;
27 |
28 | import java.util.ArrayList;
29 | import java.util.Arrays;
30 | import java.util.List;
31 |
32 | public class BottomOptionDialog extends BottomDialog {
33 | private final Builder mBuilder;
34 |
35 | private BottomOptionDialog(Builder builder) {
36 | super(builder.context);
37 | this.mBuilder = builder;
38 | }
39 |
40 | @Override
41 | public int getLayoutId() {
42 | return mBuilder.layoutId;
43 | }
44 |
45 | @SuppressLint("RestrictedApi")
46 | @Override
47 | protected void initDialog(Bundle savedInstanceState) {
48 | super.initDialog(savedInstanceState);
49 | TextView topTipTextView = findViewById(R.id.ev_id_optionDialog_topTip);
50 | if (mBuilder.tipText != null) {
51 | //如果tipText有内容而此时没有对应的TextView 则需要抛出异常
52 | Preconditions.checkState(topTipTextView != null, "layout res must have a TextView with id named ev_id_optionDialog_topTip");
53 |
54 | topTipTextView.setTextSize(mBuilder.tipTextSize);
55 | topTipTextView.setTextColor(mBuilder.tipTextColor);
56 | topTipTextView.setText(mBuilder.tipText);
57 | ViewGroup.LayoutParams lp = topTipTextView.getLayoutParams();
58 | //lp.height = mBuilder.optionHeight;
59 | topTipTextView.setBackgroundColor(mBuilder.itemColor);
60 | //topTipTextView.setLayoutParams(lp);
61 | //设置分割线的颜色
62 | if (topTipTextView instanceof DividerTextView) {
63 | DividerTextView dividerTextView = (DividerTextView) topTipTextView;
64 | dividerTextView.setBottomColor(mBuilder.dividerColor);
65 | }
66 | } else {
67 | if (topTipTextView != null) {
68 | topTipTextView.setVisibility(View.GONE);
69 | }
70 | }
71 |
72 | TextView bottomTextView = findViewById(R.id.ev_id_optionDialog_bottom);
73 | if (mBuilder.bottomText != null) {
74 | Preconditions.checkState(bottomTextView != null, "layout res must have a TextView with id named ev_id_optionDialog_bottom");
75 | bottomTextView.setTextSize(mBuilder.textSize);
76 | bottomTextView.setTextColor(mBuilder.bottomTextColor);
77 | bottomTextView.setText(mBuilder.bottomText);
78 | ViewGroup.LayoutParams lp = bottomTextView.getLayoutParams();
79 | lp.height = mBuilder.optionHeight;
80 | bottomTextView.setLayoutParams(lp);
81 | bottomTextView.setOnClickListener(this);
82 | bottomTextView.setBackgroundColor(mBuilder.itemColor);
83 | } else {
84 | if (bottomTextView != null) {
85 | bottomTextView.setVisibility(View.GONE);
86 | }
87 | }
88 | RecyclerView recyclerView = findViewById(R.id.ev_id_recyclerView);
89 | Preconditions.checkState(recyclerView != null, "layout res must have a RecyclerView with id named ev_id_recyclerView");
90 | recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
91 | recyclerView.addItemDecoration(new SpaceDecoration(mBuilder.dividerColor, 1));
92 | recyclerView.setAdapter(new OptionAdapter(mBuilder.context, new ArrayList<>(Arrays.asList(mBuilder.optionTexts))));
93 | }
94 |
95 | @Override
96 | public void onClick(View v) {
97 | dismiss();
98 | if (v.getId() == R.id.ev_id_optionDialog_bottom) {
99 | if (mBuilder.onSelectListener != null) {
100 | mBuilder.onSelectListener.onBottomSelect(v);
101 | }
102 | }
103 | }
104 |
105 | public static class Builder {
106 | private Context context;
107 | private int layoutId;
108 | private String[] optionTexts;
109 | private String tipText;
110 | private int tipTextColor;
111 | private int tipTextSize;
112 | private String bottomText;
113 | private OnSelectListener onSelectListener;
114 | private int itemColor;
115 | private int dividerColor;
116 | private int textSize;
117 | private int bottomTextColor;
118 | private int optionTextColor;
119 | private int optionHeight;
120 |
121 | public Builder(Context context) {
122 | this.context = context;
123 | this.layoutId = R.layout.ev_dialog_option_bottom;
124 | this.tipTextSize = 14;
125 | this.tipTextColor = ContextCompat.getColor(context, R.color.ev_text_grey);
126 | this.bottomText = "取消";
127 | this.itemColor = Color.WHITE;
128 | this.bottomTextColor = ContextCompat.getColor(context, R.color.ev_text_grey);
129 | this.optionTextColor = ContextCompat.getColor(context, R.color.ev_light_blue);
130 | this.dividerColor = ContextCompat.getColor(context, R.color.ev_divider_color);
131 | this.textSize = 18;
132 | this.optionHeight = LocalDisplay.dp2px(45);
133 | }
134 |
135 | /**
136 | * 自定义布局必须有一个RecyclerView其id为 ev_id_recyclerView,
137 | * * @param layoutId 布局的id
138 | */
139 | public Builder layoutId(@LayoutRes int layoutId) {
140 | this.layoutId = layoutId;
141 | return this;
142 | }
143 |
144 | public Builder tipText(String tipText) {
145 | this.tipText = tipText;
146 | return this;
147 | }
148 |
149 | public Builder tipTextColor(@ColorInt int tipTextColor) {
150 | this.tipTextColor = tipTextColor;
151 | return this;
152 | }
153 |
154 | public Builder tipTextSize(int tipTextSize) {
155 | this.tipTextSize = tipTextSize;
156 | return this;
157 | }
158 |
159 | public Builder optionHeight(int optionHeight) {
160 | this.optionHeight = optionHeight;
161 | return this;
162 | }
163 |
164 | public Builder bottomTextColor(@ColorInt int bottomTextColor) {
165 | this.bottomTextColor = bottomTextColor;
166 | return this;
167 | }
168 |
169 | public Builder optionTextColor(@ColorInt int optionTextColor) {
170 | this.optionTextColor = optionTextColor;
171 | return this;
172 | }
173 |
174 | public Builder optionTexts(@Size(min = 1) String... optionTexts) {
175 | this.optionTexts = optionTexts;
176 | return this;
177 | }
178 |
179 | /**
180 | * @param bottomText if null, do not show bottomBtn
181 | * @return Builder
182 | */
183 | public Builder bottomText(String bottomText) {
184 | this.bottomText = bottomText;
185 | return this;
186 | }
187 |
188 | public Builder onSelectListener(OnSelectListener l) {
189 | this.onSelectListener = l;
190 | return this;
191 | }
192 |
193 | public Builder itemColor(@ColorInt int itemColor) {
194 | this.itemColor = itemColor;
195 | return this;
196 | }
197 |
198 | public Builder dividerColor(@ColorInt int dividerColor) {
199 | this.dividerColor = dividerColor;
200 | return this;
201 | }
202 |
203 | /**
204 | * @param textSize 单位为sp
205 | * @return Builder
206 | */
207 | public Builder textSize(int textSize) {
208 | this.textSize = textSize;
209 | return this;
210 | }
211 |
212 | @SuppressLint("RestrictedApi")
213 | public BottomOptionDialog create() {
214 | Preconditions.checkState(optionTexts != null, "optionTexts has not been init");
215 | return new BottomOptionDialog(this);
216 | }
217 |
218 | public BottomOptionDialog show() {
219 | BottomOptionDialog dialog = create();
220 | dialog.show();
221 | return dialog;
222 | }
223 | }
224 |
225 | private class OptionAdapter extends EasyAdapter {
226 | private OptionAdapter(Context context, @Nullable List data) {
227 | super(context, data);
228 | }
229 |
230 | @Override
231 | public View getDelegateView(ViewGroup parent, int viewType) {
232 | TextView optionText = new TextView(getContext());
233 | optionText.setGravity(Gravity.CENTER);
234 | RecyclerView.LayoutParams lp = new RecyclerView.LayoutParams(-1, mBuilder.optionHeight);
235 | optionText.setTextColor(mBuilder.optionTextColor);
236 | optionText.setTextSize(mBuilder.textSize);
237 | optionText.setLayoutParams(lp);
238 | optionText.setBackgroundColor(mBuilder.itemColor);
239 | return optionText;
240 | }
241 |
242 | @Override
243 | public void convert(final EasyHolder holder, String s, int position) {
244 | TextView optionText = (TextView) holder.itemView;
245 | optionText.setOnClickListener(new View.OnClickListener() {
246 | @Override
247 | public void onClick(View v) {
248 | dismiss();
249 | if (mBuilder.onSelectListener != null) {
250 | mBuilder.onSelectListener.onOptionSelect(v, holder.getAdapterPosition());
251 | }
252 | }
253 | });
254 | optionText.setText(mBuilder.optionTexts[position]);
255 | }
256 | }
257 |
258 | public interface OnSelectListener {
259 | void onBottomSelect(View view);
260 |
261 | /**
262 | * @param view 对应的view
263 | * @param position 设置在数组中的位置
264 | */
265 | void onOptionSelect(View view, int position);
266 | }
267 | }
268 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/dialog/EasyDialog.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller.dialog;
2 |
3 | import android.app.Dialog;
4 | import android.content.Context;
5 | import android.os.Bundle;
6 | import android.view.View;
7 |
8 | import androidx.annotation.LayoutRes;
9 | import androidx.annotation.NonNull;
10 | import androidx.annotation.Nullable;
11 | import androidx.annotation.StyleRes;
12 |
13 |
14 | /**
15 | * 基础的Dialog
16 | * Created by chengxin on 2016/11/7.
17 | */
18 | public abstract class EasyDialog extends Dialog implements View.OnClickListener {
19 |
20 | public EasyDialog(@NonNull Context context) {
21 | super(context);
22 | }
23 |
24 | public EasyDialog(@NonNull Context context, @StyleRes int themeResId) {
25 | super(context, themeResId);
26 | }
27 |
28 | public EasyDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) {
29 | super(context, cancelable, cancelListener);
30 | }
31 |
32 | @Override
33 | protected final void onCreate(Bundle savedInstanceState) {
34 | super.onCreate(savedInstanceState);
35 | setContentView(getLayoutId());
36 | initDialog(savedInstanceState);
37 | }
38 |
39 | /**
40 | * 获取布局Layout的id
41 | */
42 | @LayoutRes
43 | protected abstract int getLayoutId();
44 |
45 | /**
46 | * 初始化dialog
47 | */
48 | protected void initDialog(@Nullable Bundle savedInstanceState) {
49 |
50 | }
51 |
52 | @Override
53 | public void onClick(View v) {
54 |
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/controller/dialog/LoadingDialog.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.controller.dialog;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.annotation.LayoutRes;
6 |
7 | import com.xcheng.view.R;
8 |
9 | public class LoadingDialog extends EasyDialog {
10 | private LoadingDialog(Context context, int defStyle) {
11 | super(context, defStyle);
12 | setCancelable(false);
13 | setCanceledOnTouchOutside(false);
14 | }
15 |
16 | public LoadingDialog(Context context) {
17 | this(context, R.style.ev_dialog_loadingStyle);
18 | }
19 |
20 | public static LoadingDialog getSimpleDialog(Context context, @LayoutRes final int layoutId) {
21 | return new LoadingDialog(context) {
22 | @Override
23 | public int getLayoutId() {
24 | return layoutId;
25 | }
26 | };
27 | }
28 |
29 | @Override
30 | protected int getLayoutId() {
31 | return R.layout.ev_dialog_loading;
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/divider/DividerContainer.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.divider;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.util.AttributeSet;
6 | import android.widget.FrameLayout;
7 |
8 | /**
9 | * 带分割线的的FrameLayout
10 | * Created by chengxin on 2017/8/29.
11 | */
12 | public class DividerContainer extends FrameLayout implements IDividerView {
13 | private DividerHelper mDividerHelper;
14 |
15 | public DividerContainer(Context context) {
16 | this(context, null);
17 | }
18 |
19 | public DividerContainer(Context context, AttributeSet attrs) {
20 | this(context, attrs, 0);
21 | }
22 |
23 | public DividerContainer(Context context, AttributeSet attrs, int defStyleAttr) {
24 | super(context, attrs, defStyleAttr);
25 | mDividerHelper = new DividerHelper(this);
26 | mDividerHelper.loadFromAttributes(attrs, defStyleAttr);
27 | }
28 |
29 | @Override
30 | public void draw(Canvas canvas) {
31 | super.draw(canvas);
32 | mDividerHelper.drawDivider(canvas);
33 | }
34 |
35 | @Override
36 | public void setTopToLeft(int topToLeft) {
37 | mDividerHelper.setTopToLeft(topToLeft);
38 | }
39 |
40 | @Override
41 | public void setTopToRight(int topToRight) {
42 | mDividerHelper.setTopToRight(topToRight);
43 | }
44 |
45 | @Override
46 | public void setBottomToLeft(int bottomToLeft) {
47 | mDividerHelper.setBottomToLeft(bottomToLeft);
48 | }
49 |
50 | @Override
51 | public void setBottomToRight(int bottomToRight) {
52 | mDividerHelper.setBottomToRight(bottomToRight);
53 | }
54 |
55 | @Override
56 | public void setTopHeight(float topHeight) {
57 | mDividerHelper.setTopHeight(topHeight);
58 | }
59 |
60 | @Override
61 | public void setBottomHeight(float bottomHeight) {
62 | mDividerHelper.setBottomHeight(bottomHeight);
63 | }
64 |
65 | @Override
66 | public void setTopColor(int topColor) {
67 | mDividerHelper.setTopColor(topColor);
68 | }
69 |
70 | @Override
71 | public void setBottomColor(int bottomColor) {
72 | mDividerHelper.setBottomColor(bottomColor);
73 | }
74 |
75 | @Override
76 | public void setPosition(int position) {
77 | mDividerHelper.setPosition(position);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/divider/DividerHelper.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.divider;
2 |
3 | import android.content.res.TypedArray;
4 | import android.graphics.Canvas;
5 | import android.graphics.Paint;
6 | import androidx.annotation.CallSuper;
7 | import androidx.core.content.ContextCompat;
8 | import android.util.AttributeSet;
9 | import android.view.View;
10 | import android.view.ViewGroup;
11 |
12 | import com.xcheng.view.R;
13 |
14 | /**
15 | * 表单View解析帮助类
16 | * Created by chengxin on 2017/7/29.
17 | */
18 | public class DividerHelper {
19 | private Paint mPaint;
20 | public static final int DIVIDER_NONE = 0x0;
21 | public static final int DIVIDER_TOP = 0x1;//是否绘制上面
22 | public static final int DIVIDER_BOTTOM = 0x2;//是否绘制下面
23 |
24 | private int position;
25 | private int topToLeft;
26 | private int topToRight;
27 | private int bottomToLeft;
28 | private int bottomToRight;
29 |
30 | private View dividerView;
31 |
32 | private float topHeight;
33 | private float bottomHeight;
34 |
35 | private int topColor;
36 | private int bottomColor;
37 |
38 | public DividerHelper(View dividerView) {
39 | if (dividerView instanceof ViewGroup) {
40 | ViewGroup vp = (ViewGroup) dividerView;
41 | vp.setWillNotDraw(false);
42 | }
43 | this.dividerView = dividerView;
44 | mPaint = new Paint();
45 | mPaint.setAntiAlias(true);
46 | }
47 |
48 | @CallSuper
49 | public void loadFromAttributes(AttributeSet attrs, int defStyleAttr) {
50 | TypedArray typedArray = dividerView.getContext().obtainStyledAttributes(attrs, R.styleable.DividerView, defStyleAttr, 0);
51 | int defaultDividerColor = ContextCompat.getColor(dividerView.getContext(), R.color.ev_divider_color);
52 | position = typedArray.getInt(R.styleable.DividerView_ev_position, DIVIDER_NONE);
53 | topToLeft = typedArray.getDimensionPixelSize(R.styleable.DividerView_ev_topToLeft, 0);
54 | topToRight = typedArray.getDimensionPixelSize(R.styleable.DividerView_ev_topToRight, 0);
55 | topColor = typedArray.getColor(R.styleable.DividerView_ev_topColor, defaultDividerColor);
56 | topHeight = typedArray.getDimensionPixelSize(R.styleable.DividerView_ev_topHeight, 1);
57 |
58 | bottomToLeft = typedArray.getDimensionPixelSize(R.styleable.DividerView_ev_bottomToLeft, 0);
59 | bottomToRight = typedArray.getDimensionPixelSize(R.styleable.DividerView_ev_bottomToRight, 0);
60 | bottomColor = typedArray.getColor(R.styleable.DividerView_ev_bottomColor, defaultDividerColor);
61 | bottomHeight = typedArray.getDimensionPixelSize(R.styleable.DividerView_ev_bottomHeight, 1);
62 | typedArray.recycle();
63 | }
64 |
65 | @SuppressWarnings("SuspiciousNameCombination")
66 | private void drawTop(Canvas canvas) {
67 | if ((position & DIVIDER_TOP) == DIVIDER_TOP) {
68 | mPaint.setColor(topColor);
69 | mPaint.setStrokeWidth(topHeight);
70 | canvas.drawLine(topToLeft, topHeight / 2, dividerView.getWidth() - topToRight, topHeight / 2, mPaint);
71 | }
72 | }
73 |
74 | @SuppressWarnings("SuspiciousNameCombination")
75 | private void drawBottom(Canvas canvas) {
76 | if ((position & DIVIDER_BOTTOM) == DIVIDER_BOTTOM) {
77 | mPaint.setColor(bottomColor);
78 | mPaint.setStrokeWidth(bottomHeight);
79 | canvas.drawLine(bottomToLeft, dividerView.getHeight() - bottomHeight / 2, dividerView.getWidth() - bottomToRight, dividerView.getHeight() - bottomHeight / 2, mPaint);
80 | }
81 | }
82 |
83 | /**
84 | * called this method in {@link View#draw(Canvas)}
85 | *
86 | * @param canvas
87 | */
88 | public void drawDivider(Canvas canvas) {
89 | drawTop(canvas);
90 | drawBottom(canvas);
91 | }
92 |
93 | public void setTopToLeft(int topToLeft) {
94 | this.topToLeft = topToLeft;
95 | dividerView.invalidate();
96 | }
97 |
98 |
99 | public void setTopToRight(int topToRight) {
100 | this.topToRight = topToRight;
101 | dividerView.invalidate();
102 | }
103 |
104 |
105 | public void setBottomToLeft(int bottomToLeft) {
106 | this.bottomToLeft = bottomToLeft;
107 | dividerView.invalidate();
108 | }
109 |
110 |
111 | public void setBottomToRight(int bottomToRight) {
112 | this.bottomToRight = bottomToRight;
113 | dividerView.invalidate();
114 | }
115 |
116 |
117 | public void setTopHeight(float topHeight) {
118 | this.topHeight = topHeight;
119 | dividerView.invalidate();
120 | }
121 |
122 | public void setBottomHeight(float bottomHeight) {
123 | this.bottomHeight = bottomHeight;
124 | dividerView.invalidate();
125 | }
126 |
127 |
128 | public void setTopColor(int topColor) {
129 | this.topColor = topColor;
130 | dividerView.invalidate();
131 | }
132 |
133 |
134 | public void setBottomColor(int bottomColor) {
135 | this.bottomColor = bottomColor;
136 | dividerView.invalidate();
137 | }
138 |
139 |
140 | public void setPosition(int position) {
141 | this.position = position;
142 | dividerView.invalidate();
143 | }
144 | }
145 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/divider/DividerLayout.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.divider;
2 |
3 | import android.content.Context;
4 | import android.graphics.Canvas;
5 | import android.util.AttributeSet;
6 | import android.widget.LinearLayout;
7 |
8 | /**
9 | * 带分割线的的LinearLayout
10 | * Created by chengxin on 2017/8/29.
11 | */
12 | public class DividerLayout extends LinearLayout implements IDividerView {
13 | private DividerHelper mDividerHelper;
14 |
15 | public DividerLayout(Context context) {
16 | this(context, null);
17 | }
18 |
19 | public DividerLayout(Context context, AttributeSet attrs) {
20 | this(context, attrs, 0);
21 | }
22 |
23 | public DividerLayout(Context context, AttributeSet attrs, int defStyleAttr) {
24 | super(context, attrs, defStyleAttr);
25 | mDividerHelper = new DividerHelper(this);
26 | mDividerHelper.loadFromAttributes(attrs, defStyleAttr);
27 | }
28 |
29 | @Override
30 | public void draw(Canvas canvas) {
31 | super.draw(canvas);
32 | mDividerHelper.drawDivider(canvas);
33 | }
34 |
35 | @Override
36 | public void setTopToLeft(int topToLeft) {
37 | mDividerHelper.setTopToLeft(topToLeft);
38 | }
39 |
40 | @Override
41 | public void setTopToRight(int topToRight) {
42 | mDividerHelper.setTopToRight(topToRight);
43 | }
44 |
45 | @Override
46 | public void setBottomToLeft(int bottomToLeft) {
47 | mDividerHelper.setBottomToLeft(bottomToLeft);
48 | }
49 |
50 | @Override
51 | public void setBottomToRight(int bottomToRight) {
52 | mDividerHelper.setBottomToRight(bottomToRight);
53 | }
54 |
55 | @Override
56 | public void setTopHeight(float topHeight) {
57 | mDividerHelper.setTopHeight(topHeight);
58 | }
59 |
60 | @Override
61 | public void setBottomHeight(float bottomHeight) {
62 | mDividerHelper.setBottomHeight(bottomHeight);
63 | }
64 |
65 | @Override
66 | public void setTopColor(int topColor) {
67 | mDividerHelper.setTopColor(topColor);
68 | }
69 |
70 | @Override
71 | public void setBottomColor(int bottomColor) {
72 | mDividerHelper.setBottomColor(bottomColor);
73 | }
74 |
75 | @Override
76 | public void setPosition(int position) {
77 | mDividerHelper.setPosition(position);
78 | }
79 | }
80 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/divider/DividerTextView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.divider;
2 |
3 | import android.annotation.SuppressLint;
4 | import android.content.Context;
5 | import android.graphics.Canvas;
6 | import android.util.AttributeSet;
7 | import android.widget.TextView;
8 |
9 | /**
10 | * 带分割线的的TextView
11 | * Created by chengxin on 2017/8/29.
12 | */
13 | @SuppressLint("AppCompatCustomView")
14 | public class DividerTextView extends TextView implements IDividerView {
15 | private DividerHelper mDividerHelper;
16 |
17 | public DividerTextView(Context context) {
18 | this(context, null);
19 | }
20 |
21 | public DividerTextView(Context context, AttributeSet attrs) {
22 | //必须传递android.R.attr.textStyle,否则没有默认的样式掉
23 | this(context, attrs, android.R.attr.textViewStyle);
24 | }
25 |
26 | public DividerTextView(Context context, AttributeSet attrs, int defStyleAttr) {
27 | super(context, attrs, defStyleAttr);
28 | mDividerHelper = new DividerHelper(this);
29 | mDividerHelper.loadFromAttributes(attrs, defStyleAttr);
30 | }
31 |
32 | @Override
33 | public void draw(Canvas canvas) {
34 | super.draw(canvas);
35 | mDividerHelper.drawDivider(canvas);
36 | }
37 |
38 | @Override
39 | public void setTopToLeft(int topToLeft) {
40 | mDividerHelper.setTopToLeft(topToLeft);
41 | }
42 |
43 | @Override
44 | public void setTopToRight(int topToRight) {
45 | mDividerHelper.setTopToRight(topToRight);
46 | }
47 |
48 | @Override
49 | public void setBottomToLeft(int bottomToLeft) {
50 | mDividerHelper.setBottomToLeft(bottomToLeft);
51 | }
52 |
53 | @Override
54 | public void setBottomToRight(int bottomToRight) {
55 | mDividerHelper.setBottomToRight(bottomToRight);
56 | }
57 |
58 | @Override
59 | public void setTopHeight(float topHeight) {
60 | mDividerHelper.setTopHeight(topHeight);
61 | }
62 |
63 | @Override
64 | public void setBottomHeight(float bottomHeight) {
65 | mDividerHelper.setBottomHeight(bottomHeight);
66 | }
67 |
68 | @Override
69 | public void setTopColor(int topColor) {
70 | mDividerHelper.setTopColor(topColor);
71 | }
72 |
73 | @Override
74 | public void setBottomColor(int bottomColor) {
75 | mDividerHelper.setBottomColor(bottomColor);
76 | }
77 |
78 | @Override
79 | public void setPosition(int position) {
80 | mDividerHelper.setPosition(position);
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/divider/IDividerView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.divider;
2 |
3 | /**
4 | * 带分割线的的View ,实现此接口
5 | * Created by chengxin on 2017/8/29.
6 | */
7 | public interface IDividerView {
8 | void setTopToLeft(int topToLeft);
9 |
10 | void setTopToRight(int topToRight);
11 |
12 | void setBottomToLeft(int bottomToLeft);
13 |
14 | void setBottomToRight(int bottomToRight);
15 |
16 | void setTopHeight(float topHeight);
17 |
18 | void setBottomHeight(float bottomHeight);
19 |
20 | void setTopColor(int topColor);
21 |
22 | void setBottomColor(int bottomColor);
23 |
24 | void setPosition(int position);
25 | }
26 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/enums/SmartState.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.enums;
2 |
3 | /**
4 | * 刷新组件的状态
5 | */
6 | public enum SmartState {
7 |
8 | NONE("初始状态"),
9 | REFRESHING("正在刷新"),
10 | LOADING_MORE("加载更多"),
11 | REFRESH_FINISHED("刷新结束"),
12 | LOADING_FINISHED("加载更多结束");
13 |
14 | private final String text;
15 |
16 | SmartState(String text) {
17 | this.text = text;
18 | }
19 |
20 | public String getText() {
21 | return text;
22 | }
23 |
24 | }
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/round/RoundButton.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.round;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import androidx.appcompat.widget.AppCompatButton;
7 |
8 | /**
9 | * 创建时间:2018/7/20
10 | * 编写人: chengxin
11 | * 功能描述:
12 | */
13 | public class RoundButton extends AppCompatButton {
14 |
15 | public RoundButton(Context context) {
16 | this(context, null);
17 | }
18 |
19 | public RoundButton(Context context, AttributeSet attrs) {
20 | super(context, attrs);
21 | RoundDrawableHelper roundDrawableHelper = new RoundDrawableHelper(this);
22 | roundDrawableHelper.loadAttributeSet(context, attrs, 0);
23 | roundDrawableHelper.setRoundDrawable();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/round/RoundDrawableHelper.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.round;
2 |
3 | import android.content.Context;
4 | import android.content.res.TypedArray;
5 | import android.graphics.Rect;
6 | import android.graphics.drawable.Drawable;
7 | import android.graphics.drawable.GradientDrawable;
8 | import android.graphics.drawable.StateListDrawable;
9 | import android.util.AttributeSet;
10 | import android.util.StateSet;
11 | import android.view.View;
12 | import android.widget.Button;
13 |
14 | import androidx.annotation.ColorInt;
15 |
16 | import com.xcheng.view.R;
17 | import com.xcheng.view.util.ColorUtil;
18 | import com.xcheng.view.util.ViewUtil;
19 |
20 | /**
21 | * 使按钮能方便地指定圆角、边框颜色、边框粗细、背景色
22 | *
23 | * 优先级关系
24 | *
1、ev_radius
25 | * 2、ev_radiusTopLeft、ev_radiusTopRight....
26 | * 3、ev_isRadiusAdjustBounds
27 | *
28 | *
29 | * 注意: 因为该控件的圆角采用 View 的 background 实现, 所以与原生的 android:background
有冲突。
30 | *
31 | * 如果在 xml 中用 android:background
指定 background, 该 background 不会生效。
32 | * 如果在该 View 构造完后用 {@link View#setBackgroundResource(int)} 等方法设置背景, 该背景将覆盖圆角效果。
33 | *
34 | *
35 | *
36 | * 如需在 xml 中指定圆角、边框颜色、边框粗细、背景色等值,采用 xml 属性 {@link com.xcheng.view.R.styleable#RoundButton}
37 | *
38 | */
39 | public class RoundDrawableHelper {
40 | private final View mView;
41 | private int mFillColor;
42 | //enable为false的颜色
43 | private int mFillColorDisable;
44 | //按下的颜色
45 | private int mFillColorPressed;
46 |
47 | private int mBorderColor;
48 | //enable为false的颜色
49 | private int mBorderColorDisable;
50 | //按下的颜色
51 | private int mBorderColorPressed;
52 | private int mBorderWidth;
53 | /**
54 | * 默认为null,为null标识没有圆角
55 | */
56 | private float[] mRadii;
57 | private float mRadius;
58 |
59 | private boolean mRadiusAdjustBounds;
60 | private boolean mHasState;
61 |
62 | public RoundDrawableHelper(View view) {
63 | this.mView = view;
64 | }
65 |
66 | /**
67 | * 先调用此方法
68 | * 解析AttributeSet里面的属性信息
69 | */
70 | public void loadAttributeSet(Context context, AttributeSet attrs, int defStyleAttr) {
71 | TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RoundButton, defStyleAttr, 0);
72 | mFillColor = typedArray.getColor(R.styleable.RoundButton_ev_fillColor, 0);
73 | mFillColorPressed = typedArray.getColor(R.styleable.RoundButton_ev_fillColorPressed,
74 | mFillColor == 0 ? 0 : ColorUtil.pressed(mFillColor));
75 | mFillColorDisable = typedArray.getColor(R.styleable.RoundButton_ev_fillColorDisable,
76 | mFillColor == 0 ? 0 : ColorUtil.disabled(mFillColor));
77 | mBorderColor = typedArray.getColor(R.styleable.RoundButton_ev_borderColor, 0);
78 | mBorderColorPressed = typedArray.getColor(R.styleable.RoundButton_ev_borderColorPressed,
79 | mBorderColor == 0 ? 0 : ColorUtil.pressed(mBorderColor));
80 | mBorderColorDisable = typedArray.getColor(R.styleable.RoundButton_ev_borderColorDisable,
81 | mBorderColor == 0 ? 0 : ColorUtil.disabled(mBorderColor));
82 | mBorderWidth = typedArray.getDimensionPixelSize(R.styleable.RoundButton_ev_borderWidth, 0);
83 | mRadiusAdjustBounds = typedArray.getBoolean(R.styleable.RoundButton_ev_isRadiusAdjustBounds, true);
84 | mHasState = typedArray.getBoolean(R.styleable.RoundButton_ev_hasState,
85 | mView instanceof Button && mView.isClickable());
86 | int radius = typedArray.getDimensionPixelSize(R.styleable.RoundButton_ev_radius, 0);
87 | int radiusTopLeft = typedArray.getDimensionPixelSize(R.styleable.RoundButton_ev_radiusTopLeft, 0);
88 | int radiusTopRight = typedArray.getDimensionPixelSize(R.styleable.RoundButton_ev_radiusTopRight, 0);
89 | int radiusBottomLeft = typedArray.getDimensionPixelSize(R.styleable.RoundButton_ev_radiusBottomLeft, 0);
90 | int radiusBottomRight = typedArray.getDimensionPixelSize(R.styleable.RoundButton_ev_radiusBottomRight, 0);
91 | typedArray.recycle();
92 | //ev_radius优先级高于ev_radiusTopLeft、ev_radiusTopRight
93 | if (radius > 0) {
94 | mRadius = radius;
95 | mRadiusAdjustBounds = false;
96 | } else {
97 | //如果mBorderColor==1的情况下,这种设置方式边框会模糊
98 | if (radiusTopLeft > 0 || radiusTopRight > 0 || radiusBottomLeft > 0 || radiusBottomRight > 0) {
99 | mRadii = new float[]{
100 | radiusTopLeft, radiusTopLeft,
101 | radiusTopRight, radiusTopRight,
102 | radiusBottomRight, radiusBottomRight,
103 | radiusBottomLeft, radiusBottomLeft
104 | };
105 | mRadiusAdjustBounds = false;
106 | }
107 | }
108 | }
109 |
110 | /**
111 | * 设置圆角背景
112 | */
113 | public void setRoundDrawable() {
114 | Drawable drawable;
115 | if (mHasState) {
116 | drawable = createStateListDrawable();
117 | } else {
118 | drawable = createDrawable(mFillColor, mBorderColor);
119 | }
120 | ViewUtil.setBackgroundKeepingPadding(mView, drawable);
121 | }
122 |
123 | /**
124 | * 创建一个stateListDrawable
125 | */
126 | public StateListDrawable createStateListDrawable() {
127 | //构建各种状态的颜色数组,1-->状态 2-->填充颜色 3-->边框颜色
128 | final int[] statesColor = new int[]{
129 | android.R.attr.state_pressed, mFillColorPressed, mBorderColorPressed,
130 | -android.R.attr.state_enabled, mFillColorDisable, mBorderColorDisable,
131 | 0, mFillColor, mBorderColor
132 | };
133 | StateListDrawable stateListDrawable = new StateListDrawable();
134 | for (int index = 0; index < statesColor.length / 3; index++) {
135 | int state = statesColor[index * 3];
136 | int fillColor = statesColor[index * 3 + 1];
137 | int borderColor = statesColor[index * 3 + 2];
138 | GradientDrawable drawable = createDrawable(fillColor, borderColor);
139 | stateListDrawable.addState(state != 0 ? new int[]{state} : StateSet.WILD_CARD, drawable);
140 | }
141 | return stateListDrawable;
142 | }
143 |
144 | /**
145 | * 创建一个GradientDrawable
146 | *
147 | * @param fillColor 填充颜色
148 | * @param borderColor 边框颜色
149 | * @return
150 | */
151 | public GradientDrawable createDrawable(@ColorInt int fillColor, @ColorInt int borderColor) {
152 | RoundDrawable drawable = new RoundDrawable(mRadiusAdjustBounds);
153 | if (!mRadiusAdjustBounds) {
154 | if (mRadius > 0) {
155 | drawable.setCornerRadius(mRadius);
156 | } else if (mRadii != null) {
157 | drawable.setCornerRadii(mRadii);
158 | }
159 | }
160 | drawable.setColor(fillColor);
161 |
162 | if (mBorderWidth > 0) {
163 | drawable.setStroke(mBorderWidth, borderColor);
164 | }
165 | return drawable;
166 | }
167 |
168 |
169 | static class RoundDrawable extends GradientDrawable {
170 | /**
171 | * 圆角大小是否自适应为 View 的高度的一般
172 | */
173 | private final boolean mRadiusAdjustBounds;
174 |
175 | RoundDrawable(boolean radiusAdjustBounds) {
176 | this.mRadiusAdjustBounds = radiusAdjustBounds;
177 | }
178 |
179 | @Override
180 | protected void onBoundsChange(Rect r) {
181 | super.onBoundsChange(r);
182 | if (mRadiusAdjustBounds) {
183 | // 修改圆角为短边的一半
184 | setCornerRadius(Math.min(r.width(), r.height()) / 2);
185 | }
186 | }
187 | }
188 | }
189 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/round/RoundEditText.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.round;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 |
6 | import androidx.appcompat.widget.AppCompatEditText;
7 |
8 | /**
9 | * 创建时间:2018/7/20
10 | * 编写人: chengxin
11 | * 功能描述:圆角EditText
12 | */
13 | public class RoundEditText extends AppCompatEditText {
14 |
15 | public RoundEditText(Context context) {
16 | this(context, null);
17 | }
18 |
19 | public RoundEditText(Context context, AttributeSet attrs) {
20 | super(context, attrs);
21 | RoundDrawableHelper roundDrawableHelper = new RoundDrawableHelper(this);
22 | roundDrawableHelper.loadAttributeSet(context, attrs, 0);
23 | roundDrawableHelper.setRoundDrawable();
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/round/RoundFrameLayout.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.round;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.FrameLayout;
6 |
7 | /**
8 | * 创建时间:2018/7/20
9 | * 编写人: chengxin
10 | * 功能描述:圆角FrameLayout
11 | */
12 | public class RoundFrameLayout extends FrameLayout {
13 |
14 | public RoundFrameLayout(Context context) {
15 | this(context, null);
16 | }
17 |
18 | public RoundFrameLayout(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | RoundDrawableHelper roundDrawableHelper = new RoundDrawableHelper(this);
21 | roundDrawableHelper.loadAttributeSet(context, attrs, 0);
22 | roundDrawableHelper.setRoundDrawable();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/round/RoundLinearLayout.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.round;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.LinearLayout;
6 |
7 | /**
8 | * 创建时间:2018/7/20
9 | * 编写人: chengxin
10 | * 功能描述:圆角LinearLayout
11 | */
12 | public class RoundLinearLayout extends LinearLayout {
13 |
14 | public RoundLinearLayout(Context context) {
15 | this(context, null);
16 | }
17 |
18 | public RoundLinearLayout(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | RoundDrawableHelper roundDrawableHelper = new RoundDrawableHelper(this);
21 | roundDrawableHelper.loadAttributeSet(context, attrs, 0);
22 | roundDrawableHelper.setRoundDrawable();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/round/RoundRelativeLayout.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.round;
2 |
3 | import android.content.Context;
4 | import android.util.AttributeSet;
5 | import android.widget.RelativeLayout;
6 |
7 | /**
8 | * 创建时间:2018/7/20
9 | * 编写人: chengxin
10 | * 功能描述:圆角RelativeLayout
11 | */
12 | public class RoundRelativeLayout extends RelativeLayout {
13 |
14 | public RoundRelativeLayout(Context context) {
15 | this(context, null);
16 | }
17 |
18 | public RoundRelativeLayout(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | RoundDrawableHelper roundDrawableHelper = new RoundDrawableHelper(this);
21 | roundDrawableHelper.loadAttributeSet(context, attrs, 0);
22 | roundDrawableHelper.setRoundDrawable();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/round/RoundTextView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.round;
2 |
3 | import android.content.Context;
4 | import androidx.appcompat.widget.AppCompatTextView;
5 | import android.util.AttributeSet;
6 |
7 | /**
8 | * 创建时间:2018/7/20
9 | * 编写人: chengxin
10 | * 功能描述:圆角TextView
11 | */
12 | public class RoundTextView extends AppCompatTextView {
13 |
14 | public RoundTextView(Context context) {
15 | this(context, null);
16 | }
17 |
18 | public RoundTextView(Context context, AttributeSet attrs) {
19 | super(context, attrs);
20 | RoundDrawableHelper roundDrawableHelper = new RoundDrawableHelper(this);
21 | roundDrawableHelper.loadAttributeSet(context, attrs, 0);
22 | roundDrawableHelper.setRoundDrawable();
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/util/ColorUtil.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.util;
2 |
3 | import android.graphics.Color;
4 | import androidx.annotation.ColorInt;
5 |
6 | /**
7 | * 颜色转换工具类
8 | * Created by cx on 17/8/18.
9 | */
10 | public class ColorUtil {
11 | private static final int DISABLED_ALPHA_FILL = 186;//136
12 | private static final float ACTIVE_OPACITY_FACTOR_FILL = 0.125f;
13 |
14 | /**
15 | * 将颜色转换为16位字符串
16 | *
17 | * @param color
18 | * @return
19 | */
20 | public static String getHexColor(@ColorInt int color) {
21 | return String.format("#%s", Integer.toHexString(color));
22 | }
23 |
24 | /**
25 | * 按下填充显色
26 | *
27 | * @param color 将color经过转换计算成为pressedColor
28 | * @return
29 | */
30 | public static int pressed(int color) {
31 | return decreaseRgbChannel(color, ACTIVE_OPACITY_FACTOR_FILL);
32 | }
33 |
34 | /**
35 | * disable填充显色
36 | *
37 | * @param color 将color经过转换计算成为disabledColor
38 | * @return
39 | */
40 | public static int disabled(int color) {
41 | return increaseOpacity(color, DISABLED_ALPHA_FILL);
42 | }
43 |
44 | /**
45 | * 颜色加深处理
46 | * from: http://blog.csdn.net/jdsjlzx/article/details/41441083
47 | *
48 | * @param color RGB的值,由alpha(透明度)、red(红)、green(绿)、blue(蓝)构成,
49 | * Android中我们一般使用它的16进制,
50 | * 例如:"#FFAABBCC",最左边到最右每两个字母就是代表alpha(透明度)、
51 | * red(红)、green(绿)、blue(蓝)。每种颜色值占一个字节(8位),值域0~255
52 | * 所以下面使用移位的方法可以得到每种颜色的值,然后每种颜色值减小一下,在合成RGB颜色,颜色就会看起来深一些了
53 | * @return
54 | */
55 | public static int decreaseRgbChannel(@ColorInt int color, float percent) {
56 | // reduce rgb channel values to produce box shadow effect
57 | int red = (Color.red(color));
58 | red -= (red * percent);
59 | red = red > 0 ? red : 0;
60 |
61 | int green = (Color.green(color));
62 | green -= (green * percent);
63 | green = green > 0 ? green : 0;
64 |
65 | int blue = (Color.blue(color));
66 | blue -= (blue * percent);
67 | blue = blue > 0 ? blue : 0;
68 |
69 | return Color.argb(Color.alpha(color), red, green, blue);
70 | }
71 |
72 | public static int increaseOpacity(int color, int alpha) {
73 | return Color.argb(alpha, Color.red(color), Color.green(color), Color.blue(color));
74 | }
75 | }
76 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/util/KeyboardUtil.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.util;
2 |
3 | import android.app.Activity;
4 | import android.content.Context;
5 | import android.view.MotionEvent;
6 | import android.view.View;
7 | import android.view.inputmethod.InputMethodManager;
8 | import android.widget.EditText;
9 |
10 | /**
11 | * 输入法相关的工具类
12 | */
13 | public final class KeyboardUtil {
14 |
15 | /**
16 | * 显示输入法
17 | *
18 | * @param view
19 | */
20 | public static void show(View view) {
21 | InputMethodManager imm =
22 | (InputMethodManager) view.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
23 | imm.showSoftInput(view, InputMethodManager.SHOW_FORCED);
24 | imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
25 | }
26 |
27 | /**
28 | * 隐藏输入法
29 | *
30 | * @param view
31 | */
32 | public static void hide(View view) {
33 | InputMethodManager imm =
34 | (InputMethodManager) view.getContext().getApplicationContext().getSystemService(Context.INPUT_METHOD_SERVICE);
35 | imm.hideSoftInputFromWindow(view.getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
36 | }
37 |
38 | public static void hide(Activity activity) {
39 | View focusView = activity.getCurrentFocus();
40 | if (focusView != null) {
41 | hide(focusView);
42 | }
43 | }
44 |
45 | // 根据EditText所在坐标和用户点击的坐标相对比,来判断是否隐藏键盘,因为当用户点击EditText时没必要隐藏
46 | public static boolean isHideInput(View v, MotionEvent ev) {
47 | if (v != null && (v instanceof EditText)) {
48 | int[] l = {0, 0};
49 | v.getLocationInWindow(l);
50 | int left = l[0], top = l[1], bottom = top + v.getHeight(), right = left
51 | + v.getWidth();
52 | if (ev.getX() > left && ev.getX() < right && ev.getY() > top
53 | && ev.getY() < bottom) {
54 | // 点击EditText的事件,忽略它。
55 | return false;
56 | } else {
57 | return true;
58 | }
59 | }
60 | // 如果焦点不是EditText则忽略,这个发生在视图刚绘制完,第一个焦点不在EditView上,和用户用轨迹球选择其他的焦点
61 | return false;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/util/LocalDisplay.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.util;
2 |
3 | import android.content.Context;
4 | import android.util.DisplayMetrics;
5 | import android.util.TypedValue;
6 | import android.view.WindowManager;
7 |
8 | /**
9 | * 获取屏幕宽高的工具类,忽略屏幕的方向,宽度为较小的一边,高度为较长的一边
10 | */
11 | public class LocalDisplay {
12 |
13 | public static int WIDTH_PIXEL;
14 | public static int HEIGHT_PIXEL;
15 | public static float DENSITY;
16 | public static int WIDTH_DP;
17 | public static int HEIGHT_DP;
18 | //default false volatile 保证同步刷新到内存即可见性
19 | private static volatile boolean sInitialized;
20 |
21 | public static void init(Context context) {
22 | if (sInitialized) {
23 | return;
24 | }
25 | DisplayMetrics dm = new DisplayMetrics();
26 | WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
27 | wm.getDefaultDisplay().getMetrics(dm);
28 | DENSITY = dm.density;
29 | boolean widthLessThanHeight = dm.widthPixels <= dm.heightPixels;
30 | WIDTH_PIXEL = widthLessThanHeight ? dm.widthPixels : dm.heightPixels;
31 | HEIGHT_PIXEL = widthLessThanHeight ? dm.heightPixels : dm.widthPixels;
32 | WIDTH_DP = (int) (WIDTH_PIXEL / DENSITY);
33 | HEIGHT_DP = (int) (HEIGHT_PIXEL / DENSITY);
34 | sInitialized = true;
35 | }
36 |
37 | /**
38 | * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
39 | */
40 | public static int dp2px(float dp) {
41 | checkInit();
42 | final float scale = DENSITY;
43 | return (int) (dp * scale + 0.5f);
44 | }
45 |
46 | /**
47 | * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
48 | */
49 | public static int px2dp(float pxValue) {
50 | checkInit();
51 | final float scale = DENSITY;
52 | return (int) (pxValue / scale + 0.5f);
53 | }
54 |
55 | private static void checkInit() {
56 | if (!sInitialized)
57 | throw new IllegalStateException("LocalDisplay has not init");
58 | }
59 |
60 | /**
61 | * 单位转换
62 | */
63 | public static int convert(int unit, float value, Context context) {
64 | // TypedValue.COMPLEX_UNIT_SP
65 | return (int) TypedValue.applyDimension(unit, value, context.getResources()
66 | .getDisplayMetrics());
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/util/NumberTextWatcher.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.util;
2 |
3 | import android.text.Editable;
4 | import android.text.TextWatcher;
5 |
6 | /**
7 | * Created by ddq on 2016/11/7.
8 | */
9 | public class NumberTextWatcher implements TextWatcher {
10 | private int integer;//整数部分位数
11 | private int decimal;//小数部分位数
12 |
13 | public NumberTextWatcher(int integer, int decimal) {
14 | this.integer = integer;
15 | this.decimal = decimal;
16 | if (integer < 0)
17 | this.integer = 0;
18 | if (decimal < 0)
19 | this.decimal = 0;
20 | }
21 |
22 | public NumberTextWatcher() {
23 | this(9, 3);
24 | }
25 |
26 | @Override
27 | public void beforeTextChanged(CharSequence s, int start, int count, int after) {
28 |
29 | }
30 |
31 | @Override
32 | public void onTextChanged(CharSequence s, int start, int before, int count) {
33 |
34 | }
35 |
36 | @Override
37 | public void afterTextChanged(Editable s) {
38 | int index = s.toString().indexOf(".");
39 | if (index > -1) {
40 | if (index == 0) {
41 | s.insert(0, "0");
42 | }
43 |
44 | if (index < s.length() - 1) {
45 | CharSequence sub = s.subSequence(index + 1, s.length());
46 | if (sub.length() > decimal) {
47 | s.delete(index + decimal + 1, s.length());
48 | }
49 | }
50 |
51 | if (index > integer) {
52 | s.delete(integer, index);
53 | }
54 | } else {
55 | if (s.length() > integer) {
56 | s.delete(integer, s.length());
57 | }
58 | }
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/util/ViewUtil.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.util;
2 |
3 | import android.annotation.TargetApi;
4 | import android.graphics.Rect;
5 | import android.graphics.drawable.Drawable;
6 | import android.os.Build;
7 | import android.view.TouchDelegate;
8 | import android.view.View;
9 |
10 | import androidx.annotation.ColorInt;
11 | import androidx.annotation.DrawableRes;
12 |
13 | /**
14 | * 创建时间:2018/7/23
15 | * 编写人: chengxin
16 | * 功能描述:view帮助类
17 | */
18 | public class ViewUtil {
19 |
20 | @SuppressWarnings("deprecation")
21 | @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
22 | public static void setBackgroundKeepingPadding(View view, Drawable drawable) {
23 | int[] padding = new int[]{view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()};
24 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
25 | view.setBackground(drawable);
26 | } else {
27 | view.setBackgroundDrawable(drawable);
28 | }
29 | view.setPadding(padding[0], padding[1], padding[2], padding[3]);
30 | }
31 |
32 | @SuppressWarnings("deprecation")
33 | public static void setBackgroundKeepingPadding(View view, @DrawableRes int backgroundResId) {
34 | setBackgroundKeepingPadding(view, view.getResources().getDrawable(backgroundResId));
35 | }
36 |
37 | public static void setBackgroundColorKeepPadding(View view, @ColorInt int color) {
38 | int[] padding = new int[]{view.getPaddingLeft(), view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()};
39 | view.setBackgroundColor(color);
40 | view.setPadding(padding[0], padding[1], padding[2], padding[3]);
41 | }
42 |
43 | /**
44 | * 扩展点击区域的范围
45 | *
46 | * @param view 需要扩展的元素,此元素必需要有父级元素
47 | * @param expendSize 需要扩展的尺寸(以sp为单位的)
48 | */
49 | public static void expendTouchArea(final View view, final int expendSize) {
50 | if (view != null) {
51 | final View parentView = (View) view.getParent();
52 | parentView.post(new Runnable() {
53 | @Override
54 | public void run() {
55 | Rect rect = new Rect();
56 | view.getHitRect(rect); //如果太早执行本函数,会获取rect失败,因为此时UI界面尚未开始绘制,无法获得正确的坐标
57 | rect.left -= expendSize;
58 | rect.top -= expendSize;
59 | rect.right += expendSize;
60 | rect.bottom += expendSize;
61 | parentView.setTouchDelegate(new TouchDelegate(rect, view));
62 | }
63 | });
64 | }
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/widget/CheckView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.widget;
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.Paint;
8 | import android.graphics.PorterDuff;
9 | import android.graphics.PorterDuffXfermode;
10 | import android.graphics.Rect;
11 | import android.graphics.drawable.Drawable;
12 | import androidx.annotation.IntRange;
13 | import androidx.core.content.res.ResourcesCompat;
14 | import android.util.AttributeSet;
15 | import android.view.View;
16 | import android.widget.Checkable;
17 |
18 | import com.xcheng.view.R;
19 | import com.xcheng.view.util.LocalDisplay;
20 |
21 | import static com.xcheng.view.widget.ProgressView.TYPE_CIRCLE;
22 |
23 | public class CheckView extends View implements Checkable {
24 | //圆框的颜色
25 | private int mStrokeWidth; // dp
26 | //圆框的尺寸
27 | private int mSize; // dp
28 | //圆框的颜色
29 | private int mStrokeColor;
30 | //圆框内填充的颜色
31 | private int mbgColor;
32 | //选中的颜色
33 | private int mCheckedColor;
34 | private boolean mChecked;
35 | private Paint mStrokePaint;
36 | private Paint mBackgroundPaint;
37 | private Drawable mCheckDrawable;
38 | private Rect mCheckRect;
39 | private Rect mBgRect;
40 | private Rect mStrokeRect;
41 |
42 | private int mType;
43 |
44 | public CheckView(Context context) {
45 | this(context, null);
46 | }
47 |
48 | public CheckView(Context context, AttributeSet attrs) {
49 | this(context, attrs, 0);
50 | }
51 |
52 | public CheckView(Context context, AttributeSet attrs, int defStyleAttr) {
53 | super(context, attrs, defStyleAttr);
54 | init(context, attrs, defStyleAttr);
55 | }
56 |
57 |
58 | private void init(Context context, AttributeSet attrs, int defStyleAttr) {
59 | TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.CheckView, defStyleAttr, 0);
60 | mSize = ta.getDimensionPixelSize(R.styleable.CheckView_ev_size, LocalDisplay.dp2px(18));
61 | mType = ta.getInt(R.styleable.CheckView_ev_type, TYPE_CIRCLE);
62 |
63 | mStrokeWidth = ta.getDimensionPixelSize(R.styleable.CheckView_ev_strokeWidth, LocalDisplay.dp2px(2));
64 | mStrokeColor = ta.getColor(R.styleable.CheckView_ev_strokeColor, Color.parseColor("#c2c9cc"));
65 | mbgColor = ta.getColor(R.styleable.CheckView_ev_bgColor, Color.TRANSPARENT);
66 | mCheckedColor = ta.getColor(R.styleable.CheckView_ev_checkedColor, Color.parseColor("#0bd38a"));
67 | mChecked = ta.getBoolean(R.styleable.CheckView_android_checked, false);
68 | ta.recycle();
69 |
70 | mStrokePaint = new Paint();
71 | mStrokePaint.setAntiAlias(true);
72 | mStrokePaint.setStyle(Paint.Style.STROKE);
73 | mStrokePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OVER));
74 | mStrokePaint.setStrokeWidth(mStrokeWidth);
75 | mStrokePaint.setColor(mStrokeColor);
76 | mCheckDrawable = ResourcesCompat.getDrawable(context.getResources(),
77 | R.drawable.ic_check_white_18dp, context.getTheme());
78 |
79 | mBackgroundPaint = new Paint();
80 | mBackgroundPaint.setAntiAlias(true);
81 | mBackgroundPaint.setStyle(Paint.Style.FILL);
82 |
83 | mCheckRect = getSquareRect(0);
84 | mBgRect = getSquareRect(mStrokeWidth);
85 | mStrokeRect = getSquareRect(mStrokeWidth / 2);
86 |
87 | }
88 |
89 | @Override
90 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
91 | setMeasuredDimension(mSize + mStrokeWidth * 2 + getPaddingLeft() + getPaddingRight(),
92 | mSize + mStrokeWidth * 2 + getPaddingTop() + getPaddingBottom());
93 | }
94 |
95 | @Override
96 | public void setChecked(boolean checked) {
97 | mChecked = checked;
98 | invalidate();
99 | }
100 |
101 | @Override
102 | public boolean isChecked() {
103 | return mChecked;
104 | }
105 |
106 | @Override
107 | public void toggle() {
108 | setChecked(!mChecked);
109 | }
110 |
111 | @Override
112 | protected void onDraw(Canvas canvas) {
113 | super.onDraw(canvas);
114 | if (mChecked) {
115 | mBackgroundPaint.setColor(mCheckedColor);
116 | if (mType == ProgressView.TYPE_CIRCLE) {
117 | canvas.drawCircle(getPaddingLeft() + mStrokeWidth + mSize / 2,
118 | getPaddingTop() + mStrokeWidth + mSize / 2,
119 | mStrokeWidth + mSize / 2, mBackgroundPaint);
120 | } else {
121 | canvas.drawRect(mBgRect, mBackgroundPaint);
122 | }
123 | mCheckDrawable.setBounds(mCheckRect);
124 | mCheckDrawable.draw(canvas);
125 | } else {
126 | mBackgroundPaint.setColor(mbgColor);
127 | if (mType == ProgressView.TYPE_CIRCLE) {
128 | //渲染这个圆形背景
129 | canvas.drawCircle(getPaddingLeft() + mStrokeWidth + mSize / 2,
130 | getPaddingTop() + mStrokeWidth + mSize / 2,
131 | mSize / 2 + mStrokeWidth, mBackgroundPaint);
132 | //渲染这个圆形边框
133 | canvas.drawCircle(getPaddingLeft() + mStrokeWidth + mSize / 2,
134 | getPaddingTop() + mStrokeWidth + mSize / 2,
135 | (mStrokeWidth + mSize) / 2/*Paint.Style.STROKE的情况下画笔在StrokeWidth中间*/, mStrokePaint);
136 | } else {
137 | //渲染这个方形背景
138 | canvas.drawRect(mBgRect, mBackgroundPaint);
139 | //渲染这个方形边框
140 | canvas.drawRect(mStrokeRect, mStrokePaint);
141 | }
142 | }
143 | // enable hint
144 | setAlpha(isEnabled() ? 1.0f : 0.5f);
145 | }
146 |
147 |
148 | private Rect getSquareRect(@IntRange(from = 0) int offset) {
149 | int centerX = getPaddingLeft() + mStrokeWidth + mSize / 2;
150 | int centerY = getPaddingTop() + mStrokeWidth + mSize / 2;
151 | return new Rect(centerX - mSize / 2 - offset, centerY - mSize / 2 - offset,
152 | centerX + mSize / 2 + offset, centerY + mSize / 2 + offset);
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/widget/LoadingView.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.widget;
2 |
3 | import android.animation.ValueAnimator;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.graphics.Canvas;
7 | import android.graphics.Color;
8 | import android.graphics.Paint;
9 | import android.util.AttributeSet;
10 | import android.view.View;
11 | import android.view.animation.LinearInterpolator;
12 |
13 | import androidx.annotation.NonNull;
14 |
15 | import com.xcheng.view.R;
16 | import com.xcheng.view.util.LocalDisplay;
17 |
18 | /**
19 | * 用于显示 Loading 的 {@link View},支持颜色和大小的设置。
20 | * https://github.com/Tencent/QMUI_Android/blob/b6993d99de35ce20de48e67332856cfec5ff3cb0/qmui/src/main/java/com/qmuiteam/qmui/widget/QMUILoadingView.java
21 | *
22 | * @author cginechen
23 | * @date 2016-09-21
24 | */
25 | public class LoadingView extends View {
26 | private int mSize;
27 | private int mPaintColor;
28 | private int mAnimateValue = 0;
29 | private ValueAnimator mAnimator;
30 | private Paint mPaint;
31 | private static final int LINE_COUNT = 12;
32 | private static final int DEGREE_PER_LINE = 360 / LINE_COUNT;
33 |
34 | public LoadingView(Context context) {
35 | this(context, null);
36 | }
37 |
38 | public LoadingView(Context context, AttributeSet attrs) {
39 | this(context, attrs, 0);
40 | }
41 |
42 | public LoadingView(Context context, AttributeSet attrs, int defStyleAttr) {
43 | super(context, attrs, defStyleAttr);
44 | TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.LoadingView, defStyleAttr, 0);
45 | mSize = array.getDimensionPixelSize(R.styleable.LoadingView_ev_loading_view_size, LocalDisplay.dp2px(20));
46 | mPaintColor = array.getInt(R.styleable.LoadingView_android_color, Color.GRAY);
47 | array.recycle();
48 | initPaint();
49 | }
50 |
51 | public LoadingView(Context context, int size, int color) {
52 | super(context);
53 | mSize = size;
54 | mPaintColor = color;
55 | initPaint();
56 | }
57 |
58 | private void initPaint() {
59 | mPaint = new Paint();
60 | mPaint.setColor(mPaintColor);
61 | mPaint.setAntiAlias(true);
62 | mPaint.setStrokeCap(Paint.Cap.ROUND);
63 | }
64 |
65 | public void setColor(int color) {
66 | mPaintColor = color;
67 | mPaint.setColor(color);
68 | invalidate();
69 | }
70 |
71 | public void setSize(int size) {
72 | mSize = size;
73 | requestLayout();
74 | }
75 |
76 | private ValueAnimator.AnimatorUpdateListener mUpdateListener = new ValueAnimator.AnimatorUpdateListener() {
77 | @Override
78 | public void onAnimationUpdate(ValueAnimator animation) {
79 | mAnimateValue = (int) animation.getAnimatedValue();
80 | invalidate();
81 | }
82 | };
83 |
84 | public void start() {
85 | if (mAnimator == null) {
86 | mAnimator = ValueAnimator.ofInt(0, LINE_COUNT - 1);
87 | mAnimator.addUpdateListener(mUpdateListener);
88 | mAnimator.setDuration(600);
89 | mAnimator.setRepeatMode(ValueAnimator.RESTART);
90 | mAnimator.setRepeatCount(ValueAnimator.INFINITE);
91 | mAnimator.setInterpolator(new LinearInterpolator());
92 | mAnimator.start();
93 | } else if (!mAnimator.isStarted()) {
94 | mAnimator.start();
95 | }
96 | }
97 |
98 | public void stop() {
99 | if (mAnimator != null) {
100 | mAnimator.removeUpdateListener(mUpdateListener);
101 | mAnimator.removeAllUpdateListeners();
102 | mAnimator.cancel();
103 | mAnimator = null;
104 | }
105 | }
106 |
107 | private void drawLoading(Canvas canvas, int rotateDegrees) {
108 | int width = mSize / 12, height = mSize / 6;
109 | mPaint.setStrokeWidth(width);
110 |
111 | canvas.rotate(rotateDegrees, mSize / 2, mSize / 2);
112 | canvas.translate(mSize / 2, mSize / 2);
113 |
114 | for (int i = 0; i < LINE_COUNT; i++) {
115 | canvas.rotate(DEGREE_PER_LINE);
116 | mPaint.setAlpha((int) (255f * (i + 1) / LINE_COUNT));
117 | canvas.translate(0, -mSize / 2 + width / 2);
118 | canvas.drawLine(0, 0, 0, height, mPaint);
119 | canvas.translate(0, mSize / 2 - width / 2);
120 | }
121 | }
122 |
123 | @Override
124 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
125 | setMeasuredDimension(mSize, mSize);
126 | }
127 |
128 | @Override
129 | protected void onDraw(Canvas canvas) {
130 | super.onDraw(canvas);
131 | int saveCount = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
132 | drawLoading(canvas, mAnimateValue * DEGREE_PER_LINE);
133 | canvas.restoreToCount(saveCount);
134 | }
135 |
136 | @Override
137 | protected void onAttachedToWindow() {
138 | super.onAttachedToWindow();
139 | start();
140 | }
141 |
142 | @Override
143 | protected void onDetachedFromWindow() {
144 | super.onDetachedFromWindow();
145 | stop();
146 | }
147 |
148 | @Override
149 | protected void onVisibilityChanged(@NonNull View changedView, int visibility) {
150 | super.onVisibilityChanged(changedView, visibility);
151 | if (visibility == VISIBLE) {
152 | start();
153 | } else {
154 | stop();
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/widget/ScaleTransformer.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.widget;
2 |
3 | import android.view.View;
4 |
5 | /**
6 | * Created by chensuilun on 2016/12/16.
7 | */
8 | public class ScaleTransformer implements GalleryLayoutManager.ItemTransformer {
9 |
10 | private static final String TAG = "CurveTransformer";
11 |
12 | @Override
13 | public void transformItem(GalleryLayoutManager layoutManager, View item, float fraction) {
14 | item.setPivotX(item.getWidth() / 2.f);
15 | item.setPivotY(item.getHeight() / 2.0f);
16 | float scale = 1 - 0.2f * Math.abs(fraction);
17 | item.setScaleX(scale);
18 | item.setScaleY(scale);
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/widget/TopBarLayout.java:
--------------------------------------------------------------------------------
1 | package com.xcheng.view.widget;
2 |
3 | import android.annotation.TargetApi;
4 | import android.content.Context;
5 | import android.content.res.TypedArray;
6 | import android.os.Build;
7 | import android.text.TextUtils;
8 | import android.util.AttributeSet;
9 | import android.view.LayoutInflater;
10 | import android.widget.LinearLayout;
11 | import android.widget.TextView;
12 |
13 | import com.xcheng.view.R;
14 |
15 | /**
16 | * 封装Toolbar 添加到TopBarLayout成为其第一个子控件,实现Toolbar布局文件的复用
17 | * Created by chengxin on 2017/5/2.
18 | */
19 | public class TopBarLayout extends LinearLayout {
20 |
21 | public TopBarLayout(Context context) {
22 | this(context, null);
23 | }
24 |
25 | public TopBarLayout(Context context, AttributeSet attrs) {
26 | this(context, attrs, 0);
27 | }
28 |
29 | public TopBarLayout(Context context, AttributeSet attrs, int defStyleAttr) {
30 | super(context, attrs, defStyleAttr);
31 | initTopBar(attrs);
32 | }
33 |
34 | @TargetApi(Build.VERSION_CODES.LOLLIPOP)
35 | public TopBarLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
36 | super(context, attrs, defStyleAttr, defStyleRes);
37 | initTopBar(attrs);
38 | }
39 |
40 | private void initTopBar(AttributeSet attrs) {
41 | setOrientation(VERTICAL);
42 | final TypedArray a = getContext().obtainStyledAttributes(attrs,
43 | R.styleable.TopBarLayout);
44 | int topBarLayoutId = a.getResourceId(R.styleable.TopBarLayout_ev_topBarLayout, 0);
45 | CharSequence topBarTitle = a.getText(R.styleable.TopBarLayout_ev_topBarTitle);
46 | a.recycle();
47 | if (topBarLayoutId != 0) {
48 | //设置Toolbar
49 | LayoutInflater.from(getContext()).inflate(topBarLayoutId, this);
50 | }
51 | if (!TextUtils.isEmpty(topBarTitle)) {
52 | TextView titleView = (TextView) findViewById(R.id.ev_id_titleView);
53 | if (titleView != null) {
54 | titleView.setText(topBarTitle);
55 | }
56 | }
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/widget/smarttab/SmartTabIndicationInterpolator.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2015 ogaclejapan
3 | * Copyright (C) 2013 The Android Open Source Project
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.xcheng.view.widget.smarttab;
18 |
19 | import android.view.animation.AccelerateInterpolator;
20 | import android.view.animation.DecelerateInterpolator;
21 | import android.view.animation.Interpolator;
22 |
23 | public abstract class SmartTabIndicationInterpolator {
24 | static final int ID_SMART = 0;
25 | static final int ID_LINEAR = 1;
26 |
27 | public static SmartTabIndicationInterpolator of(int id) {
28 | switch (id) {
29 | case ID_SMART:
30 | return SmartIndicationInterpolator.DEFAULT;
31 | case ID_LINEAR:
32 | return LinearIndicationInterpolator.DEFAULT;
33 | default:
34 | throw new IllegalArgumentException("Unknown id: " + id);
35 | }
36 | }
37 |
38 | public abstract float getLeftEdge(float offset);
39 |
40 | public abstract float getRightEdge(float offset);
41 |
42 | public float getThickness(float offset) {
43 | return 1f; //Always the same thickness by default
44 | }
45 |
46 | public static class SmartIndicationInterpolator extends SmartTabIndicationInterpolator {
47 | static final SmartTabIndicationInterpolator DEFAULT = new SmartIndicationInterpolator();
48 |
49 | private static final float DEFAULT_INDICATOR_INTERPOLATION_FACTOR = 3.0f;
50 |
51 | private final Interpolator leftEdgeInterpolator;
52 | private final Interpolator rightEdgeInterpolator;
53 |
54 | public SmartIndicationInterpolator() {
55 | this(DEFAULT_INDICATOR_INTERPOLATION_FACTOR);
56 | }
57 |
58 | public SmartIndicationInterpolator(float factor) {
59 | leftEdgeInterpolator = new AccelerateInterpolator(factor);
60 | rightEdgeInterpolator = new DecelerateInterpolator(factor);
61 | }
62 |
63 | @Override
64 | public float getLeftEdge(float offset) {
65 | return leftEdgeInterpolator.getInterpolation(offset);
66 | }
67 |
68 | @Override
69 | public float getRightEdge(float offset) {
70 | return rightEdgeInterpolator.getInterpolation(offset);
71 | }
72 |
73 | @Override
74 | public float getThickness(float offset) {
75 | return 1f / (1.0f - getLeftEdge(offset) + getRightEdge(offset));
76 | }
77 |
78 | }
79 |
80 | public static class LinearIndicationInterpolator extends SmartTabIndicationInterpolator {
81 | static final SmartTabIndicationInterpolator DEFAULT = new LinearIndicationInterpolator();
82 |
83 | @Override
84 | public float getLeftEdge(float offset) {
85 | return offset;
86 | }
87 |
88 | @Override
89 | public float getRightEdge(float offset) {
90 | return offset;
91 | }
92 |
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/library/src/main/java/com/xcheng/view/widget/smarttab/Utils.java:
--------------------------------------------------------------------------------
1 | /**
2 | * Copyright (C) 2015 ogaclejapan
3 | * Copyright (C) 2013 The Android Open Source Project
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License");
6 | * you may not use this file except in compliance with the License.
7 | * You may obtain a copy of the License at
8 | *
9 | * http://www.apache.org/licenses/LICENSE-2.0
10 | *
11 | * Unless required by applicable law or agreed to in writing, software
12 | * distributed under the License is distributed on an "AS IS" BASIS,
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 | * See the License for the specific language governing permissions and
15 | * limitations under the License.
16 | */
17 | package com.xcheng.view.widget.smarttab;
18 |
19 | import androidx.core.view.MarginLayoutParamsCompat;
20 | import androidx.core.view.ViewCompat;
21 | import android.view.View;
22 | import android.view.ViewGroup;
23 |
24 | final class Utils {
25 |
26 | static int getMeasuredWidth(View v) {
27 | return (v == null) ? 0 : v.getMeasuredWidth();
28 | }
29 |
30 | static int getWidth(View v) {
31 | return (v == null) ? 0 : v.getWidth();
32 | }
33 |
34 | static int getWidthWithMargin(View v) {
35 | return getWidth(v) + getMarginHorizontally(v);
36 | }
37 |
38 | static int getStart(View v) {
39 | return getStart(v, false);
40 | }
41 |
42 | static int getStart(View v, boolean withoutPadding) {
43 | if (v == null) {
44 | return 0;
45 | }
46 | if (isLayoutRtl(v)) {
47 | return (withoutPadding) ? v.getRight() - getPaddingStart(v) : v.getRight();
48 | } else {
49 | return (withoutPadding) ? v.getLeft() + getPaddingStart(v) : v.getLeft();
50 | }
51 | }
52 |
53 | static int getEnd(View v) {
54 | return getEnd(v, false);
55 | }
56 |
57 | static int getEnd(View v, boolean withoutPadding) {
58 | if (v == null) {
59 | return 0;
60 | }
61 | if (isLayoutRtl(v)) {
62 | return (withoutPadding) ? v.getLeft() + getPaddingEnd(v) : v.getLeft();
63 | } else {
64 | return (withoutPadding) ? v.getRight() - getPaddingEnd(v) : v.getRight();
65 | }
66 | }
67 |
68 | static int getPaddingStart(View v) {
69 | if (v == null) {
70 | return 0;
71 | }
72 | return ViewCompat.getPaddingStart(v);
73 | }
74 |
75 | static int getPaddingEnd(View v) {
76 | if (v == null) {
77 | return 0;
78 | }
79 | return ViewCompat.getPaddingEnd(v);
80 | }
81 |
82 | static int getPaddingHorizontally(View v) {
83 | if (v == null) {
84 | return 0;
85 | }
86 | return v.getPaddingLeft() + v.getPaddingRight();
87 | }
88 |
89 | static int getMarginStart(View v) {
90 | if (v == null) {
91 | return 0;
92 | }
93 | ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
94 | return MarginLayoutParamsCompat.getMarginStart(lp);
95 | }
96 |
97 | static int getMarginEnd(View v) {
98 | if (v == null) {
99 | return 0;
100 | }
101 | ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
102 | return MarginLayoutParamsCompat.getMarginEnd(lp);
103 | }
104 |
105 | static int getMarginHorizontally(View v) {
106 | if (v == null) {
107 | return 0;
108 | }
109 | ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) v.getLayoutParams();
110 | return MarginLayoutParamsCompat.getMarginStart(lp) + MarginLayoutParamsCompat.getMarginEnd(lp);
111 | }
112 |
113 | static boolean isLayoutRtl(View v) {
114 | return ViewCompat.getLayoutDirection(v) == ViewCompat.LAYOUT_DIRECTION_RTL;
115 | }
116 |
117 | private Utils() { }
118 |
119 | }
120 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/ev_dialog_bottom_enter.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
10 |
--------------------------------------------------------------------------------
/library/src/main/res/anim/ev_dialog_bottom_exit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
9 |
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xhdpi/ev_ic_empty_data.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/library/src/main/res/drawable-xhdpi/ev_ic_empty_data.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xhdpi/ev_ic_network_error.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/library/src/main/res/drawable-xhdpi/ev_ic_network_error.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xhdpi/ic_check_white_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/library/src/main/res/drawable-xhdpi/ic_check_white_18dp.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxhdpi/ev_enter_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/library/src/main/res/drawable-xxhdpi/ev_enter_arrow.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxhdpi/ev_nav_back_arrow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/library/src/main/res/drawable-xxhdpi/ev_nav_back_arrow.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable-xxhdpi/ic_check_white_18dp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/xchengDroid/EasyView/086701db03cd1bfea832e77e114bc4f73febd1af/library/src/main/res/drawable-xxhdpi/ic_check_white_18dp.png
--------------------------------------------------------------------------------
/library/src/main/res/drawable/ev_shape_bg_dialog_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_commom_view.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
16 |
17 |
23 |
24 |
29 |
30 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_dialog_loading.xml:
--------------------------------------------------------------------------------
1 |
2 |
10 |
11 |
14 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_dialog_option_bottom.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
18 |
19 |
25 |
26 |
32 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_item_module.xml:
--------------------------------------------------------------------------------
1 |
2 |
11 |
12 |
19 |
20 |
28 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_item_text.xml:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_pager.xml:
--------------------------------------------------------------------------------
1 |
6 |
7 |
19 |
20 |
25 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_smart_refresh.xml:
--------------------------------------------------------------------------------
1 |
2 |
13 |
14 |
15 |
19 |
20 |
25 |
26 |
30 |
31 |
--------------------------------------------------------------------------------
/library/src/main/res/layout/ev_toolbar.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #3F51B5
4 | #303F9F
5 | #FF4081
6 |
7 | #F2F2F2
8 |
9 | #ff0099cc
10 | #ff33b5e5
11 | #ff99cc00
12 | #ffaa66cc
13 | #ffff4444
14 |
15 | #ff00ddff
16 | #ff99cc00
17 | #ffffbb33
18 | #ffff4444
19 |
20 | #333333
21 | #78848d
22 | #c2c9cc
23 | #00ACF9
24 | #80000000
25 | #4d97ff
26 | #dae1e5
27 |
28 |
29 | #6633B5E5
30 |
31 | #00000000
32 | #ffffffff
33 | #ff000000
34 | #0BD38A
35 | #ffcc0000
36 |
--------------------------------------------------------------------------------
/library/src/main/res/values/dimens.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | 12sp
4 | 14sp
5 | 16sp
6 | 18sp
7 | 20sp
8 | 18sp
9 |
10 | 48dp
11 |
12 |
--------------------------------------------------------------------------------
/library/src/main/res/values/ids.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/library/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | EasyView
3 |
4 | 确定
5 | 提交
6 | 退出
7 | 跳过
8 | 登录
9 | 账号
10 | 用户名
11 | 登录名
12 | 密码
13 | 没有账号?
14 | 去注册
15 | 忘记密码?
16 | 下一步
17 | 注册
18 | 取消
19 | 重新加载
20 | 呼叫
21 | 网络异常
22 | 保存
23 | 删除
24 | 修改密码
25 |
26 |
27 |
--------------------------------------------------------------------------------
/library/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
15 |
16 |
19 |
20 |
23 |
24 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/library/src/main/res/values/themes.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
22 |
23 |
24 |
32 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app', ':library'
2 |
--------------------------------------------------------------------------------