.
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | /**
22 | * Hue Changed Listener
23 | *
24 | * 内部使用
25 | *
26 | * @author 焕晨HChen
27 | */
28 | public interface OnHueChangedListener {
29 | // 色相更改回调
30 | // 内部使用
31 | void onHueValueChanged(int value);
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorPickerType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.color;
20 |
21 | /**
22 | * 色盘类型
23 | *
24 | * @author 焕晨HChen
25 | */
26 | public enum ColorPickerType {
27 | // 最终值
28 | FINAL_COLOR,
29 | // 实时变化值
30 | COLOR_VALUE,
31 | HUE,
32 | LIGHTNESS,
33 | SATURATION,
34 | ALPHA
35 | }
36 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnRefreshViewListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | import com.hchen.himiuix.MiuixBasicView;
22 |
23 | /**
24 | * On Refresh View
25 | *
26 | * @author 焕晨HChen
27 | */
28 | public interface OnRefreshViewListener {
29 | // 视图刷新后回调
30 | void refreshed(MiuixBasicView view);
31 | }
32 |
--------------------------------------------------------------------------------
/src/main/res/drawable/ic_default_icon.xml:
--------------------------------------------------------------------------------
1 |
7 |
10 |
13 |
14 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnImeVisibilityChangedListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | /**
22 | * Ime Visibility Changed Listener
23 | *
24 | * @author 焕晨HChen
25 | */
26 | public interface OnImeVisibilityChangedListener {
27 | // Ime 可见性回调
28 | // 内部使用
29 | void visibilityChanged(boolean isShown);
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnItemSelectedListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | import androidx.annotation.NonNull;
22 |
23 | import com.hchen.himiuix.MiuixBottomNavigatorView;
24 |
25 | public interface OnItemSelectedListener {
26 | boolean onNavigationItemSelected(@NonNull MiuixBottomNavigatorView.MenuInfo item, boolean fromUser);
27 | }
28 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnStateChangeListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | /**
22 | * State Changed Listener
23 | *
24 | * @author 焕晨HChen
25 | */
26 | public interface OnStateChangeListener {
27 | /**
28 | * 开关状态更改时调用
29 | *
30 | * 返回 false 可阻止更改
31 | */
32 | boolean onStateChange(boolean newValue);
33 | }
34 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnColorChangedListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | import com.hchen.himiuix.color.ColorPickerType;
22 |
23 | /**
24 | * Color Changed Listener
25 | *
26 | * @author 焕晨HChen
27 | */
28 | public interface OnColorChangedListener {
29 | // 颜色更改时回调
30 | // 你可以接受 FINAL_COLOR 或 COLOR_VALUE 事件
31 | void onColorValueChanged(ColorPickerType type, int value);
32 | }
33 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnAppBarListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | import android.view.View;
22 |
23 | /**
24 | * OnAppBarListener
25 | *
26 | * @author 焕晨HChen
27 | */
28 | public interface OnAppBarListener {
29 | // 内部使用
30 | void targetStart(View view);
31 |
32 | void targetRegister(View view);
33 |
34 | void targetUnregister(View view);
35 |
36 | void targetDestroy(View view);
37 | }
38 |
--------------------------------------------------------------------------------
/src/main/res/drawable/miuix_up_down.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
11 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
HiMiuix
3 |
4 | 
5 | 
6 | 
7 | 
8 |
9 | [//]: # (
English | 简体中文
)
10 |
仿 Miuix 的 xml 式组件
11 |
12 |
13 | ### HiMiuiX
14 |
15 | #### Demo 项目:
16 |
17 | - [HiMiuixDemo](https://github.com/HChenX/HiMiuixDemo)
18 | - 欢迎下载体验!
19 |
20 | #### 展示:
21 |
22 | - Miuix About
23 | 
24 |
25 | ### 使用
26 |
27 | - 请做为模块在项目中导入使用!
28 |
29 | ```shell
30 | # 在你仓库中执行,将本仓库作为模块使用
31 | git submodule add https://github.com/HChenX/HiMiuix.git
32 | # 后续拉取本模块仓库
33 | git submodule update --init
34 | ```
35 |
36 | - 然后设置项目 settings.gradle 添加:
37 |
38 | ```groovy
39 | include ':HiMiuix'
40 | ```
41 |
42 | - 最后设置项目 app 下 build.gradle 文件,添加:
43 |
44 | ```groovy
45 | implementation(project(':HiMiuix'))
46 | ```
47 |
48 | - tip: 请确保导入并使用了 `com.android.library`
49 |
50 | #### 开源许可
51 |
52 | - 本项目遵循 LGPL-2.1 开源协议。
53 | - 使用本项目请在项目中注明!
54 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorPickerData.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.color;
20 |
21 | import android.graphics.Color;
22 |
23 |
24 | /**
25 | * 颜色数值储存类
26 | *
27 | * @author 焕晨HChen
28 | */
29 | class ColorPickerData {
30 | int hue;
31 | int saturation;
32 | int lightness = 10000;
33 | int alpha = 255;
34 |
35 | int HSVToColor() {
36 | return Color.HSVToColor(alpha, new float[]{(float) hue / 100, (float) saturation / 10000, (float) lightness / 10000});
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/springback/ViewCompatOnScrollChangeListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.springback;
20 |
21 | import android.view.View;
22 |
23 | /**
24 | * ViewCompatOnScrollChangeListener
25 | *
26 | * 改编自 HyperOS 2
27 | *
28 | * @author 焕晨HChen
29 | */
30 | public interface ViewCompatOnScrollChangeListener {
31 | void onStateChanged(int oldState, int state, boolean finished);
32 |
33 | void onScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY);
34 | }
35 |
--------------------------------------------------------------------------------
/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | -keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
22 |
23 | -keep class * extends com.hchen.himiuix.fragment.Fragment
24 | -keep class * extends com.hchen.himiuix.fragment.PreferenceFragmentCompat
25 | -keep class androidx.preference.Preference {
26 | private boolean mWasDetached;
27 | private java.lang.String mDependencyKey;
28 | }
29 | -keep class androidx.preference.PreferenceGroup {
30 | private final java.util.List mPreferences;
31 | }
32 | -keep class androidx.appcompat.widget.Toolbar {
33 | android.view.View getNavButtonView();
34 | }
--------------------------------------------------------------------------------
/src/main/res/anim/miuix_checkbox_off_to_on.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 |
17 |
24 |
32 |
--------------------------------------------------------------------------------
/src/main/res/layout/miuix_item.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
13 |
14 |
23 |
24 |
32 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnChooseItemListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | /**
22 | * List 条目选中回调
23 | *
24 | * @author 焕晨HChen
25 | */
26 | public interface OnChooseItemListener {
27 | /**
28 | * 选中条目前回调
29 | *
30 | * 可以在此处阻止选中本条目
31 | */
32 | default boolean onChooseBefore(CharSequence item, int which) {
33 | return true;
34 | }
35 |
36 | /**
37 | * 选中条目后回调
38 | *
39 | * 在此处可用获取当前已选中的所有条目
40 | */
41 | default void onChooseAfter(CharSequence[] items, CharSequence[] selectedItems, Integer[] selectedValues) {
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/OnCheckedChangeListener.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | import androidx.annotation.IdRes;
22 |
23 | import com.hchen.himiuix.MiuixRadioGroup;
24 | import com.hchen.himiuix.preference.MiuixRadioButtonPreference;
25 |
26 | /**
27 | * Group Changed Listener
28 | *
29 | * @author 焕晨HChen
30 | */
31 | public interface OnCheckedChangeListener {
32 | // 普通 Radio 选中切换回调
33 | default void onCheckedChanged(MiuixRadioGroup group, @IdRes int checkedId) {
34 | }
35 |
36 | // Preference Radio 选中切换回调
37 | default void onCheckedChanged(MiuixRadioButtonPreference preference) {
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/src/main/res/layout/miuix_group_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
12 |
13 |
19 |
20 |
31 |
32 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/main/res/layout/miuix_vertical_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
22 |
23 |
29 |
30 |
36 |
37 |
42 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/fragment/Fragment.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.fragment;
20 |
21 | import androidx.annotation.CallSuper;
22 |
23 | import com.hchen.himiuix.helper.AppBarHelper;
24 |
25 | /**
26 | * 继承此 Fragment 才能使用 MiuixAppBar
27 | *
28 | * @author 焕晨HChen
29 | */
30 | public class Fragment extends androidx.fragment.app.Fragment {
31 | @Override
32 | @CallSuper
33 | public void onStart() {
34 | AppBarHelper.callTargetStart(getView());
35 | super.onStart();
36 | }
37 |
38 | @Override
39 | @CallSuper
40 | public void onResume() {
41 | AppBarHelper.callTargetRegister(getView());
42 | super.onResume();
43 | }
44 |
45 | @Override
46 | @CallSuper
47 | public void onPause() {
48 | AppBarHelper.callTargetUnregister(getView());
49 | super.onPause();
50 | }
51 |
52 | @Override
53 | @CallSuper
54 | public void onDestroyView() {
55 | AppBarHelper.onDestroyView(getView());
56 | super.onDestroyView();
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorPickerAlpha.java:
--------------------------------------------------------------------------------
1 | package com.hchen.himiuix.color;
2 |
3 | import android.content.Context;
4 | import android.graphics.Color;
5 | import android.util.AttributeSet;
6 |
7 | import androidx.annotation.FloatRange;
8 | import androidx.annotation.NonNull;
9 | import androidx.annotation.Nullable;
10 | import androidx.core.content.ContextCompat;
11 |
12 | import com.hchen.himiuix.R;
13 | import com.hchen.himiuix.callback.OnHueChangedListener;
14 |
15 | /**
16 | * Alpha 色盘
17 | *
18 | * @author 焕晨HChen
19 | */
20 | class ColorPickerAlpha extends ColorPickerBaseSeekBar implements OnHueChangedListener {
21 | public ColorPickerAlpha(@NonNull Context context) {
22 | super(context);
23 | }
24 |
25 | public ColorPickerAlpha(@NonNull Context context, @Nullable AttributeSet attrs) {
26 | super(context, attrs);
27 | }
28 |
29 | public ColorPickerAlpha(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
30 | super(context, attrs, defStyleAttr);
31 | }
32 |
33 | @Override
34 | void updateBasicInfo() {
35 | setType(ColorPickerType.ALPHA);
36 | setMax(255);
37 | setProgress(255);
38 | setColors(
39 | Color.HSVToColor(0, new float[]{0, 1, 1}),
40 | Color.HSVToColor(255, new float[]{0, 1, 1})
41 | );
42 | setColorPickerBackground(ContextCompat.getDrawable(getContext(), R.drawable.miuix_color_picker_alpha_bg));
43 | }
44 |
45 | @Override
46 | void setValue(@FloatRange(from = 0, to = 255) float value) {
47 | super.setValue(value);
48 | }
49 |
50 | @Override
51 | public void onHueValueChanged(int value) {
52 | setColors(
53 | Color.HSVToColor(0, new float[]{value, 1, 1}),
54 | Color.HSVToColor(255, new float[]{value, 1, 1})
55 | );
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/fragment/PreferenceFragmentCompat.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.fragment;
20 |
21 | import androidx.annotation.CallSuper;
22 |
23 | import com.hchen.himiuix.helper.AppBarHelper;
24 |
25 | /**
26 | * 继承此 Fragment 才能使用 MiuixAppBar
27 | *
28 | * @author 焕晨HChen
29 | */
30 | public abstract class PreferenceFragmentCompat extends androidx.preference.PreferenceFragmentCompat {
31 | @Override
32 | @CallSuper
33 | public void onStart() {
34 | AppBarHelper.callTargetStart(getView());
35 | super.onStart();
36 | }
37 |
38 | @Override
39 | @CallSuper
40 | public void onResume() {
41 | AppBarHelper.callTargetRegister(getView());
42 | super.onResume();
43 | }
44 |
45 | @CallSuper
46 | @Override public void onPause() {
47 | AppBarHelper.callTargetUnregister(getView());
48 | super.onPause();
49 | }
50 |
51 | @Override
52 | @CallSuper
53 | public void onDestroyView() {
54 | AppBarHelper.onDestroyView(getView());
55 | super.onDestroyView();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/dialog/MiuixAlertDialogFactory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.dialog;
20 |
21 | import android.app.Dialog;
22 | import android.content.Context;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.StyleRes;
26 | import androidx.annotation.UiContext;
27 |
28 | import com.hchen.himiuix.utils.MiuixUtils;
29 |
30 | /**
31 | * Miuix Dialog Factory
32 | *
33 | * @author 焕晨HChen
34 | */
35 | class MiuixAlertDialogFactory {
36 | @UiContext
37 | @NonNull
38 | private final Context context;
39 | private final int themeResId;
40 |
41 | MiuixAlertDialogFactory(@UiContext @NonNull Context context, @StyleRes int themeResId) {
42 | this.context = context;
43 | this.themeResId = themeResId;
44 | }
45 |
46 | public MiuixAlertDialogBase create() {
47 | Dialog dialog = new Dialog(context, themeResId);
48 | return MiuixUtils.isVerticalScreen(context) ? new MiuixAlertVerticalDialog(dialog) :
49 | MiuixUtils.isPad(context) ? new MiuixAlertVerticalDialog(dialog) : new MiuixAlertHorizontalDialog(dialog);
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/preference/MiuixSwitchPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.preference;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 |
27 | import com.hchen.himiuix.R;
28 |
29 | /**
30 | * Switch Preference
31 | *
32 | * @author 焕晨HChen
33 | */
34 | public class MiuixSwitchPreference extends MiuixStatePreference {
35 |
36 | public MiuixSwitchPreference(@NonNull Context context) {
37 | super(context);
38 | }
39 |
40 | public MiuixSwitchPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
41 | super(context, attrs);
42 | }
43 |
44 | public MiuixSwitchPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
45 | super(context, attrs, defStyleAttr);
46 | }
47 |
48 | public MiuixSwitchPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
49 | super(context, attrs, defStyleAttr, defStyleRes);
50 | }
51 |
52 | @Override
53 | int loadLayoutResource() {
54 | return R.layout.miuix_switch_preference;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/preference/MiuixCheckBoxPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.preference;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 |
27 | import com.hchen.himiuix.R;
28 |
29 | /**
30 | * CheckBox Preference
31 | *
32 | * @author 焕晨HChen
33 | */
34 | public class MiuixCheckBoxPreference extends MiuixStatePreference {
35 |
36 | public MiuixCheckBoxPreference(@NonNull Context context) {
37 | super(context);
38 | }
39 |
40 | public MiuixCheckBoxPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
41 | super(context, attrs);
42 | }
43 |
44 | public MiuixCheckBoxPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
45 | super(context, attrs, defStyleAttr);
46 | }
47 |
48 | public MiuixCheckBoxPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
49 | super(context, attrs, defStyleAttr, defStyleRes);
50 | }
51 |
52 | @Override
53 | int loadLayoutResource() {
54 | return R.layout.miuix_checkbox_preference;
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/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 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/callback/MiuixDialogInterface.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.callback;
20 |
21 | import android.view.View;
22 | import android.view.ViewGroup;
23 |
24 | import androidx.annotation.NonNull;
25 |
26 | /**
27 | * Dialog 回调接口
28 | *
29 | * @author 焕晨HChen
30 | */
31 | public interface MiuixDialogInterface {
32 | /**
33 | * 未知 Button
34 | *
35 | * 请勿使用
36 | */
37 | int BUTTON_NONE = 0;
38 | /**
39 | * 确认类型按钮
40 | */
41 | int BUTTON_POSITIVE = -1;
42 | /**
43 | * 拒绝类型按钮
44 | */
45 | int BUTTON_NEGATIVE = -2;
46 | /**
47 | * 自定义类型按钮
48 | */
49 | int BUTTON_NEUTRAL = -3;
50 |
51 | /**
52 | * 取消
53 | */
54 | void cancel();
55 |
56 | /**
57 | * 销毁
58 | */
59 | void dismiss();
60 |
61 | /**
62 | * 按钮点击回调
63 | */
64 | interface OnClickListener {
65 | void onClick(MiuixDialogInterface dialog, int which);
66 | }
67 |
68 | /**
69 | * 销毁时调用
70 | */
71 | interface OnDismissListener {
72 | void onDismiss(MiuixDialogInterface dialog);
73 | }
74 |
75 | /**
76 | * 显示时调用
77 | */
78 | interface OnShowListener {
79 | void onShow(MiuixDialogInterface dialog);
80 | }
81 |
82 | /**
83 | * 取消时调用
84 | */
85 | interface OnCancelListener {
86 | void onCancel(MiuixDialogInterface dialog);
87 | }
88 |
89 | /**
90 | * 绑定自定义视图时调用
91 | */
92 | interface OnBindViewListener {
93 | void onBindView(@NonNull ViewGroup root, @NonNull View view);
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/res/layout/miuix_horizontal_dialog.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
9 |
15 |
16 |
22 |
23 |
29 |
30 |
36 |
37 |
42 |
43 |
44 |
50 |
51 |
58 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorPickerLightness.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.color;
20 |
21 | import android.content.Context;
22 | import android.graphics.Color;
23 | import android.util.AttributeSet;
24 |
25 | import androidx.annotation.FloatRange;
26 | import androidx.annotation.NonNull;
27 | import androidx.annotation.Nullable;
28 |
29 | import com.hchen.himiuix.callback.OnHueChangedListener;
30 |
31 | /**
32 | * Lightness 色盘
33 | *
34 | * @author 焕晨HChen
35 | */
36 | class ColorPickerLightness extends ColorPickerBaseSeekBar implements OnHueChangedListener {
37 | public ColorPickerLightness(@NonNull Context context) {
38 | super(context);
39 | }
40 |
41 | public ColorPickerLightness(@NonNull Context context, @Nullable AttributeSet attrs) {
42 | super(context, attrs);
43 | }
44 |
45 | public ColorPickerLightness(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
46 | super(context, attrs, defStyleAttr);
47 | }
48 |
49 | @Override
50 | void updateBasicInfo() {
51 | setType(ColorPickerType.LIGHTNESS);
52 | setColors(
53 | Color.HSVToColor(new float[]{0, 1, 0}),
54 | Color.HSVToColor(new float[]{0, 1, 1})
55 | );
56 | setMax(10000);
57 | setProgress(10000);
58 | }
59 |
60 | @Override
61 | void setValue(@FloatRange(from = 0, to = 1) float value) {
62 | value = value * 10000;
63 | super.setValue(value);
64 | }
65 |
66 | @Override
67 | public void onHueValueChanged(int value) {
68 | setColors(
69 | Color.HSVToColor(new float[]{value, 1, 0}),
70 | Color.HSVToColor(new float[]{value, 1, 1})
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorPickerSaturation.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.color;
20 |
21 | import android.content.Context;
22 | import android.graphics.Color;
23 | import android.util.AttributeSet;
24 |
25 | import androidx.annotation.FloatRange;
26 | import androidx.annotation.NonNull;
27 | import androidx.annotation.Nullable;
28 |
29 | import com.hchen.himiuix.callback.OnHueChangedListener;
30 |
31 | /**
32 | * Saturation 色盘
33 | *
34 | * @author 焕晨HChen
35 | */
36 | class ColorPickerSaturation extends ColorPickerBaseSeekBar implements OnHueChangedListener {
37 | public ColorPickerSaturation(@NonNull Context context) {
38 | super(context);
39 | }
40 |
41 | public ColorPickerSaturation(@NonNull Context context, @Nullable AttributeSet attrs) {
42 | super(context, attrs);
43 | }
44 |
45 | public ColorPickerSaturation(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
46 | super(context, attrs, defStyleAttr);
47 | }
48 |
49 | @Override
50 | void updateBasicInfo() {
51 | setType(ColorPickerType.SATURATION);
52 | setColors(
53 | Color.HSVToColor(new float[]{0, 0, 1}),
54 | Color.HSVToColor(new float[]{0, 1, 1})
55 | );
56 | setMax(10000);
57 | setProgress(0);
58 | }
59 |
60 | @Override
61 | void setValue(@FloatRange(from = 0, to = 1) float value) {
62 | value = value * 10000;
63 | super.setValue(value);
64 | }
65 |
66 | @Override
67 | public void onHueValueChanged(int value) {
68 | setColors(
69 | Color.HSVToColor(new float[]{value, 0, 1}),
70 | Color.HSVToColor(new float[]{value, 1, 1})
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/preference/MiuixRadioButtonPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.preference;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 |
27 | import com.hchen.himiuix.R;
28 |
29 | /**
30 | * Radio Button Preference
31 | *
32 | * @author 焕晨HChen
33 | */
34 | public class MiuixRadioButtonPreference extends MiuixStatePreference {
35 | private OnInnerCheckedListener listener;
36 |
37 | public MiuixRadioButtonPreference(@NonNull Context context) {
38 | super(context);
39 | }
40 |
41 | public MiuixRadioButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
42 | super(context, attrs);
43 | }
44 |
45 | public MiuixRadioButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
46 | super(context, attrs, defStyleAttr);
47 | }
48 |
49 | public MiuixRadioButtonPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
50 | super(context, attrs, defStyleAttr, defStyleRes);
51 | }
52 |
53 | @Override
54 | int loadLayoutResource() {
55 | return R.layout.miuix_radio_button_preference;
56 | }
57 |
58 | void setOnInnerCheckedListener(OnInnerCheckedListener listener) {
59 | this.listener = listener;
60 | }
61 |
62 | @Override
63 | public boolean onStateChange(boolean newValue) {
64 | boolean change = super.onStateChange(newValue);
65 | if (change && newValue && listener != null)
66 | listener.onChecked(this);
67 |
68 | return change;
69 | }
70 |
71 | interface OnInnerCheckedListener {
72 | void onChecked(MiuixRadioButtonPreference preference);
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/springback/SpringOperator.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.springback;
20 |
21 | /**
22 | * SpringOperator
23 | *
24 | * 改编自 HyperOS 2
25 | *
26 | * @author 焕晨HChen
27 | */
28 | public class SpringOperator {
29 | private final double dampingCoefficient; // 阻尼系数 (c/m 或 2 * ζ * ω)
30 | private final double stiffnessOverMass; // 刚度与质量之比 (k/m 或 ω^2)
31 |
32 | /**
33 | * 创建一个新的 SpringOperator 实例
34 | *
35 | * @param dampingRatio 阻尼比 (ζ)。一个无量纲参数,描述振荡如何衰减
36 | * 0: 无阻尼; (0,1): 欠阻尼; 1: 临界阻尼; >1: 过阻尼
37 | * @param naturalPeriod 固有振荡周期 (T)。在无阻尼情况下,完成一次完整振荡所需的时间
38 | */
39 | public SpringOperator(float dampingRatio, float naturalPeriod) {
40 | if (naturalPeriod <= 0)
41 | throw new IllegalArgumentException("Natural period must be positive.");
42 |
43 | // 角频率 ω = 2π / T
44 | double angularFrequency = (2.0 * Math.PI) / naturalPeriod;
45 | // 张力 (或 k/m) = ω^2
46 | stiffnessOverMass = angularFrequency * angularFrequency;
47 | // 阻尼系数 (或 c/m) = 2 * ζ * ω
48 | dampingCoefficient = 2.0 * dampingRatio * angularFrequency;
49 | }
50 |
51 | /**
52 | * 根据当前状态使用简单的欧拉积分更新并返回弹簧系统的新速度
53 | *
54 | * @param currentVelocity 当前的速度
55 | * @param deltaTime 时间步长 (dt)
56 | * @param currentPosition 当前的位置
57 | * @param targetPosition 弹簧的目标位置或平衡位置
58 | * @return 更新后的速度
59 | */
60 | public double updateVelocity(double currentVelocity, float deltaTime, double currentPosition, double targetPosition) {
61 | double velocityDecayFactor = 1.0 - dampingCoefficient * deltaTime;
62 | double velocityIncreaseFromSpring = stiffnessOverMass * (targetPosition - currentPosition) * deltaTime;
63 |
64 | return currentVelocity * velocityDecayFactor + velocityIncreaseFromSpring;
65 | }
66 | }
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/helper/ImeHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.helper;
20 |
21 | import android.view.View;
22 |
23 | import androidx.annotation.NonNull;
24 | import androidx.core.view.OnApplyWindowInsetsListener;
25 | import androidx.core.view.WindowInsetsCompat;
26 |
27 | import com.hchen.himiuix.callback.OnImeVisibilityChangedListener;
28 |
29 | import java.util.HashSet;
30 |
31 | /**
32 | * Ime 监听
33 | *
34 | * @author 焕晨HChen
35 | */
36 | public class ImeHelper implements OnApplyWindowInsetsListener {
37 | private static final HashSet listeners = new HashSet<>();
38 | private static final ImeHelper imeHelper = new ImeHelper();
39 | private static boolean lastShown;
40 |
41 | public static ImeHelper init() {
42 | return imeHelper;
43 | }
44 |
45 | public static void addListeners(OnImeVisibilityChangedListener listener) {
46 | listeners.add(listener);
47 | }
48 |
49 | public static void removeListeners(OnImeVisibilityChangedListener listener) {
50 | listeners.remove(listener);
51 | }
52 |
53 | private static void checkAndRemoveListenersIfNeed() {
54 | listeners.removeIf(listener -> {
55 | if (listener instanceof View v) {
56 | return !v.isAttachedToWindow();
57 | }
58 | return false;
59 | });
60 | }
61 |
62 | @NonNull @Override
63 | public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) {
64 | checkAndRemoveListenersIfNeed();
65 | if (insets.isVisible(WindowInsetsCompat.Type.ime())) {
66 | listeners.forEach(listener -> listener.visibilityChanged(true));
67 | lastShown = true;
68 | } else if (lastShown) {
69 | listeners.forEach(listener -> listener.visibilityChanged(false));
70 | lastShown = false;
71 | }
72 | return insets;
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/main/res/values-night/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | @android:color/black
5 |
6 |
7 | #242424
8 | #F4F4F4
9 | #929292
10 | #929292
11 | #666666
12 |
13 |
14 | #FFFFFFFF
15 |
16 |
17 | #505050
18 | #4078EF
19 | @android:color/white
20 |
21 |
22 | #4078EF
23 | #505050
24 |
25 |
26 | #4078EF
27 |
28 |
29 | #797E94
30 | #26FFFFFF
31 |
32 |
33 | #242424
34 | #F4F4F4
35 | #D3D3D3
36 | #2F2F2F
37 | #434343
38 | #4078EF
39 | #D9D9D9
40 | #EBF1FD
41 |
42 |
43 | #F4F4F4
44 | #2C2C2C
45 | #4078EF
46 | #2F3B53
47 |
48 |
49 | #666666
50 |
51 |
52 | #434343
53 | #4078EF
54 | #4078EF
55 | #7C7C7C
56 |
57 |
58 | #29354D
59 | #4078EF
60 | #AA555962
61 |
62 |
63 | @android:color/black
64 |
65 |
66 | #505050
67 | #000000
68 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/utils/PropUtils.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.utils;
20 |
21 | import static com.hchen.himiuix.utils.InvokeUtils.callStaticMethod;
22 |
23 | import androidx.annotation.NonNull;
24 |
25 | import java.util.Optional;
26 |
27 | /**
28 | * Prop Utils
29 | *
30 | * @author 焕晨HChen
31 | */
32 | public class PropUtils {
33 | private static final Class> propClass = InvokeUtils.findClass("android.os.SystemProperties");
34 |
35 | private PropUtils() {
36 | }
37 |
38 | /**
39 | * 获取 boolean 类型的 prop
40 | */
41 | public static boolean getProp(@NonNull String key, boolean def) {
42 | return Boolean.TRUE.equals(
43 | callStaticMethod(propClass, "getBoolean", new Class[]{String.class, boolean.class}, key, def)
44 | );
45 | }
46 |
47 | /**
48 | * 获取 int 类型的 prop
49 | */
50 | public static int getProp(@NonNull String key, int def) {
51 | return (int) Optional.ofNullable(
52 | callStaticMethod(propClass, "getInt", new Class[]{String.class, int.class}, key, def)
53 | ).orElse(def);
54 | }
55 |
56 | /**
57 | * 获取 long 类型的 prop
58 | */
59 | public static long getProp(@NonNull String key, long def) {
60 | return (long) Optional.ofNullable(
61 | callStaticMethod(propClass, "getLong", new Class[]{String.class, long.class}, key, def)
62 | ).orElse(def);
63 | }
64 |
65 | /**
66 | * 获取 String 类型的 prop
67 | */
68 | public static String getProp(@NonNull String key, String def) {
69 | return (String) Optional.ofNullable(
70 | callStaticMethod(propClass, "get", new Class[]{String.class, String.class}, key, def)
71 | ).orElse(def);
72 | }
73 |
74 | /**
75 | * 获取 String 类型的 prop,无默认值
76 | */
77 | public static String getProp(@NonNull String key) {
78 | return callStaticMethod(propClass, "get", new Class[]{String.class}, key);
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/widget/MiuixTextView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.widget;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.util.AttributeSet;
24 | import android.view.Gravity;
25 |
26 | import androidx.annotation.NonNull;
27 | import androidx.annotation.Nullable;
28 | import androidx.appcompat.widget.AppCompatTextView;
29 |
30 | import com.hchen.himiuix.R;
31 |
32 | /**
33 | * Miuix TextView
34 | *
35 | * @author 焕晨HChen
36 | */
37 | public class MiuixTextView extends AppCompatTextView {
38 | private boolean focusable;
39 | private boolean singleLineCenter;
40 |
41 | public MiuixTextView(@NonNull Context context) {
42 | this(context, null);
43 | }
44 |
45 | public MiuixTextView(@NonNull Context context, @Nullable AttributeSet attrs) {
46 | this(context, attrs,0);
47 | }
48 |
49 | public MiuixTextView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
50 | super(context, attrs, defStyleAttr);
51 | init(context, attrs, defStyleAttr);
52 | }
53 |
54 | private void init(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
55 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.MiuixTextView, defStyleAttr, 0);
56 | focusable = array.getBoolean(R.styleable.MiuixTextView_android_focusable, false);
57 | singleLineCenter = array.getBoolean(R.styleable.MiuixTextView_singleLineCenter, false);
58 | array.recycle();
59 | }
60 |
61 | @Override
62 | public boolean isFocused() {
63 | return focusable;
64 | }
65 |
66 | @Override
67 | protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
68 | super.onMeasure(widthMeasureSpec, heightMeasureSpec);
69 | if (!singleLineCenter) return;
70 | if (getLineCount() <= 1) setGravity(Gravity.CENTER_HORIZONTAL);
71 | else setGravity(Gravity.LEFT);
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | #F7F7F7
5 |
6 |
7 | @android:color/white
8 | @android:color/black
9 | #666666
10 | #666666
11 | #B2B2B2
12 |
13 |
14 | #FF000000
15 |
16 |
17 | #E5E5E5
18 | #4980F7
19 | @android:color/white
20 |
21 |
22 | #4980F7
23 | #F0F0F0
24 |
25 |
26 | #4980F7
27 |
28 |
29 | #8D92AF
30 | #1A000000
31 |
32 |
33 | @android:color/white
34 | @android:color/black
35 | #333333
36 | #D8D8D8
37 | #F0F0F0
38 | #4980F7
39 | @android:color/black
40 | @android:color/white
41 |
42 |
43 | @android:color/black
44 | @android:color/white
45 | #487FF6
46 | #EAF0FC
47 |
48 |
49 | #B2B2B2
50 |
51 |
52 | #F0F0F0
53 | #4980F7
54 | #4980F7
55 | #A8A8A8
56 |
57 |
58 | #EBF1FD
59 | #4980F7
60 | #AAD7DDE9
61 |
62 |
63 | @android:color/white
64 |
65 |
66 | #F0F0F0
67 | #FFFFFF
68 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorPickerHue.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.color;
20 |
21 | import android.content.Context;
22 | import android.graphics.Color;
23 | import android.util.AttributeSet;
24 | import android.widget.SeekBar;
25 |
26 | import androidx.annotation.FloatRange;
27 | import androidx.annotation.NonNull;
28 | import androidx.annotation.Nullable;
29 |
30 | import com.hchen.himiuix.callback.OnHueChangedListener;
31 |
32 | import java.util.Arrays;
33 |
34 | /**
35 | * Hue 色盘
36 | *
37 | * @author 焕晨HChen
38 | */
39 | class ColorPickerHue extends ColorPickerBaseSeekBar {
40 | private OnHueChangedListener[] listeners;
41 |
42 | public ColorPickerHue(@NonNull Context context) {
43 | super(context);
44 | }
45 |
46 | public ColorPickerHue(@NonNull Context context, @Nullable AttributeSet attrs) {
47 | super(context, attrs);
48 | }
49 |
50 | public ColorPickerHue(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
51 | super(context, attrs, defStyleAttr);
52 | }
53 |
54 | @Override
55 | void updateBasicInfo() {
56 | setType(ColorPickerType.HUE);
57 | setColors(
58 | Color.HSVToColor(new float[]{0, 1, 1}),
59 | Color.HSVToColor(new float[]{60, 1, 1}),
60 | Color.HSVToColor(new float[]{120, 1, 1}),
61 | Color.HSVToColor(new float[]{180, 1, 1}),
62 | Color.HSVToColor(new float[]{240, 1, 1}),
63 | Color.HSVToColor(new float[]{300, 1, 1}),
64 | Color.HSVToColor(new float[]{360, 1, 1})
65 | );
66 | setMin(0);
67 | setMax(36000);
68 | setProgress(0);
69 | }
70 |
71 | void setListeners(OnHueChangedListener... listeners) {
72 | this.listeners = listeners;
73 | }
74 |
75 | @Override
76 | void setValue(@FloatRange(from = 0, to = 360) float value) {
77 | value = value * 100;
78 | super.setValue(value);
79 | callChanged();
80 | }
81 |
82 | @Override
83 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
84 | super.onProgressChanged(seekBar, progress, fromUser);
85 | if (listeners != null && fromUser) callChanged();
86 | }
87 |
88 | private void callChanged() {
89 | Arrays.stream(listeners).forEach(
90 | listener ->
91 | listener.onHueValueChanged(getValue() / 100)
92 | );
93 | }
94 | }
95 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/widget/MiuixRadioButton.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.widget;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.util.AttributeSet;
24 |
25 | import androidx.annotation.Nullable;
26 | import androidx.appcompat.widget.AppCompatRadioButton;
27 |
28 | import com.hchen.himiuix.R;
29 | import com.hchen.himiuix.callback.OnStateChangeListener;
30 |
31 | /**
32 | * Miuix Radio Button
33 | *
34 | * @author 焕晨HChen
35 | */
36 | public class MiuixRadioButton extends AppCompatRadioButton {
37 | private static final String TAG = "HiMiuix:RadioButton";
38 | private OnStateChangeListener onStateChangeListener;
39 |
40 | public MiuixRadioButton(Context context) {
41 | this(context, null);
42 | }
43 |
44 | public MiuixRadioButton(Context context, @Nullable AttributeSet attrs) {
45 | this(context, attrs, 0);
46 | }
47 |
48 | public MiuixRadioButton(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
49 | super(context, attrs, defStyleAttr);
50 | init(attrs, defStyleAttr);
51 | }
52 |
53 | private void init(@Nullable AttributeSet attrs, int defStyleAttr) {
54 | final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MiuixRadioButton, defStyleAttr, 0);
55 | int buttonId = typedArray.getResourceId(R.styleable.MiuixRadioButton_android_button, 0);
56 | typedArray.recycle();
57 |
58 | setClickable(true);
59 | setBackground(null);
60 | setSaveEnabled(false);
61 | setSaveFromParentEnabled(false);
62 | if (buttonId == 0) setButtonDrawable(R.drawable.miuix_radio_button);
63 | else setButtonDrawable(buttonId);
64 | }
65 |
66 | @Override
67 | public void toggle() {
68 | if (!isChecked())
69 | setUserChecked(!isChecked());
70 | }
71 |
72 | @Override
73 | public void setChecked(boolean checked) {
74 | if (isChecked() == checked) return;
75 | super.setChecked(checked);
76 | }
77 |
78 | // 当且仅当 onStateChange 拦截操作时才会返回 false
79 | public boolean setUserChecked(boolean checked) {
80 | if (isChecked() == checked) return true;
81 |
82 | if (onStateChangeListener == null || onStateChangeListener.onStateChange(checked)) {
83 | super.setChecked(checked);
84 | return true;
85 | }
86 | return false;
87 | }
88 |
89 | public void setOnStateChangeListener(OnStateChangeListener listener) {
90 | onStateChangeListener = listener;
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/preference/MiuixRadioGroupPreference.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.preference;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 | import androidx.preference.Preference;
27 |
28 | import com.hchen.himiuix.callback.OnCheckedChangeListener;
29 |
30 | import java.util.HashSet;
31 |
32 | /**
33 | * Radio Group Preference
34 | *
35 | * @author 焕晨HChen
36 | */
37 | public class MiuixRadioGroupPreference extends MiuixPreferenceCategory implements MiuixRadioButtonPreference.OnInnerCheckedListener {
38 | private final HashSet hashSet = new HashSet<>();
39 | private OnCheckedChangeListener listener;
40 |
41 | public MiuixRadioGroupPreference(@NonNull Context context, @Nullable AttributeSet attrs) {
42 | super(context, attrs);
43 | }
44 |
45 | public MiuixRadioGroupPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
46 | super(context, attrs, defStyleAttr);
47 | }
48 |
49 | public MiuixRadioGroupPreference(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
50 | super(context, attrs, defStyleAttr, defStyleRes);
51 | }
52 |
53 | @Override
54 | public boolean addPreference(@NonNull Preference preference) {
55 | if (preference instanceof MiuixRadioButtonPreference xRadioButtonPreference) {
56 | xRadioButtonPreference.setOnInnerCheckedListener(this);
57 | hashSet.add(xRadioButtonPreference);
58 | }
59 | return super.addPreference(preference);
60 | }
61 |
62 | @Override
63 | public boolean removePreference(@NonNull Preference preference) {
64 | if (preference instanceof MiuixRadioButtonPreference xRadioButtonPreference)
65 | hashSet.remove(xRadioButtonPreference);
66 | return super.removePreference(preference);
67 | }
68 |
69 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
70 | this.listener = listener;
71 | }
72 |
73 | private void updateCheckedState(MiuixRadioButtonPreference preference) {
74 | if (listener != null)
75 | listener.onCheckedChanged(preference);
76 |
77 | hashSet.forEach(x -> {
78 | if (!x.equals(preference))
79 | x.setChecked(false);
80 | });
81 | }
82 |
83 | @Override
84 | public void onChecked(MiuixRadioButtonPreference preference) {
85 | updateCheckedState(preference);
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/main/res/layout/miuix_color_picker.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
11 |
12 |
18 |
19 |
24 |
25 |
31 |
32 |
37 |
38 |
44 |
45 |
50 |
51 |
57 |
58 |
64 |
65 |
70 |
71 |
75 |
76 |
81 |
82 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/helper/WindowInsetsHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.helper;
20 |
21 | import android.app.Activity;
22 | import android.app.Application;
23 | import android.os.Bundle;
24 | import android.view.View;
25 |
26 | import androidx.annotation.NonNull;
27 | import androidx.annotation.Nullable;
28 | import androidx.core.view.OnApplyWindowInsetsListener;
29 | import androidx.core.view.ViewCompat;
30 | import androidx.core.view.WindowInsetsCompat;
31 |
32 | import java.util.HashSet;
33 |
34 | public class WindowInsetsHelper {
35 | private static final HashSet listeners = new HashSet<>();
36 | private static final Application.ActivityLifecycleCallbacks callbacks = new Application.ActivityLifecycleCallbacks() {
37 | @Override
38 | public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
39 | }
40 |
41 | @Override
42 | public void onActivityDestroyed(@NonNull Activity activity) {
43 | removeApplyWindowInsetsListener(null);
44 | activity.unregisterActivityLifecycleCallbacks(this);
45 | }
46 |
47 | @Override
48 | public void onActivityPaused(@NonNull Activity activity) {
49 | }
50 |
51 | @Override
52 | public void onActivityResumed(@NonNull Activity activity) {
53 | }
54 |
55 | @Override
56 | public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
57 | }
58 |
59 | @Override
60 | public void onActivityStarted(@NonNull Activity activity) {
61 | }
62 |
63 | @Override
64 | public void onActivityStopped(@NonNull Activity activity) {
65 | }
66 | };
67 |
68 | public static void initialWindowInsetsListener(Activity activity) {
69 | activity.registerActivityLifecycleCallbacks(callbacks);
70 |
71 | ViewCompat.setOnApplyWindowInsetsListener(activity.getWindow().getDecorView(), new OnApplyWindowInsetsListener() {
72 | @NonNull
73 | @Override
74 | public WindowInsetsCompat onApplyWindowInsets(@NonNull View v, @NonNull WindowInsetsCompat insets) {
75 | for (OnApplyWindowInsetsListener l : listeners) {
76 | l.onApplyWindowInsets(v, insets);
77 | }
78 | return insets;
79 | }
80 | });
81 | }
82 |
83 | public static void setOnApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
84 | listeners.add(listener);
85 | }
86 |
87 | public static void removeApplyWindowInsetsListener(OnApplyWindowInsetsListener listener) {
88 | if (listener != null) listeners.remove(listener);
89 | else listeners.clear();
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/MiuixSwitchView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 |
27 | import com.hchen.himiuix.callback.OnStateChangeListener;
28 | import com.hchen.himiuix.widget.MiuixSwitch;
29 |
30 | /**
31 | * Miuix Switch 视图
32 | *
33 | * @author 焕晨HChen
34 | */
35 | public class MiuixSwitchView extends MiuixStateView implements OnStateChangeListener {
36 | private MiuixSwitch xSwitch;
37 |
38 | public MiuixSwitchView(@NonNull Context context) {
39 | super(context);
40 | }
41 |
42 | public MiuixSwitchView(@NonNull Context context, @Nullable AttributeSet attrs) {
43 | super(context, attrs);
44 | }
45 |
46 | public MiuixSwitchView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
47 | super(context, attrs, defStyleAttr);
48 | }
49 |
50 | public MiuixSwitchView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
51 | super(context, attrs, defStyleAttr, defStyleRes);
52 | }
53 |
54 | @Override
55 | void loadViewWhenBuild() {
56 | super.loadViewWhenBuild();
57 | xSwitch = (MiuixSwitch) getIndicatorView();
58 | xSwitch.setOnStateChangeListener(this);
59 | }
60 |
61 | @Override
62 | DynamicIndicator loadDynamicIndicator() {
63 | return DynamicIndicator.INDICATOR_SWITCH;
64 | }
65 |
66 | @Override
67 | void updateVisibility() {
68 | super.updateVisibility();
69 | xSwitch.setVisibility(VISIBLE);
70 | }
71 |
72 | @Override
73 | void updateViewContent() {
74 | // 跳过非用户的 Check 动作
75 | if (!pass) {
76 | if (!xSwitch.setUserChecked(isChecked)) {
77 | isChecked = !isChecked; // 被拦截,还原
78 | }
79 | }
80 | super.updateViewContent();
81 | }
82 |
83 | @Override
84 | public boolean performClick() {
85 | isChecked = !isChecked;
86 | refreshView();
87 | return super.performClick();
88 | }
89 |
90 | @Override
91 | public boolean isChecked() {
92 | return isChecked;
93 | }
94 |
95 | @Override
96 | public void setChecked(boolean checked) {
97 | if (isChecked == checked) return;
98 | isChecked = checked;
99 | xSwitch.setChecked(checked);
100 | passRefreshStateView();
101 | }
102 |
103 | @Override
104 | public boolean onStateChange(boolean newValue) {
105 | if (listener == null || listener.onStateChange(newValue)) {
106 | isChecked = newValue;
107 | passRefreshStateView();
108 |
109 | return true;
110 | }
111 | return false;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/MiuixCheckBoxView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 |
24 | import androidx.annotation.NonNull;
25 | import androidx.annotation.Nullable;
26 |
27 | import com.hchen.himiuix.callback.OnStateChangeListener;
28 | import com.hchen.himiuix.widget.MiuixCheckBox;
29 |
30 | /**
31 | * Miuix 复选框视图
32 | *
33 | * @author 焕晨HChen
34 | */
35 | public class MiuixCheckBoxView extends MiuixStateView implements OnStateChangeListener {
36 | private MiuixCheckBox xCheckBox;
37 |
38 | public MiuixCheckBoxView(@NonNull Context context) {
39 | super(context);
40 | }
41 |
42 | public MiuixCheckBoxView(@NonNull Context context, @Nullable AttributeSet attrs) {
43 | super(context, attrs);
44 | }
45 |
46 | public MiuixCheckBoxView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
47 | super(context, attrs, defStyleAttr);
48 | }
49 |
50 | public MiuixCheckBoxView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
51 | super(context, attrs, defStyleAttr, defStyleRes);
52 | }
53 |
54 | @Override
55 | void loadViewWhenBuild() {
56 | super.loadViewWhenBuild();
57 | xCheckBox = (MiuixCheckBox) getIndicatorView();
58 | xCheckBox.setOnStateChangeListener(this);
59 | }
60 |
61 | @Override
62 | DynamicIndicator loadDynamicIndicator() {
63 | return DynamicIndicator.INDICATOR_CHECKBOX;
64 | }
65 |
66 | @Override
67 | void updateVisibility() {
68 | super.updateVisibility();
69 | xCheckBox.setVisibility(VISIBLE);
70 | }
71 |
72 | @Override
73 | void updateViewContent() {
74 | // 跳过执行非用户的 Check 动作
75 | if (!pass) {
76 | if (!xCheckBox.setUserChecked(isChecked)) {
77 | isChecked = !isChecked; // 被拦截,还原
78 | }
79 | }
80 | super.updateViewContent();
81 | }
82 |
83 | @Override
84 | public boolean performClick() {
85 | isChecked = !isChecked;
86 | refreshView();
87 | return super.performClick();
88 | }
89 |
90 | @Override
91 | public boolean isChecked() {
92 | return isChecked;
93 | }
94 |
95 | @Override
96 | public void setChecked(boolean checked) {
97 | if (isChecked == checked) return;
98 | isChecked = checked;
99 | xCheckBox.setChecked(checked);
100 | passRefreshStateView();
101 | }
102 |
103 | @Override
104 | public boolean onStateChange(boolean newValue) {
105 | if (listener == null || listener.onStateChange(newValue)) {
106 | isChecked = newValue;
107 | passRefreshStateView();
108 |
109 | return true;
110 | }
111 | return false;
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/widget/MiuixSeekBar.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.widget;
20 |
21 | import android.content.Context;
22 | import android.graphics.Canvas;
23 | import android.graphics.Paint;
24 | import android.util.AttributeSet;
25 |
26 | import androidx.annotation.NonNull;
27 | import androidx.annotation.Nullable;
28 | import androidx.appcompat.widget.AppCompatSeekBar;
29 | import androidx.core.content.ContextCompat;
30 |
31 | import com.hchen.himiuix.R;
32 |
33 | /**
34 | * Miuix SeekBar
35 | *
36 | * @author 焕晨HChen
37 | */
38 | public class MiuixSeekBar extends AppCompatSeekBar {
39 | private Paint paint;
40 | private int defValue;
41 | private int stepCount;
42 | private boolean isStep;
43 | private boolean isShowDefaultPoint;
44 | private boolean isAlwaysHapticFeedback;
45 |
46 | public MiuixSeekBar(@NonNull Context context) {
47 | this(context, null);
48 | }
49 |
50 | public MiuixSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) {
51 | this(context, attrs, 0);
52 | }
53 |
54 | public MiuixSeekBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
55 | super(context, attrs, defStyleAttr);
56 | init(attrs, defStyleAttr);
57 | }
58 |
59 | protected void init(@Nullable AttributeSet attrs, int defStyleAttr) {
60 | paint = new Paint(Paint.ANTI_ALIAS_FLAG);
61 | paint.setStyle(Paint.Style.FILL_AND_STROKE);
62 | paint.setColor(getContext().getColor(R.color.miuix_seekbar_def));
63 |
64 | setThumb(null);
65 | setBackground(null);
66 | setSplitTrack(false);
67 | setPadding(0, 0, 0, 0);
68 | setProgressDrawable(ContextCompat.getDrawable(getContext(), R.drawable.miuix_seekbar_progress));
69 | }
70 |
71 | @Override
72 | protected void onDraw(Canvas canvas) {
73 | super.onDraw(canvas);
74 |
75 | if (isShowDefaultPoint) {
76 | int width = getWidth();
77 | int height = getHeight();
78 | float scaleWidth = (float) width / (getMax() - getMin());
79 | float xPosition = scaleWidth * (isStep ? (stepCount) : (defValue - getMin()));
80 | float yPosition = (float) height / 2;
81 | canvas.drawCircle(xPosition, yPosition, (float) ((float) height / 6.5), paint);
82 | }
83 | }
84 |
85 | public void setDefValue(int defValue) {
86 | this.defValue = defValue;
87 | }
88 |
89 | public void setDefStepCount(int stepCount) {
90 | this.stepCount = stepCount;
91 | isStep = true;
92 | }
93 |
94 | public void setShowDefaultPoint(boolean show) {
95 | isShowDefaultPoint = show;
96 | }
97 |
98 | public void setAlwaysHapticFeedback(boolean enabled) {
99 | isAlwaysHapticFeedback = enabled;
100 | }
101 |
102 | public boolean isAlwaysHapticFeedback() {
103 | return isAlwaysHapticFeedback;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/src/main/res/layout/miuix_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
16 |
25 |
26 |
34 |
35 |
36 |
37 |
42 |
43 |
49 |
50 |
56 |
57 |
58 |
59 |
64 |
65 |
66 |
74 |
75 |
76 |
81 |
82 |
83 |
84 |
85 |
92 |
93 |
94 |
99 |
--------------------------------------------------------------------------------
/src/main/res/layout/miuix_reverse_layout.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
8 |
14 |
15 |
16 |
21 |
22 |
23 |
31 |
32 |
33 |
38 |
39 |
40 |
41 |
46 |
47 |
53 |
54 |
60 |
61 |
62 |
63 |
72 |
73 |
81 |
82 |
83 |
84 |
85 |
92 |
93 |
94 |
99 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/widget/MiuixCardView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.widget;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.graphics.Canvas;
24 | import android.graphics.Path;
25 | import android.graphics.Rect;
26 | import android.graphics.RectF;
27 | import android.util.AttributeSet;
28 |
29 | import androidx.annotation.NonNull;
30 | import androidx.annotation.Nullable;
31 | import androidx.cardview.widget.CardView;
32 |
33 | import com.hchen.himiuix.R;
34 |
35 | /**
36 | * Card View
37 | *
38 | * @author 焕晨HChen
39 | */
40 | public class MiuixCardView extends CardView {
41 | private final Path path = new Path();
42 | private final Rect rect = new Rect();
43 | private final RectF rectF = new RectF();
44 | private float tlRadius;
45 | private float trRadius;
46 | private float brRadius;
47 | private float blRadius;
48 |
49 | public MiuixCardView(@NonNull Context context) {
50 | this(context, null);
51 | }
52 |
53 | public MiuixCardView(@NonNull Context context, @Nullable AttributeSet attrs) {
54 | this(context, attrs, 0);
55 | }
56 |
57 | public MiuixCardView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
58 | super(context, attrs, defStyleAttr);
59 |
60 | final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MiuixCardView, defStyleAttr, 0);
61 | tlRadius = typedArray.getDimension(R.styleable.MiuixCardView_cardTopLeftRadius, 0);
62 | trRadius = typedArray.getDimension(R.styleable.MiuixCardView_cardTopRightRadius, 0);
63 | blRadius = typedArray.getDimension(R.styleable.MiuixCardView_cardBottomLeftRadius, 0);
64 | brRadius = typedArray.getDimension(R.styleable.MiuixCardView_cardBottomRightRadius, 0);
65 | typedArray.recycle();
66 |
67 | setRadius(0.0f);
68 | setCardElevation(0.0f);
69 | setPreventCornerOverlap(false);
70 | setUseCompatPadding(false);
71 | setCardBackgroundColor(getContext().getColor(android.R.color.transparent));
72 | }
73 |
74 | public MiuixCardView setTlRadius(float tlRadius) {
75 | this.tlRadius = tlRadius;
76 | return this;
77 | }
78 |
79 | public MiuixCardView setTrRadius(float trRadius) {
80 | this.trRadius = trRadius;
81 | return this;
82 | }
83 |
84 | public MiuixCardView setBrRadius(float brRadius) {
85 | this.brRadius = brRadius;
86 | return this;
87 | }
88 |
89 | public MiuixCardView setBlRadius(float blRadius) {
90 | this.blRadius = blRadius;
91 | return this;
92 | }
93 |
94 | @Override
95 | protected void onDraw(@NonNull Canvas canvas) {
96 | if (getRadius() == 0.0f) {
97 | float[] radius = {tlRadius, tlRadius, trRadius, trRadius, brRadius, brRadius, blRadius, blRadius};
98 | RectF rectF = getRectF();
99 | path.reset();
100 | path.addRoundRect(rectF, radius, Path.Direction.CW);
101 | canvas.clipPath(path);
102 | }
103 | super.onDraw(canvas);
104 | }
105 |
106 | private RectF getRectF() {
107 | getDrawingRect(rect);
108 | rectF.set(rect);
109 | return rectF;
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/widget/MiuixCheckBox.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.widget;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.util.AttributeSet;
24 | import android.view.animation.Animation;
25 | import android.view.animation.OvershootInterpolator;
26 | import android.view.animation.ScaleAnimation;
27 |
28 | import androidx.annotation.NonNull;
29 | import androidx.annotation.Nullable;
30 | import androidx.appcompat.widget.AppCompatCheckBox;
31 |
32 | import com.hchen.himiuix.R;
33 | import com.hchen.himiuix.callback.OnStateChangeListener;
34 |
35 | /**
36 | * Miuix CheckBox
37 | *
38 | * @author 焕晨HChen
39 | */
40 | public class MiuixCheckBox extends AppCompatCheckBox {
41 | private static final String TAG = "HiMiuix:CheckBox";
42 | private OnStateChangeListener onStateChangeListener;
43 |
44 | public MiuixCheckBox(@NonNull Context context) {
45 | this(context, null);
46 | }
47 |
48 | public MiuixCheckBox(@NonNull Context context, @Nullable AttributeSet attrs) {
49 | this(context, attrs, 0);
50 | }
51 |
52 | public MiuixCheckBox(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
53 | super(context, attrs, defStyleAttr);
54 | init(attrs, defStyleAttr);
55 | }
56 |
57 | private void init(@Nullable AttributeSet attrs, int defStyleAttr) {
58 | final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MiuixCheckBox, defStyleAttr, 0);
59 | int buttonId = typedArray.getResourceId(R.styleable.MiuixCheckBox_android_button, 0);
60 | typedArray.recycle();
61 |
62 | setClickable(true);
63 | setBackground(null);
64 | setSaveEnabled(false);
65 | setSaveFromParentEnabled(false);
66 | if (buttonId == 0) setButtonDrawable(R.drawable.miuix_checkbox);
67 | else setButtonDrawable(buttonId);
68 | }
69 |
70 | @Override
71 | public void toggle() {
72 | setUserChecked(!isChecked());
73 | }
74 |
75 | @Override
76 | public void setChecked(boolean checked) {
77 | if (isChecked() == checked) return;
78 | super.setChecked(checked);
79 | }
80 |
81 | // 当且仅当 onStateChange 拦截操作时才会返回 false
82 | public boolean setUserChecked(boolean checked) {
83 | if (isChecked() == checked) return true;
84 |
85 | if (onStateChangeListener == null || onStateChangeListener.onStateChange(checked)) {
86 | playScaleAnimation(checked);
87 | super.setChecked(checked);
88 | return true;
89 | }
90 | return false;
91 | }
92 |
93 | public void setOnStateChangeListener(OnStateChangeListener listener) {
94 | onStateChangeListener = listener;
95 | }
96 |
97 | private void playScaleAnimation(boolean checked) {
98 | ScaleAnimation anim = new ScaleAnimation(
99 | 1.0f, checked ? 1.05f : 0.95f, checked ? 1.05f : 0.95f, checked ? 1.05f : 0.95f,
100 | Animation.RELATIVE_TO_SELF, 0.5f,
101 | Animation.RELATIVE_TO_SELF, 0.5f
102 | );
103 | anim.setDuration(100);
104 | anim.setRepeatCount(1);
105 | anim.setRepeatMode(Animation.REVERSE);
106 | anim.setInterpolator(new OvershootInterpolator(1.3f));
107 | startAnimation(anim);
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorSelectView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.color;
20 |
21 | import android.content.Context;
22 | import android.graphics.Canvas;
23 | import android.graphics.Color;
24 | import android.graphics.Matrix;
25 | import android.graphics.Paint;
26 | import android.graphics.PaintFlagsDrawFilter;
27 | import android.graphics.SweepGradient;
28 | import android.util.AttributeSet;
29 | import android.view.View;
30 |
31 | import androidx.annotation.NonNull;
32 | import androidx.annotation.Nullable;
33 |
34 | import com.hchen.himiuix.R;
35 |
36 | /**
37 | * 色盘缩略图
38 | *
39 | * @author 焕晨HChen
40 | */
41 | public class ColorSelectView extends View {
42 | private float width;
43 | private float radius;
44 | private int color;
45 | private final Paint paint = new Paint();
46 | private final PaintFlagsDrawFilter filter = new PaintFlagsDrawFilter(0, 3);
47 | private SweepGradient sweepGradient;
48 | private final int[] colors = {
49 | Color.parseColor("#FF6565"),
50 | Color.parseColor("#FFBB55"),
51 | Color.parseColor("#FFF175"),
52 | Color.parseColor("#B3FFA7"),
53 | Color.parseColor("#98FFF9"),
54 | Color.parseColor("#7B98FF"),
55 | Color.parseColor("#FF75E1"),
56 | };
57 |
58 | public ColorSelectView(Context context) {
59 | this(context, null);
60 | }
61 |
62 | public ColorSelectView(Context context, @Nullable AttributeSet attrs) {
63 | this(context, attrs,0);
64 | }
65 |
66 | public ColorSelectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
67 | this(context, attrs, defStyleAttr,0);
68 | }
69 |
70 | public ColorSelectView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
71 | super(context, attrs, defStyleAttr, defStyleRes);
72 | init();
73 | }
74 |
75 | private void init() {
76 | width = -1.0F;
77 | post(() -> {
78 | update(getWidth());
79 | });
80 | }
81 |
82 | @Override
83 | protected void onSizeChanged(int w, int h, int oldw, int oldh) {
84 | super.onSizeChanged(w, h, oldw, oldh);
85 | if (w == 0) return;
86 | update(w);
87 | }
88 |
89 | public void setColor(int color) {
90 | if (this.color == color) return;
91 | this.color = color;
92 | }
93 |
94 | private void update(float width) {
95 | this.width = width;
96 | radius = width / 2;
97 |
98 | Matrix matrix = new Matrix();
99 | matrix.preRotate(90, radius, radius);
100 | sweepGradient = new SweepGradient(radius, radius, colors, null);
101 | sweepGradient.setLocalMatrix(matrix);
102 | }
103 |
104 | @Override
105 | protected void onDraw(@NonNull Canvas canvas) {
106 | if (width != -1.0F) {
107 | canvas.setDrawFilter(filter);
108 | paint.reset();
109 | paint.setColor(getContext().getColor(android.R.color.transparent));
110 | canvas.drawCircle(radius, radius, radius, paint);
111 | paint.reset();
112 | paint.setShader(sweepGradient);
113 | canvas.drawCircle(radius, radius, radius - 0.2F, paint);
114 | paint.reset();
115 | paint.setColor(getContext().getColor(R.color.miuix_color_select_def));
116 | canvas.drawCircle(radius, radius, radius - width / 9.0F, paint);
117 | paint.setColor(color);
118 | canvas.drawCircle(radius, radius, radius - width / 5.0F, paint);
119 | }
120 |
121 | super.onDraw(canvas);
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/MiuixRadioButtonView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 |
24 | import androidx.annotation.IdRes;
25 | import androidx.annotation.NonNull;
26 | import androidx.annotation.Nullable;
27 |
28 | import com.hchen.himiuix.callback.OnStateChangeListener;
29 | import com.hchen.himiuix.widget.MiuixRadioButton;
30 |
31 | /**
32 | * Miuix 单选框
33 | *
34 | * @author 焕晨HChen
35 | */
36 | public class MiuixRadioButtonView extends MiuixStateView implements OnStateChangeListener {
37 | private MiuixRadioButton xRadioButton;
38 | private OnInnerCheckedListener onInnerCheckedListener;
39 |
40 | public MiuixRadioButtonView(@NonNull Context context) {
41 | super(context);
42 | }
43 |
44 | public MiuixRadioButtonView(@NonNull Context context, @Nullable AttributeSet attrs) {
45 | super(context, attrs);
46 | }
47 |
48 | public MiuixRadioButtonView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
49 | super(context, attrs, defStyleAttr);
50 | }
51 |
52 | public MiuixRadioButtonView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
53 | super(context, attrs, defStyleAttr, defStyleRes);
54 | }
55 |
56 | @Override
57 | void loadViewWhenBuild() {
58 | super.loadViewWhenBuild();
59 | xRadioButton = (MiuixRadioButton) getIndicatorView();
60 | xRadioButton.setOnStateChangeListener(this);
61 | }
62 |
63 | @Override
64 | DynamicIndicator loadDynamicIndicator() {
65 | return DynamicIndicator.INDICATOR_RADIO_BUTTON;
66 | }
67 |
68 | @Override
69 | void updateVisibility() {
70 | super.updateVisibility();
71 | xRadioButton.setVisibility(VISIBLE);
72 | }
73 |
74 | @Override
75 | void updateViewContent() {
76 | // 跳过非用户的 Check 动作
77 | if (!pass) {
78 | if (!xRadioButton.setUserChecked(isChecked))
79 | isChecked = !isChecked; // 被拦截,还原
80 | }
81 | setShadowHelperEnabled(!isChecked);
82 | super.updateViewContent();
83 | }
84 |
85 | @Override
86 | public boolean performClick() {
87 | if (!isChecked) {
88 | isChecked = true;
89 | refreshView();
90 | }
91 | return super.performClick();
92 | }
93 |
94 | @Override
95 | public boolean isChecked() {
96 | return isChecked;
97 | }
98 |
99 | @Override
100 | public void setChecked(boolean checked) {
101 | if (isChecked == checked) return;
102 | isChecked = checked;
103 | xRadioButton.setChecked(checked);
104 | if (isChecked && onInnerCheckedListener != null)
105 | onInnerCheckedListener.onChecked(getId());
106 | passRefreshStateView();
107 | }
108 |
109 | MiuixRadioButton getRadioButton() {
110 | return xRadioButton;
111 | }
112 |
113 | @Override
114 | public boolean onStateChange(boolean newValue) {
115 | if (listener == null || listener.onStateChange(newValue)) {
116 | isChecked = newValue;
117 | passRefreshStateView();
118 |
119 | // RadioGroup 回调
120 | if (isChecked && onInnerCheckedListener != null)
121 | onInnerCheckedListener.onChecked(getId());
122 | return true;
123 | }
124 | return false;
125 | }
126 |
127 | void setInnerCheckedListener(OnInnerCheckedListener listener) {
128 | onInnerCheckedListener = listener;
129 | }
130 |
131 | interface OnInnerCheckedListener {
132 | void onChecked(@IdRes int id);
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/fill/MiuixRecyclerFillView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.fill;
20 |
21 | import android.annotation.SuppressLint;
22 | import android.content.Context;
23 | import android.content.res.Configuration;
24 | import android.content.res.TypedArray;
25 | import android.util.AttributeSet;
26 |
27 | import androidx.annotation.Nullable;
28 | import androidx.recyclerview.widget.RecyclerView;
29 |
30 | import com.hchen.himiuix.R;
31 |
32 | /**
33 | * 适用于 MiuixAppBar/MiuixBottomNavigatorView 的填充视图
34 | *
35 | * @author 焕晨HChen
36 | */
37 | public class MiuixRecyclerFillView extends RecyclerView {
38 | public static final String View_Tag = "Miuix:RecyclerFillView";
39 | private int collapsibleTitleHeight;
40 | private int navigationBarHeight;
41 | private int statusBarHeight;
42 | private int defToolbarHeight;
43 | public static int defBottomHeight;
44 |
45 | public MiuixRecyclerFillView(Context context) {
46 | this(context, null);
47 | }
48 |
49 | public MiuixRecyclerFillView(Context context, @Nullable AttributeSet attrs) {
50 | this(context, attrs, 0);
51 | }
52 |
53 | public MiuixRecyclerFillView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
54 | super(context, attrs, defStyleAttr);
55 | init(attrs, defStyleAttr, 0);
56 | }
57 |
58 | private void init(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
59 | setTag(View_Tag);
60 | initialStatusBarHeight();
61 | initialNavigationBarHeight();
62 |
63 | collapsibleTitleHeight = getResources().getDimensionPixelSize(R.dimen.miuix_appbar_collapsible_title_height);
64 | defBottomHeight = getResources().getDimensionPixelSize(R.dimen.miuix_bottom_menu_target_height);
65 | TypedArray array = getContext().obtainStyledAttributes(android.R.style.Widget_Toolbar, new int[]{android.R.attr.minHeight});
66 | defToolbarHeight = array.getDimensionPixelOffset(0, 0);
67 | array.recycle();
68 |
69 | setPaddingTop(statusBarHeight + defToolbarHeight + collapsibleTitleHeight);
70 | setPaddingBottom(navigationBarHeight + defBottomHeight);
71 | }
72 |
73 | private void setPaddingTop(int top) {
74 | setPadding(getPaddingLeft(), top, getPaddingRight(), getPaddingBottom());
75 | }
76 |
77 | private void setPaddingBottom(int bottom) {
78 | setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
79 | }
80 |
81 | @Override
82 | protected void onConfigurationChanged(Configuration newConfig) {
83 | super.onConfigurationChanged(newConfig);
84 | int lastStatusBarHeight = statusBarHeight;
85 | int lastNavigationBarHeight = navigationBarHeight;
86 | initialStatusBarHeight();
87 | initialNavigationBarHeight();
88 | if (statusBarHeight != lastStatusBarHeight)
89 | setPaddingTop(statusBarHeight + defToolbarHeight + collapsibleTitleHeight);
90 | if (lastNavigationBarHeight != navigationBarHeight)
91 | setPaddingBottom(navigationBarHeight + defBottomHeight);
92 | }
93 |
94 | private void initialStatusBarHeight() {
95 | @SuppressLint("InternalInsetResource")
96 | int resourceId = getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
97 | if (resourceId > 0)
98 | statusBarHeight = getContext().getResources().getDimensionPixelSize(resourceId);
99 | }
100 |
101 | private void initialNavigationBarHeight() {
102 | @SuppressLint("InternalInsetResource")
103 | int resourceId = getContext().getResources().getIdentifier("navigation_bar_height", "dimen", "android");
104 | if (resourceId > 0)
105 | navigationBarHeight = getContext().getResources().getDimensionPixelSize(resourceId);
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/fill/MiuixFillView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.fill;
20 |
21 | import android.annotation.SuppressLint;
22 | import android.content.Context;
23 | import android.content.res.Configuration;
24 | import android.content.res.TypedArray;
25 | import android.util.AttributeSet;
26 | import android.widget.LinearLayout;
27 |
28 | import androidx.annotation.Nullable;
29 |
30 | import com.hchen.himiuix.R;
31 |
32 | /**
33 | * 适用于 MiuixAppBar/MiuixBottomNavigatorView 的填充视图
34 | *
35 | * @author 焕晨HChen
36 | */
37 | public class MiuixFillView extends LinearLayout {
38 | public static final String View_Tag = "Miuix:FillView";
39 | private int collapsibleTitleHeight;
40 | private int navigationBarHeight;
41 | private int statusBarHeight;
42 | private int defToolbarHeight;
43 | public static int defBottomHeight;
44 |
45 | public MiuixFillView(Context context) {
46 | this(context, null);
47 | }
48 |
49 | public MiuixFillView(Context context, @Nullable AttributeSet attrs) {
50 | this(context, attrs, 0);
51 | }
52 |
53 | public MiuixFillView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
54 | this(context, attrs, defStyleAttr, 0);
55 | }
56 |
57 | public MiuixFillView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
58 | super(context, attrs, defStyleAttr, defStyleRes);
59 | init(attrs, defStyleAttr, defStyleRes);
60 | }
61 |
62 | private void init(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
63 | setId(R.id.miuix_fill);
64 | setTag(View_Tag);
65 | setOrientation(VERTICAL);
66 | initialStatusBarHeight();
67 | initialNavigationBarHeight();
68 |
69 | collapsibleTitleHeight = getResources().getDimensionPixelSize(R.dimen.miuix_appbar_collapsible_title_height);
70 | defBottomHeight = getResources().getDimensionPixelSize(R.dimen.miuix_bottom_menu_target_height);
71 | TypedArray array = getContext().obtainStyledAttributes(android.R.style.Widget_Toolbar, new int[]{android.R.attr.minHeight});
72 | defToolbarHeight = array.getDimensionPixelOffset(0, 0);
73 | array.recycle();
74 |
75 | setPaddingTop(statusBarHeight + defToolbarHeight + collapsibleTitleHeight);
76 | setPaddingBottom(navigationBarHeight + defBottomHeight);
77 | }
78 |
79 | private void setPaddingTop(int top) {
80 | setPadding(getPaddingLeft(), top, getPaddingRight(), getPaddingBottom());
81 | }
82 |
83 | private void setPaddingBottom(int bottom) {
84 | setPadding(getPaddingLeft(), getPaddingTop(), getPaddingRight(), bottom);
85 | }
86 |
87 | @Override
88 | protected void onConfigurationChanged(Configuration newConfig) {
89 | super.onConfigurationChanged(newConfig);
90 | int lastStatusBarHeight = statusBarHeight;
91 | int lastNavigationBarHeight = navigationBarHeight;
92 | initialStatusBarHeight();
93 | initialNavigationBarHeight();
94 | if (statusBarHeight != lastStatusBarHeight)
95 | setPaddingTop(statusBarHeight + defToolbarHeight + collapsibleTitleHeight);
96 | if (lastNavigationBarHeight != navigationBarHeight)
97 | setPaddingBottom(navigationBarHeight + defBottomHeight);
98 | }
99 |
100 | private void initialStatusBarHeight() {
101 | @SuppressLint("InternalInsetResource")
102 | int resourceId = getContext().getResources().getIdentifier("status_bar_height", "dimen", "android");
103 | if (resourceId > 0)
104 | statusBarHeight = getContext().getResources().getDimensionPixelSize(resourceId);
105 | }
106 |
107 | private void initialNavigationBarHeight() {
108 | @SuppressLint("InternalInsetResource")
109 | int resourceId = getContext().getResources().getIdentifier("navigation_bar_height", "dimen", "android");
110 | if (resourceId > 0)
111 | navigationBarHeight = getContext().getResources().getDimensionPixelSize(resourceId);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/springback/SpringBackLayoutHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.springback;
20 |
21 | import static com.hchen.himiuix.springback.SpringBackLayout.HORIZONTAL;
22 | import static com.hchen.himiuix.springback.SpringBackLayout.UNCHECK_ORIENTATION;
23 | import static com.hchen.himiuix.springback.SpringBackLayout.VERTICAL;
24 |
25 | import android.graphics.Rect;
26 | import android.view.MotionEvent;
27 | import android.view.ViewConfiguration;
28 | import android.view.ViewGroup;
29 |
30 | /**
31 | * SpringBack 帮助
32 | *
33 | * 改编自 HyperOS 2
34 | *
35 | * @author 焕晨HChen
36 | */
37 | public class SpringBackLayoutHelper {
38 | private final Rect mTargetBoundsInWindow = new Rect();
39 | float mInitialDownX; // 手指按下时的 X 坐标
40 | float mInitialDownY; // 手指按下时的 Y 坐标
41 | int mScrollOrientation;
42 | int mActivePointerId = -1;
43 | private final int mTouchSlop;
44 | private final ViewGroup mTarget;
45 |
46 | public SpringBackLayoutHelper(ViewGroup target) {
47 | mTarget = target;
48 | mTouchSlop = ViewConfiguration.get(target.getContext()).getScaledTouchSlop();
49 | }
50 |
51 | public boolean isTouchInTarget(MotionEvent event) {
52 | int pointerIndex = event.findPointerIndex(event.getPointerId(0));
53 | if (pointerIndex < 0) return false;
54 |
55 | float touchScreenX = event.getX(pointerIndex); // 获取触摸点在事件源坐标系中的 X 坐标
56 | float touchScreenY = event.getY(pointerIndex); // 获取触摸点在事件源坐标系中的 Y 坐标
57 |
58 | int[] targetLocation = new int[2];
59 | mTarget.getLocationInWindow(targetLocation);
60 | int targetLeftInWindow = targetLocation[0];
61 | int targetTopInWindow = targetLocation[1];
62 |
63 | mTargetBoundsInWindow.set(
64 | targetLeftInWindow,
65 | targetTopInWindow,
66 | targetLeftInWindow + mTarget.getWidth(),
67 | targetTopInWindow + mTarget.getHeight()
68 | );
69 |
70 | return mTargetBoundsInWindow.contains((int) touchScreenX, (int) touchScreenY);
71 | }
72 |
73 | public void checkOrientation(MotionEvent event) {
74 | final int action = event.getActionMasked();
75 |
76 | switch (action) {
77 | case MotionEvent.ACTION_DOWN:
78 | mActivePointerId = event.getPointerId(0);
79 | int downPointerIndex = event.findPointerIndex(mActivePointerId);
80 | if (downPointerIndex >= 0) {
81 | mInitialDownX = event.getX(downPointerIndex);
82 | mInitialDownY = event.getY(downPointerIndex);
83 | } else mActivePointerId = -1;
84 |
85 | mScrollOrientation = UNCHECK_ORIENTATION;
86 | break;
87 |
88 | case MotionEvent.ACTION_MOVE:
89 | if (mActivePointerId == -1) break;
90 |
91 | int movePointerIndex = event.findPointerIndex(mActivePointerId);
92 | if (movePointerIndex >= 0) {
93 | float currentX = event.getX(movePointerIndex);
94 | float currentY = event.getY(movePointerIndex);
95 |
96 | float deltaX = currentX - mInitialDownX;
97 | float deltaY = currentY - mInitialDownY;
98 |
99 | float absDeltaX = Math.abs(deltaX);
100 | float absDeltaY = Math.abs(deltaY);
101 |
102 | if (absDeltaX > mTouchSlop || absDeltaY > mTouchSlop) {
103 | if (absDeltaX > absDeltaY) mScrollOrientation = HORIZONTAL;
104 | else mScrollOrientation = VERTICAL;
105 | }
106 | } else {
107 | mActivePointerId = -1;
108 | mScrollOrientation = UNCHECK_ORIENTATION;
109 | }
110 | break;
111 |
112 | case MotionEvent.ACTION_UP:
113 | case MotionEvent.ACTION_CANCEL:
114 | mActivePointerId = -1;
115 | mScrollOrientation = UNCHECK_ORIENTATION;
116 | mTarget.requestDisallowInterceptTouchEvent(false);
117 | break;
118 | }
119 | }
120 | }
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/preference/MiuixPreferenceCategory.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.preference;
20 |
21 | import static android.view.View.GONE;
22 | import static android.view.View.VISIBLE;
23 |
24 | import android.content.Context;
25 | import android.util.AttributeSet;
26 | import android.view.View;
27 | import android.widget.TextView;
28 |
29 | import androidx.annotation.NonNull;
30 | import androidx.annotation.Nullable;
31 | import androidx.preference.Preference;
32 | import androidx.preference.PreferenceGroup;
33 | import androidx.preference.PreferenceViewHolder;
34 |
35 | import com.hchen.himiuix.R;
36 | import com.hchen.himiuix.utils.InvokeUtils;
37 |
38 | import java.util.ArrayList;
39 | import java.util.List;
40 | import java.util.stream.Collectors;
41 |
42 | /**
43 | * Preference Category
44 | *
45 | * @author 焕晨HChen
46 | */
47 | public class MiuixPreferenceCategory extends PreferenceGroup {
48 | private static final String TAG = "HiMiuix:Preference";
49 |
50 | public MiuixPreferenceCategory(@NonNull Context context, @Nullable AttributeSet attrs) {
51 | this(context, attrs, 0);
52 | }
53 |
54 | public MiuixPreferenceCategory(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
55 | this(context, attrs, defStyleAttr, 0);
56 | }
57 |
58 | public MiuixPreferenceCategory(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
59 | super(context, attrs, defStyleAttr, defStyleRes);
60 | setLayoutResource(R.layout.miuix_category);
61 | setSelectable(false);
62 | setPersistent(false);
63 | }
64 |
65 | @Override
66 | public void onBindViewHolder(@NonNull PreferenceViewHolder holder) {
67 | super.onBindViewHolder(holder);
68 | TextView dividerTextView = holder.itemView.findViewById(R.id.miuix_divider_title);
69 | View dividerView = holder.itemView.findViewById(R.id.miuix_divider);
70 |
71 | dividerTextView.setVisibility(GONE);
72 | dividerView.setVisibility(VISIBLE);
73 |
74 | if (getTitle() != null) {
75 | dividerTextView.setText(getTitle());
76 | dividerTextView.setVisibility(VISIBLE);
77 | dividerView.setVisibility(GONE);
78 | }
79 | }
80 |
81 | @Override
82 | public boolean isEnabled() {
83 | return false;
84 | }
85 |
86 | @Override
87 | public boolean shouldDisableDependents() {
88 | return false;
89 | }
90 |
91 | @Override
92 | protected void notifyHierarchyChanged() {
93 | updateCardRadius();
94 | super.notifyHierarchyChanged();
95 | }
96 |
97 | /**
98 | * @noinspection SequencedCollectionMethodCanBeUsed
99 | */
100 | public void updateCardRadius() {
101 | // 实时刷新布局
102 | List preferences = InvokeUtils.getField(this, "mPreferences");
103 | preferences = preferences.stream()
104 | .filter(Preference::isVisible)
105 | .collect(Collectors.toCollection(ArrayList::new));
106 |
107 | if (preferences.isEmpty())
108 | super.notifyHierarchyChanged();
109 | else if (preferences.size() == 1) {
110 | if (preferences.get(0) instanceof MiuixPreference xPreference)
111 | xPreference.setCardState(MiuixPreference.CARD_RADIUS);
112 | } else {
113 | boolean isFirst = true;
114 | for (int i = 0; i < preferences.size(); i++) {
115 | if (!(preferences.get(i) instanceof MiuixPreference xPreference))
116 | continue;
117 |
118 | if (isFirst) {
119 | xPreference.setCardState(MiuixPreference.CARD_TOP_RADIUS);
120 | isFirst = false;
121 | continue;
122 | }
123 | xPreference.setCardState(MiuixPreference.CARD_NON_RADIUS);
124 | }
125 |
126 | for (int i = preferences.size() - 1; i >= 0; i--) {
127 | if (preferences.get(i) instanceof MiuixPreference xPreference) {
128 | xPreference.setCardState(MiuixPreference.CARD_BOTTOM_RADIUS);
129 | break;
130 | }
131 | }
132 | }
133 | }
134 | }
135 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/helper/AppBarHelper.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.helper;
20 |
21 | import android.view.View;
22 | import android.view.ViewGroup;
23 |
24 | import com.hchen.himiuix.callback.OnAppBarListener;
25 | import com.hchen.himiuix.springback.SpringBackLayout;
26 |
27 | import java.util.HashMap;
28 | import java.util.HashSet;
29 |
30 | /**
31 | * AppBar Helper
32 | *
33 | * @author 焕晨HChen
34 | */
35 | public class AppBarHelper {
36 | private static final String TAG = "HiMiuix:AppBar";
37 | private static final HashSet toolbarListeners = new HashSet<>();
38 | private static final HashMap viewToTargetMap = new HashMap<>();
39 |
40 | public static void addOnToolbarListener(OnAppBarListener listener) {
41 | toolbarListeners.add(listener);
42 | }
43 |
44 | public static void removeOnToolbarListener(OnAppBarListener listener) {
45 | if (listener == null) toolbarListeners.clear();
46 | toolbarListeners.remove(listener);
47 | }
48 |
49 | public static void callTargetStart(View view) {
50 | if (view == null) return;
51 | if (viewToTargetMap.get(view) != null) {
52 | for (OnAppBarListener listener : toolbarListeners) {
53 | listener.targetStart(viewToTargetMap.get(view));
54 | }
55 | return;
56 | }
57 |
58 | view.post(() -> {
59 | View target = findTargetView((ViewGroup) view);
60 | if (target == null) return;
61 | viewToTargetMap.put(view, target);
62 | for (OnAppBarListener listener : toolbarListeners) {
63 | listener.targetStart(target);
64 | }
65 | });
66 | }
67 |
68 | public static void callTargetRegister(View view) {
69 | if (view == null) return;
70 | if (viewToTargetMap.get(view) != null) {
71 | for (OnAppBarListener listener : toolbarListeners) {
72 | listener.targetRegister(viewToTargetMap.get(view));
73 | }
74 | return;
75 | }
76 |
77 | view.post(() -> {
78 | View target = findTargetView((ViewGroup) view);
79 | if (target == null) return;
80 | viewToTargetMap.put(view, target);
81 | for (OnAppBarListener listener : toolbarListeners) {
82 | listener.targetRegister(target);
83 | }
84 | });
85 | }
86 |
87 | public static void callTargetUnregister(View view) {
88 | if (view == null) return;
89 | if (viewToTargetMap.get(view) != null) {
90 | for (OnAppBarListener listener : toolbarListeners) {
91 | listener.targetUnregister(viewToTargetMap.get(view));
92 | }
93 | return;
94 | }
95 |
96 | view.post(() -> {
97 | View target = findTargetView((ViewGroup) view);
98 | if (target == null) return;
99 | viewToTargetMap.put(view, target);
100 | for (OnAppBarListener listener : toolbarListeners) {
101 | listener.targetUnregister(target);
102 | }
103 | });
104 | }
105 |
106 | public static void onDestroyView(View view) {
107 | for (OnAppBarListener listener : toolbarListeners) {
108 | listener.targetDestroy(viewToTargetMap.get(view));
109 | }
110 | viewToTargetMap.remove(view);
111 | }
112 |
113 | private static View findTargetView(ViewGroup group) {
114 | if (group instanceof SpringBackLayout springBackLayout) {
115 | if (springBackLayout.isLinkageAppBar())
116 | return springBackLayout.getTarget();
117 | }
118 | for (int i = 0; i < group.getChildCount(); i++) {
119 | View view = group.getChildAt(i);
120 |
121 | if (view instanceof SpringBackLayout springBackLayout) {
122 | if (springBackLayout.isLinkageAppBar()) {
123 | return springBackLayout.getTarget();
124 | }
125 | }
126 | if (view instanceof ViewGroup viewGroup) {
127 | View target = findTargetView(viewGroup);
128 | if (target != null) {
129 | return target;
130 | }
131 | }
132 | }
133 | return null;
134 | }
135 | }
136 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/color/ColorPickerBaseSeekBar.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix.color;
20 |
21 | import android.content.Context;
22 | import android.graphics.drawable.Drawable;
23 | import android.graphics.drawable.GradientDrawable;
24 | import android.graphics.drawable.LayerDrawable;
25 | import android.util.AttributeSet;
26 | import android.widget.SeekBar;
27 |
28 | import androidx.annotation.NonNull;
29 | import androidx.annotation.Nullable;
30 | import androidx.core.content.ContextCompat;
31 |
32 | import com.hchen.himiuix.R;
33 | import com.hchen.himiuix.callback.OnColorChangedListener;
34 | import com.hchen.himiuix.helper.HapticFeedbackHelper;
35 | import com.hchen.himiuix.widget.MiuixSeekBar;
36 |
37 | /**
38 | * 色盘 Seekbar 基类
39 | *
40 | * @author 焕晨HChen
41 | */
42 | class ColorPickerBaseSeekBar extends MiuixSeekBar implements SeekBar.OnSeekBarChangeListener {
43 | private ColorPickerType type;
44 | private OnColorChangedListener listener;
45 | private LayerDrawable layerDrawable;
46 | private GradientDrawable drawable;
47 | private int[] colors;
48 | private int value;
49 |
50 | public ColorPickerBaseSeekBar(@NonNull Context context) {
51 | super(context);
52 | }
53 |
54 | public ColorPickerBaseSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) {
55 | super(context, attrs);
56 | }
57 |
58 | public ColorPickerBaseSeekBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
59 | super(context, attrs, defStyleAttr);
60 | }
61 |
62 | @Override
63 | protected void init(@Nullable AttributeSet attrs, int defStyleAttr) {
64 | drawable = new GradientDrawable();
65 | drawable.setShape(GradientDrawable.RECTANGLE);
66 | drawable.setOrientation(GradientDrawable.Orientation.TL_BR);
67 | drawable.setCornerRadius(getResources().getDimensionPixelSize(R.dimen.miuix_color_radius));
68 | drawable.setSize(-1, getResources().getDimensionPixelSize(R.dimen.miuix_color_height));
69 | drawable.setStroke(0, 0);
70 |
71 | updateBasicInfo();
72 | updateProgressBackground();
73 | setThumb(ContextCompat.getDrawable(getContext(), R.drawable.miuix_color_picker_with_hole));
74 | setThumbOffset(getResources().getDimensionPixelSize(R.dimen.miuix_color_picker_offset));
75 | setBackground(null);
76 | setSplitTrack(false); // 去除按钮的奇怪遮罩
77 | setPadding(0, 0, 0, 0);
78 | setOnSeekBarChangeListener(this);
79 | }
80 |
81 | final void updateProgressBackground() {
82 | drawable.setColors(colors);
83 | if (layerDrawable == null) setProgressDrawable(drawable);
84 | else {
85 | layerDrawable.setDrawable(1, drawable);
86 | setProgressDrawable(layerDrawable);
87 | }
88 | }
89 |
90 | void updateBasicInfo() {
91 | }
92 |
93 | final void setListener(OnColorChangedListener listener) {
94 | this.listener = listener;
95 | }
96 |
97 | final void setType(ColorPickerType type) {
98 | this.type = type;
99 | }
100 |
101 | final void setColorPickerBackground(Drawable colorPickerBackground) {
102 | layerDrawable = new LayerDrawable(new Drawable[]{colorPickerBackground, drawable});
103 | }
104 |
105 | final void setColors(int... colors) {
106 | this.colors = colors;
107 | updateProgressBackground();
108 | }
109 |
110 | void setValue(float value) {
111 | this.value = Math.round(value);
112 | setProgress(Math.round(value));
113 | }
114 |
115 | final int getValue() {
116 | return value;
117 | }
118 |
119 | @Override
120 | public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
121 | if (fromUser) {
122 | value = progress;
123 | if (listener != null) listener.onColorValueChanged(type, value);
124 | if (isAlwaysHapticFeedback())
125 | HapticFeedbackHelper.performHapticFeedback(this, HapticFeedbackHelper.MIUI_TAP_NORMAL);
126 | }
127 | }
128 |
129 | @Override
130 | public final void onStartTrackingTouch(SeekBar seekBar) {
131 | }
132 |
133 | @Override
134 | public final void onStopTrackingTouch(SeekBar seekBar) {
135 | // 可计算最终值,-1 无任何含义
136 | if (listener != null) listener.onColorValueChanged(ColorPickerType.FINAL_COLOR, -1);
137 | }
138 | }
139 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/MiuixRadioGroup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix;
20 |
21 | import android.content.Context;
22 | import android.util.AttributeSet;
23 | import android.util.Log;
24 | import android.view.View;
25 | import android.view.ViewGroup;
26 | import android.view.autofill.AutofillValue;
27 | import android.widget.LinearLayout;
28 |
29 | import androidx.annotation.IdRes;
30 | import androidx.annotation.NonNull;
31 | import androidx.annotation.Nullable;
32 |
33 | import com.hchen.himiuix.callback.OnCheckedChangeListener;
34 | import com.hchen.himiuix.widget.MiuixRadioButton;
35 |
36 | import java.util.HashSet;
37 | import java.util.function.Consumer;
38 |
39 | /**
40 | * Radio Group
41 | *
42 | * @author 焕晨HChen
43 | */
44 | public class MiuixRadioGroup extends LinearLayout implements MiuixRadioButtonView.OnInnerCheckedListener {
45 | private static final String TAG = "HiMiuix:RadioGroup";
46 | private final HashSet radioButtonSet = new HashSet<>();
47 | private OnCheckedChangeListener onCheckedChangeListener;
48 | private int checkedId = -1;
49 |
50 | public MiuixRadioGroup(@NonNull Context context) {
51 | this(context, null);
52 | }
53 |
54 | public MiuixRadioGroup(@NonNull Context context, @Nullable AttributeSet attrs) {
55 | this(context, attrs, 0);
56 | }
57 |
58 | public MiuixRadioGroup(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
59 | this(context, attrs, defStyleAttr, 0);
60 | }
61 |
62 | public MiuixRadioGroup(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
63 | super(context, attrs, defStyleAttr, defStyleRes);
64 | setOrientation(VERTICAL);
65 | }
66 |
67 | @Override
68 | protected void onAttachedToWindow() {
69 | super.onAttachedToWindow();
70 | if (checkedId != -1) updateCheckedState(checkedId);
71 | }
72 |
73 | @Override
74 | public void addView(View child, int index, ViewGroup.LayoutParams params) {
75 | if (child instanceof MiuixRadioButtonView view) {
76 | int viewId = view.getId();
77 | if (viewId == NO_ID) {
78 | viewId = generateViewId();
79 | view.setId(viewId);
80 | }
81 | view.setInnerCheckedListener(this);
82 | radioButtonSet.add(view);
83 |
84 | MiuixRadioButton button = view.getRadioButton();
85 | if (button.isChecked()) {
86 | if (checkedId != -1)
87 | updateCheckedState(viewId);
88 | checkedId = viewId;
89 | }
90 | }
91 | super.addView(child, index, params);
92 | }
93 |
94 | public void check(@IdRes int id) {
95 | if (id != -1 && checkedId == id) return;
96 | updateCheckedState(checkedId);
97 | }
98 |
99 | @IdRes
100 | public int getCheckedId() {
101 | return checkedId;
102 | }
103 |
104 | public void clearCheck() {
105 | check(-1);
106 | }
107 |
108 | public void setOnCheckedChangeListener(OnCheckedChangeListener listener) {
109 | onCheckedChangeListener = listener;
110 | }
111 |
112 | private void updateCheckedState(int id) {
113 | if (checkedId == id) return;
114 | if (onCheckedChangeListener != null)
115 | onCheckedChangeListener.onCheckedChanged(this, id);
116 |
117 | checkedId = id;
118 | radioButtonSet.forEach(new Consumer() {
119 | @Override
120 | public void accept(MiuixRadioButtonView view) {
121 | if (id == -1) view.setChecked(false);
122 | else view.setChecked(view.getId() == id);
123 | }
124 | });
125 | }
126 |
127 | @Override
128 | public void autofill(AutofillValue value) {
129 | if (!isEnabled()) return;
130 |
131 | if (!value.isList()) {
132 | Log.w(TAG, value + " could not be autofilled into " + this);
133 | return;
134 | }
135 |
136 | final int index = value.getListValue();
137 | final View child = getChildAt(index);
138 | if (child == null) {
139 | Log.w(TAG, "RadioGroup.autoFill(): no child with index " + index);
140 | return;
141 | }
142 |
143 | check(child.getId());
144 | }
145 |
146 | @Override
147 | public void onChecked(int id) {
148 | updateCheckedState(id);
149 | }
150 | }
151 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/MiuixViewGroup.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.util.AttributeSet;
24 | import android.view.LayoutInflater;
25 | import android.view.View;
26 | import android.view.ViewGroup;
27 | import android.widget.LinearLayout;
28 | import android.widget.TextView;
29 |
30 | import androidx.annotation.Nullable;
31 | import androidx.cardview.widget.CardView;
32 |
33 | import java.util.Objects;
34 |
35 | /**
36 | * Miuix 视图组
37 | *
38 | * @author 焕晨HChen
39 | */
40 | public class MiuixViewGroup extends LinearLayout {
41 | private CharSequence dividerTitle;
42 | private LinearLayout innerLayout;
43 |
44 | public MiuixViewGroup(Context context) {
45 | this(context, null);
46 | }
47 |
48 | public MiuixViewGroup(Context context, @Nullable AttributeSet attrs) {
49 | this(context, attrs, 0);
50 | }
51 |
52 | public MiuixViewGroup(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
53 | this(context, attrs, defStyleAttr, 0);
54 | }
55 |
56 | public MiuixViewGroup(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
57 | super(context, attrs, defStyleAttr, defStyleRes);
58 | init(attrs, defStyleAttr, defStyleRes);
59 | }
60 |
61 | private void init(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
62 | final TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.MiuixViewGroup, defStyleAttr, defStyleRes);
63 | dividerTitle = typedArray.getText(R.styleable.MiuixViewGroup_dividerTitle);
64 | boolean isMarginBottomEnabled = typedArray.getBoolean(R.styleable.MiuixViewGroup_marginBottomEnabled, false);
65 | typedArray.recycle();
66 |
67 | LayoutInflater.from(getContext()).inflate(R.layout.miuix_group_layout, this, true);
68 | setOrientation(VERTICAL);
69 | updateDivider();
70 |
71 | innerLayout = findViewById(R.id.miuix_group);
72 | CardView cardView = findViewById(R.id.miuix_card);
73 |
74 | // 是否启用底部 margin
75 | // 这在项目处于底部时有奇效
76 | if (isMarginBottomEnabled) {
77 | LinearLayout.LayoutParams params = (LayoutParams) cardView.getLayoutParams();
78 | params.bottomMargin = getContext().getResources().getDimensionPixelSize(R.dimen.miuix_basic_margin);
79 | cardView.setLayoutParams(params);
80 | }
81 | }
82 |
83 | @Nullable
84 | public CharSequence getDividerTitle() {
85 | return dividerTitle;
86 | }
87 |
88 | public void setDividerTitle(@Nullable CharSequence dividerTitle) {
89 | if (Objects.equals(this.dividerTitle, dividerTitle)) return;
90 | this.dividerTitle = dividerTitle;
91 | updateDivider();
92 | }
93 |
94 | private void updateDivider() {
95 | TextView textView = findViewById(R.id.miuix_divider_title);
96 | View view = findViewById(R.id.miuix_divider);
97 | if (dividerTitle == null) {
98 | textView.setVisibility(GONE);
99 | view.setVisibility(VISIBLE);
100 | } else {
101 | textView.setText(dividerTitle);
102 | textView.setVisibility(VISIBLE);
103 | view.setVisibility(GONE);
104 | }
105 | }
106 |
107 | @Override
108 | public void bringChildToFront(View child) {
109 | if (innerLayout != null) innerLayout.bringChildToFront(child);
110 | else super.bringChildToFront(child);
111 | }
112 |
113 | @Override
114 | public void addView(View child) {
115 | if (innerLayout != null) innerLayout.addView(child);
116 | else super.addView(child);
117 | }
118 |
119 | @Override
120 | public void addView(View child, int index) {
121 | if (innerLayout != null) innerLayout.addView(child, index);
122 | else super.addView(child, index);
123 | }
124 |
125 | @Override
126 | public void addView(View child, int width, int height) {
127 | if (innerLayout != null) innerLayout.addView(child, width, height);
128 | else super.addView(child, width, height);
129 | }
130 |
131 | @Override
132 | public void addView(View child, ViewGroup.LayoutParams params) {
133 | if (innerLayout != null) innerLayout.addView(child, params);
134 | else super.addView(child, params);
135 | }
136 |
137 | @Override
138 | public void addView(View child, int index, ViewGroup.LayoutParams params) {
139 | if (innerLayout != null) innerLayout.addView(child, index, params);
140 | else super.addView(child, index, params);
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/main/java/com/hchen/himiuix/MiuixStateView.java:
--------------------------------------------------------------------------------
1 | /*
2 | * This file is part of HiMiuix.
3 | *
4 | * HiMiuix is free software: you can redistribute it and/or modify
5 | * it under the terms of the GNU Lesser General Public License as published by
6 | * the Free Software Foundation; either version 2.1 of the License, or
7 | * (at your option) any later version.
8 | *
9 | * HiMiuix is distributed in the hope that it will be useful,
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 | * GNU Lesser General Public License for more details.
13 | *
14 | * You should have received a copy of the GNU Lesser General Public License
15 | * along with HiMiuix. If not, see .
16 | *
17 | * Copyright (C) 2023–2025 HChenX
18 | */
19 | package com.hchen.himiuix;
20 |
21 | import android.content.Context;
22 | import android.content.res.TypedArray;
23 | import android.util.AttributeSet;
24 |
25 | import androidx.annotation.NonNull;
26 | import androidx.annotation.Nullable;
27 |
28 | import com.hchen.himiuix.callback.OnStateChangeListener;
29 |
30 | import java.util.Objects;
31 |
32 | /**
33 | * Miuix 状态视图
34 | *
35 | * @author 焕晨HChen
36 | */
37 | public class MiuixStateView extends MiuixBasicView {
38 | boolean isChecked;
39 | boolean pass;
40 | private CharSequence tipOn;
41 | private CharSequence tipOff;
42 | private CharSequence summaryOn;
43 | private CharSequence summaryOff;
44 | OnStateChangeListener listener;
45 |
46 | public MiuixStateView(@NonNull Context context) {
47 | super(context);
48 | }
49 |
50 | public MiuixStateView(@NonNull Context context, @Nullable AttributeSet attrs) {
51 | super(context, attrs);
52 | }
53 |
54 | public MiuixStateView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
55 | super(context, attrs, defStyleAttr);
56 | }
57 |
58 | public MiuixStateView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
59 | super(context, attrs, defStyleAttr, defStyleRes);
60 | }
61 |
62 | @Override
63 | void init(@Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
64 | TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.MiuixStateView, defStyleAttr, defStyleRes);
65 | tipOn = array.getText(R.styleable.MiuixStateView_tipOn);
66 | tipOff = array.getText(R.styleable.MiuixStateView_tipOff);
67 | summaryOn = array.getText(R.styleable.MiuixStateView_android_summaryOn);
68 | summaryOff = array.getText(R.styleable.MiuixStateView_android_summaryOff);
69 | isChecked = array.getBoolean(R.styleable.MiuixStateView_android_checked, false);
70 | array.recycle();
71 |
72 | super.init(attrs, defStyleAttr, defStyleRes);
73 | }
74 |
75 | @Override
76 | void updateViewContent() {
77 | super.updateViewContent();
78 |
79 | // 动态更新内容
80 | if (tipOn != null || tipOff != null) {
81 | if (tipOn != null && isChecked()) getTipView().setText(tipOn);
82 | if (tipOff != null && !isChecked()) getTipView().setText(tipOff);
83 |
84 | if (isChecked() && tipOn == null && getTip() != null)
85 | getTipView().setText(getTip());
86 | if (!isChecked() && tipOff == null && getTip() != null)
87 | getTipView().setText(getTip());
88 | }
89 | if (summaryOn != null || summaryOff != null) {
90 | if (summaryOn != null && isChecked()) getSummaryView().setText(summaryOn);
91 | if (summaryOff != null && !isChecked()) getSummaryView().setText(summaryOff);
92 |
93 | if (isChecked() && summaryOn == null && getSummary() != null)
94 | getSummaryView().setText(getSummary());
95 | if (!isChecked() && summaryOff == null && getSummary() != null)
96 | getSummaryView().setText(getSummary());
97 | }
98 | }
99 |
100 | @Override
101 | void updateVisibility() {
102 | super.updateVisibility();
103 |
104 | if (tipOn != null || tipOff != null)
105 | getTipView().setVisibility(VISIBLE);
106 | if (summaryOn != null || summaryOff != null)
107 | getSummaryView().setVisibility(VISIBLE);
108 | }
109 |
110 | public boolean isChecked() {
111 | return false;
112 | }
113 |
114 | public void setChecked(boolean checked) {
115 | }
116 |
117 | public void setTipOn(CharSequence tipOn) {
118 | if (Objects.equals(this.tipOn, tipOn)) return;
119 | this.tipOn = tipOn;
120 | passRefreshStateView();
121 | }
122 |
123 | public void setTipOff(CharSequence tipOff) {
124 | if (Objects.equals(this.tipOff, tipOff)) return;
125 | this.tipOff = tipOff;
126 | passRefreshStateView();
127 | }
128 |
129 | public void setSummaryOn(CharSequence summaryOn) {
130 | if (Objects.equals(this.summaryOn, summaryOn)) return;
131 | this.summaryOn = summaryOn;
132 | passRefreshStateView();
133 | }
134 |
135 | public void setSummaryOff(CharSequence summaryOff) {
136 | if (Objects.equals(this.summaryOff, summaryOff)) return;
137 | this.summaryOff = summaryOff;
138 | passRefreshStateView();
139 | }
140 |
141 | public void setOnStateChangeListener(OnStateChangeListener listener) {
142 | if (Objects.equals(this.listener, listener)) return;
143 | this.listener = listener;
144 | passRefreshStateView();
145 | }
146 |
147 | public CharSequence getTipOn() {
148 | return tipOn;
149 | }
150 |
151 | public CharSequence getTipOff() {
152 | return tipOff;
153 | }
154 |
155 | public CharSequence getSummaryOn() {
156 | return summaryOn;
157 | }
158 |
159 | public CharSequence getSummaryOff() {
160 | return summaryOff;
161 | }
162 |
163 | void passRefreshStateView() {
164 | pass = true;
165 | refreshView();
166 | pass = false;
167 | }
168 | }
169 |
--------------------------------------------------------------------------------