feat: 添加自定义开关按钮样式和UI优化

- 新增CustomSwitch自定义开关组件(黄色/黑色Material Design风格)
- 优化电量百分比显示(16sp字号,距离闪电图标2dp)
- 更新所有设置页面使用新的开关样式
- 移除旧的开关颜色设置代码
- 构建v8a正式版APK
This commit is contained in:
您的名字
2025-10-13 20:22:15 +08:00
parent d4d30d39c1
commit 597261ff57
10 changed files with 204 additions and 74 deletions
@@ -59,28 +59,6 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
mBinding.renderText.setText((render = ResUtil.getStringArray(R.array.select_render))[Setting.getRender()]);
mBinding.captionText.setText((caption = ResUtil.getStringArray(R.array.select_caption))[Setting.isCaption() ? 1 : 0]);
mBinding.backgroundText.setText((background = ResUtil.getStringArray(R.array.select_background))[Setting.getBackground()]);
// 设置开关的颜色为黄色
int accentColor = getResources().getColor(R.color.accent);
android.content.res.ColorStateList colorStateList = new android.content.res.ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}
},
new int[]{
0x66FFFFFF, // 未选中时的颜色
accentColor // 选中时的颜色
}
);
mBinding.tunnelSwitch.setThumbTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.WHITE));
mBinding.tunnelSwitch.setTrackTintList(colorStateList);
mBinding.audioDecodeSwitch.setThumbTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.WHITE));
mBinding.audioDecodeSwitch.setTrackTintList(colorStateList);
mBinding.aacSwitch.setThumbTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.WHITE));
mBinding.aacSwitch.setTrackTintList(colorStateList);
mBinding.danmakuLoadSwitch.setThumbTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.WHITE));
mBinding.danmakuLoadSwitch.setTrackTintList(colorStateList);
}
@Override
@@ -0,0 +1,137 @@
package com.fongmi.android.tv.ui.custom;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.View;
import androidx.appcompat.widget.AppCompatCheckBox;
public class CustomSwitch extends AppCompatCheckBox {
private Paint trackPaint;
private Paint thumbPaint;
private RectF trackRect;
private RectF thumbRect;
private float thumbPosition = 0f; // 0 = 左边, 1 = 右边
private int currentTrackColor;
private int currentThumbColor;
private static final int TRACK_COLOR_OFF = 0xFF555555; // 灰色
private static final int TRACK_COLOR_ON = 0xFFFFEB3B; // 黄色
private static final int THUMB_COLOR_OFF = 0xFFFFFFFF; // 白色
private static final int THUMB_COLOR_ON = 0xFF000000; // 黑色
private ValueAnimator animator;
public CustomSwitch(Context context) {
super(context);
init();
}
public CustomSwitch(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public CustomSwitch(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
// 隐藏默认的checkbox样式
setButtonDrawable(null);
trackPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
thumbPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
trackRect = new RectF();
thumbRect = new RectF();
currentTrackColor = TRACK_COLOR_OFF;
currentThumbColor = THUMB_COLOR_OFF;
// 监听状态变化
setOnCheckedChangeListener((buttonView, isChecked) -> animateSwitch(isChecked));
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// 固定尺寸:50dp × 30dp
int width = (int) (50 * getResources().getDisplayMetrics().density);
int height = (int) (30 * getResources().getDisplayMetrics().density);
setMeasuredDimension(width, height);
}
@Override
protected void onDraw(Canvas canvas) {
int width = getWidth();
int height = getHeight();
float radius = height / 2f;
// 绘制轨道
trackRect.set(0, 0, width, height);
trackPaint.setColor(currentTrackColor);
canvas.drawRoundRect(trackRect, radius, radius, trackPaint);
// 计算小圆位置
float thumbSize = height - 8 * getResources().getDisplayMetrics().density; // 22dp
float padding = 4 * getResources().getDisplayMetrics().density;
float thumbLeft = padding + thumbPosition * (width - thumbSize - 2 * padding);
float thumbTop = padding;
// 绘制小圆
thumbRect.set(thumbLeft, thumbTop, thumbLeft + thumbSize, thumbTop + thumbSize);
thumbPaint.setColor(currentThumbColor);
canvas.drawOval(thumbRect, thumbPaint);
}
private void animateSwitch(boolean isChecked) {
if (animator != null && animator.isRunning()) {
animator.cancel();
}
float targetPosition = isChecked ? 1f : 0f;
int targetTrackColor = isChecked ? TRACK_COLOR_ON : TRACK_COLOR_OFF;
int targetThumbColor = isChecked ? THUMB_COLOR_ON : THUMB_COLOR_OFF;
animator = ValueAnimator.ofFloat(thumbPosition, targetPosition);
animator.setDuration(250); // 250ms动画时长
final ArgbEvaluator colorEvaluator = new ArgbEvaluator();
animator.addUpdateListener(animation -> {
thumbPosition = (float) animation.getAnimatedValue();
// 颜色渐变
currentTrackColor = (int) colorEvaluator.evaluate(
thumbPosition, TRACK_COLOR_OFF, TRACK_COLOR_ON
);
currentThumbColor = (int) colorEvaluator.evaluate(
thumbPosition, THUMB_COLOR_OFF, THUMB_COLOR_ON
);
invalidate();
});
animator.start();
}
@Override
public void setChecked(boolean checked) {
super.setChecked(checked);
// 初始化时不播放动画
if (!isAttachedToWindow()) {
thumbPosition = checked ? 1f : 0f;
currentTrackColor = checked ? TRACK_COLOR_ON : TRACK_COLOR_OFF;
currentThumbColor = checked ? THUMB_COLOR_ON : THUMB_COLOR_OFF;
}
}
}
@@ -104,21 +104,6 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall);
mBinding.versionText.setText(getString(R.string.setting_version) + " " + BuildConfig.VERSION_NAME);
// 设置开关的颜色为黄色
int accentColor = getResources().getColor(R.color.accent);
android.content.res.ColorStateList colorStateList = new android.content.res.ColorStateList(
new int[][]{
new int[]{-android.R.attr.state_checked},
new int[]{android.R.attr.state_checked}
},
new int[]{
0x66FFFFFF, // 未选中时的颜色
accentColor // 选中时的颜色
}
);
mBinding.incognitoSwitch.setThumbTintList(android.content.res.ColorStateList.valueOf(android.graphics.Color.WHITE));
mBinding.incognitoSwitch.setTrackTintList(colorStateList);
setOtherText();
setCacheText();
String[] quotes = getResources().getStringArray(R.array.motivational_quotes);
@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 开启状态:黄色底 + 黑色圆在右边 -->
<item android:state_checked="true">
<layer-list>
<!-- 黄色轨道 -->
<item>
<shape android:shape="rectangle">
<solid android:color="#FFEB3B" />
<corners android:radius="15dp" />
</shape>
</item>
<!-- 黑色小圆(右边,精确定位 22dp) -->
<item android:top="4dp" android:bottom="4dp" android:right="4dp" android:left="24dp">
<shape android:shape="oval">
<solid android:color="#000000" />
</shape>
</item>
</layer-list>
</item>
<!-- 关闭状态:灰色底 + 白色圆在左边 -->
<item>
<layer-list>
<!-- 灰色轨道 -->
<item>
<shape android:shape="rectangle">
<solid android:color="#555555" />
<corners android:radius="15dp" />
</shape>
</item>
<!-- 白色小圆(左边,精确定位 22dp) -->
<item android:top="4dp" android:bottom="4dp" android:left="4dp" android:right="24dp">
<shape android:shape="oval">
<solid android:color="#FFFFFF" />
</shape>
</item>
</layer-list>
</item>
</selector>
@@ -222,11 +222,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/tunnelSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -249,11 +248,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/audioDecodeSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -276,11 +274,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/aacSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -303,11 +300,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/danmakuLoadSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -333,11 +333,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/incognitoSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -354,11 +354,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/tunnelSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -387,11 +386,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/audioDecodeSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -420,11 +418,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/aacSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
@@ -453,11 +450,10 @@
android:textColor="@color/white"
android:textSize="16sp" />
<androidx.appcompat.widget.SwitchCompat
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/danmakuLoadSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/M3SwitchStyle" />
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
@@ -64,7 +64,7 @@
android:layout_height="20dp"
android:layout_gravity="center_vertical"
android:layout_marginStart="8dp"
android:layout_marginEnd="4dp"
android:layout_marginEnd="2dp"
android:src="@drawable/ic_charging_bolt"
android:visibility="gone"
tools:visibility="visible" />
@@ -76,7 +76,7 @@
android:layout_gravity="center_vertical"
android:paddingEnd="8dp"
android:textColor="@color/white"
android:textSize="14sp"
android:textSize="16sp"
android:visibility="gone"
tools:text="85%"
tools:visibility="visible" />
+6 -8
View File
@@ -78,14 +78,12 @@
<item name="android:background">@null</item>
</style>
<!-- M3 Switch Style -->
<style name="M3SwitchStyle" parent="Widget.AppCompat.CompoundButton.Switch">
<item name="android:thumb">@drawable/m3_switch_thumb</item>
<item name="track">@drawable/m3_switch_track</item>
<item name="android:switchMinWidth">52dp</item>
<item name="android:switchPadding">8dp</item>
<item name="android:colorControlActivated">#FFEB3B</item>
<item name="android:colorControlHighlight">@android:color/transparent</item>
<!-- M3 Switch Style (Material Design) - 使用CustomSwitch完全自定义 -->
<style name="M3SwitchStyle" parent="Widget.AppCompat.CompoundButton.CheckBox">
<item name="android:button">@null</item>
<item name="android:background">@drawable/custom_switch_bg</item>
<item name="android:minHeight">30dp</item>
<item name="android:minWidth">50dp</item>
</style>
<!-- 自定义数据源按钮样式 -->
Binary file not shown.