feat: 升级到v3.0.9版本

- 新增直播开关控制功能,可隐藏/显示直播tab
- 优化滑杆圆球大小至20dp直径,提升操作体验
- 改进滑杆刻度显示,非激活轨道显示刻度
- 增强播放进度条动态大小调整功能
- 新增实时倍速显示功能
- 优化源管理模块间距动态调整
- 修复播放进度条圆球跳回问题
- 完善直播开关逻辑和UI交互
- 更新版本号至3.0.9
This commit is contained in:
您的名字
2025-10-24 14:00:14 +08:00
parent dcc751c691
commit 78570eed7c
38 changed files with 487 additions and 159 deletions
+9 -9
View File
@@ -27,8 +27,8 @@ android {
minSdk 24
//noinspection ExpiredTargetSdkVersion
targetSdk 28
versionCode 308
versionName "3.0.8"
versionCode 309
versionName "3.0.9"
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString(), "eventBusIndex": "com.fongmi.android.tv.event.EventIndex"]
@@ -113,7 +113,7 @@ dependencies {
implementation project(':catvod')
// implementation project(':chaquo') // 移除Python支持减少8-10MB体积
implementation project(':quickjs')
implementation 'androidx.appcompat:appcompat:1.7.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'androidx.media:media:1.7.0'
implementation 'androidx.media3:media3-common:' + media3Version
implementation 'androidx.media3:media3-container:' + media3Version
@@ -130,7 +130,7 @@ dependencies {
implementation 'androidx.media3:media3-exoplayer-smoothstreaming:' + media3Version
implementation 'androidx.media3:media3-extractor:' + media3Version
implementation 'androidx.media3:media3-ui:' + media3Version
implementation 'androidx.room:room-runtime:2.7.2'
implementation 'androidx.room:room-runtime:2.6.1'
implementation 'cat.ereza:customactivityoncrash:2.4.0'
implementation 'io.github.anilbeesetti:nextlib-media3ext:1.8.0-0.9.0'
implementation 'com.github.bassaer:materialdesigncolors:1.0.0'
@@ -141,11 +141,11 @@ dependencies {
implementation 'com.github.jahirfiquitiva:TextDrawable:1.0.3'
implementation 'com.github.thegrizzlylabs:sardine-android:0.9'
implementation 'com.github.teamnewpipe:NewPipeExtractor:v0.24.8'
implementation 'com.google.android.material:material:1.12.0'
implementation 'com.google.android.material:material:1.11.0'
implementation 'com.google.zxing:core:3.5.3'
implementation 'com.guolindev.permissionx:permissionx:1.8.1'
implementation 'com.hierynomus:smbj:0.14.0'
implementation 'io.antmedia:rtmp-client:3.2.0'
implementation 'com.guolindev.permissionx:permissionx:1.7.1'
implementation 'com.hierynomus:smbj:0.13.0'
implementation 'io.antmedia:rtmp-client:3.1.0'
implementation 'javax.servlet:javax.servlet-api:3.1.0'
implementation 'org.aomedia.avif.android:avif:1.1.1.14d8e3c4'
implementation 'org.eclipse.jetty:jetty-client:8.1.21.v20160908'
@@ -162,7 +162,7 @@ dependencies {
mobileImplementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'
mobileImplementation 'com.google.android.flexbox:flexbox:3.0.0'
mobileImplementation('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false }
annotationProcessor 'androidx.room:room-compiler:2.7.2'
annotationProcessor 'androidx.room:room-compiler:2.6.1'
// annotationProcessor 'com.github.bumptech.glide:compiler:4.16.0'
annotationProcessor 'org.greenrobot:eventbus-annotation-processor:3.3.1'
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs_nio:2.1.5'
@@ -207,13 +207,26 @@ public class Updater implements Download.Callback {
private void confirm(View view) {
// 跳转到GitHub Releases页面而不是直接下载
try {
String url = "https://github.com/Tosencen/XMBOX/releases/tag/v3.0.8";
Logger.d("Updater: Attempting to open URL: " + url);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/Tosencen/XMBOX/releases/tag/v3.0.8"));
intent.setData(Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 检查是否有应用可以处理这个Intent
if (intent.resolveActivity(App.get().getPackageManager()) != null) {
App.get().startActivity(intent);
Logger.d("Updater: Successfully started browser intent");
dismiss();
} else {
Logger.e("Updater: No app can handle the URL");
Notify.show("没有找到可以打开链接的应用,请手动访问GitHub下载");
dismiss();
}
} catch (Exception e) {
Logger.e("Failed to open GitHub releases page: " + e.getMessage());
Logger.e("Updater: Failed to open GitHub releases page: " + e.getMessage());
e.printStackTrace();
Notify.show("无法打开更新页面,请手动访问GitHub下载");
dismiss();
}
@@ -99,8 +99,17 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
mBinding.dohText.setText(getDohList()[getDohIndex()]);
mBinding.proxyText.setText(getProxy(Setting.getProxy()));
mBinding.incognitoText.setText(getSwitch(Setting.isIncognito()));
mBinding.liveTabVisibleText.setText(getSwitch(Setting.isLiveTabVisible()));
mBinding.sizeText.setText((size = ResUtil.getStringArray(R.array.select_size))[Setting.getSize()]);
mBinding.qualityText.setText((quality = ResUtil.getStringArray(R.array.select_quality))[Setting.getQuality()]);
setLiveSettingsVisibility();
}
private void setLiveSettingsVisibility() {
boolean isLiveTabVisible = !Setting.isLiveTabVisible(); // 注意:这里取反,因为开关是"隐藏直播"
mBinding.live.setVisibility(isLiveTabVisible ? View.VISIBLE : View.GONE);
mBinding.liveHome.setVisibility(isLiveTabVisible ? View.VISIBLE : View.GONE);
mBinding.liveHistory.setVisibility(isLiveTabVisible ? View.VISIBLE : View.GONE);
}
private void setCacheText() {
@@ -134,6 +143,7 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
mBinding.wallDefault.setOnClickListener(this::setWallDefault);
mBinding.wallRefresh.setOnClickListener(this::setWallRefresh);
mBinding.incognito.setOnClickListener(this::setIncognito);
mBinding.liveTabVisible.setOnClickListener(this::setLiveTabVisible);
mBinding.quality.setOnClickListener(this::setQuality);
mBinding.size.setOnClickListener(this::setSize);
mBinding.doh.setOnClickListener(this::setDoh);
@@ -304,6 +314,15 @@ public class SettingActivity extends BaseActivity implements ConfigCallback, Sit
mBinding.incognitoText.setText(getSwitch(Setting.isIncognito()));
}
private void setLiveTabVisible(View view) {
Setting.putLiveTabVisible(!Setting.isLiveTabVisible());
mBinding.liveTabVisibleText.setText(getSwitch(Setting.isLiveTabVisible()));
// 发送刷新事件,通知主界面更新导航栏
RefreshEvent.config();
// 更新直播设置项的可见性
setLiveSettingsVisibility();
}
private void setQuality(View view) {
int index = Setting.getQuality();
Setting.putQuality(index = index == quality.length - 1 ? 0 : ++index);
@@ -265,6 +265,36 @@
</LinearLayout>
<LinearLayout
android:id="@+id/liveTabVisible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:background="@drawable/selector_item"
android:focusable="true"
android:focusableInTouchMode="true"
android:nextFocusDown="@id/quality"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/setting_live_tab_visible"
android:textColor="@color/white"
android:textSize="18sp" />
<TextView
android:id="@+id/liveTabVisibleText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="end"
android:textColor="@color/white"
android:textSize="18sp"
tools:text="On" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -14,8 +14,11 @@
android:valueFrom="1"
android:valueTo="10"
app:thumbColor="@color/primary"
app:tickVisible="false"
app:thumbRadius="10dp"
app:tickVisible="true"
app:tickColor="@color/black_50"
app:trackColorActive="@color/primary"
app:trackColorInactive="@color/white_30" />
app:trackColorInactive="@color/white_20"
app:trackHeight="4dp" />
</FrameLayout>
+5 -2
View File
@@ -14,8 +14,11 @@
android:valueFrom="2"
android:valueTo="5"
app:thumbColor="@color/primary"
app:tickVisible="false"
app:thumbRadius="10dp"
app:tickVisible="true"
app:tickColor="@color/black_50"
app:trackColorActive="@color/primary"
app:trackColorInactive="@color/white_30" />
app:trackColorInactive="@color/white_20"
app:trackHeight="4dp" />
</FrameLayout>
@@ -29,6 +29,8 @@
android:nextFocusUp="@id/next"
android:nextFocusDown="@id/timeBar"
app:bar_height="2dp"
app:scrubber_enabled_size="12dp"
app:scrubber_disabled_size="12dp"
app:played_color="#FFEB3B"
app:scrubber_color="#FFEB3B"
app:buffered_color="#80FFEB3B"
@@ -324,4 +324,12 @@ public class Setting {
public static void setPrivacyAgreed(boolean agreed) {
Prefers.put("privacy_agreed_v1", agreed);
}
public static boolean isLiveTabVisible() {
return Prefers.getBoolean("live_tab_visible", true);
}
public static void putLiveTabVisible(boolean visible) {
Prefers.put("live_tab_visible", visible);
}
}
@@ -17,7 +17,7 @@ public abstract class ConfigDao extends BaseDao<Config> {
@Query("SELECT * FROM Config WHERE type = :type ORDER BY time DESC")
public abstract List<Config> findByType(int type);
@SuppressWarnings(RoomWarnings.QUERY_MISMATCH)
@SuppressWarnings(RoomWarnings.CURSOR_MISMATCH)
@Query("SELECT id, name, url, type, time FROM Config WHERE type = :type ORDER BY time DESC")
public abstract List<Config> findUrlByType(int type);
@@ -2,7 +2,9 @@ package com.fongmi.android.tv.ui.custom;
import android.content.Context;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.widget.FrameLayout;
import android.widget.TextView;
@@ -33,6 +35,7 @@ public class CustomSeekView extends FrameLayout implements TimeBar.OnScrubListen
private long currentPosition;
private long currentBuffered;
private boolean scrubbing;
private boolean isPressed;
public CustomSeekView(Context context) {
this(context, null);
@@ -55,6 +58,28 @@ public class CustomSeekView extends FrameLayout implements TimeBar.OnScrubListen
timeBar = findViewById(R.id.timeBar);
timeBar.addListener(this);
refresh = this::refresh;
// 设置触摸事件监听器,实现动态尺寸调整
timeBar.setOnTouchListener((v, event) -> {
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
if (!isPressed) {
isPressed = true;
// 按下时:滑杆4dp,圆球16dp
setTimeBarSize(4, 16);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
if (isPressed) {
isPressed = false;
// 松开时:滑杆2dp,圆球12dp
setTimeBarSize(2, 12);
}
break;
}
return false; // 不拦截事件,让DefaultTimeBar正常处理
});
}
public void setListener(Players player) {
@@ -69,6 +94,58 @@ public class CustomSeekView extends FrameLayout implements TimeBar.OnScrubListen
timeBar.setDuration(duration);
}
/**
* 动态设置进度条高度和拖拽手柄大小
* @param barHeightDp 滑杆高度值(dp
* @param scrubberSizeDp 拖拽手柄大小(dp
*/
private void setTimeBarSize(int barHeightDp, int scrubberSizeDp) {
// 设置滑杆高度
int barHeightPx = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
barHeightDp,
getContext().getResources().getDisplayMetrics()
);
// 设置拖拽手柄大小
int scrubberSizePx = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
scrubberSizeDp,
getContext().getResources().getDisplayMetrics()
);
// 通过反射设置DefaultTimeBar的内部属性
try {
// 设置滑杆高度
java.lang.reflect.Field barHeightField = timeBar.getClass().getDeclaredField("barHeight");
barHeightField.setAccessible(true);
barHeightField.setInt(timeBar, barHeightPx);
// 设置拖拽手柄大小 - 尝试多个可能的字段名
String[] scrubberFields = {"scrubberSize", "scrubberEnabledSize", "scrubberDisabledSize"};
for (String fieldName : scrubberFields) {
try {
java.lang.reflect.Field scrubberField = timeBar.getClass().getDeclaredField(fieldName);
scrubberField.setAccessible(true);
scrubberField.setInt(timeBar, scrubberSizePx);
break; // 成功设置后退出循环
} catch (NoSuchFieldException e) {
// 继续尝试下一个字段名
}
}
// 刷新视图
timeBar.requestLayout();
timeBar.invalidate();
} catch (Exception e) {
// 如果反射失败,使用备用方案
e.printStackTrace();
// 备用方案:重新设置布局参数
timeBar.getLayoutParams().height = barHeightPx;
timeBar.requestLayout();
}
}
private void start() {
removeCallbacks(refresh);
post(refresh);
@@ -137,6 +214,8 @@ public class CustomSeekView extends FrameLayout implements TimeBar.OnScrubListen
// 延迟刷新进度条,确保播放器已经处理了跳转操作
removeCallbacks(refresh);
postDelayed(() -> {
// 只有在非拖动状态下才刷新进度条位置
if (!scrubbing) {
refresh();
// 确保进度条位置与实际播放位置一致
long actualPosition = player.getPosition();
@@ -144,6 +223,7 @@ public class CustomSeekView extends FrameLayout implements TimeBar.OnScrubListen
timeBar.setPosition(actualPosition);
positionView.setText(player.stringToTime(actualPosition));
}
}
}, 50); // 延迟50ms刷新
}
@@ -168,9 +248,10 @@ public class CustomSeekView extends FrameLayout implements TimeBar.OnScrubListen
public void onScrubStop(@NonNull TimeBar timeBar, long position, boolean canceled) {
scrubbing = false;
if (!canceled) {
// 先隐藏进度条提示,避免用户看到不一致的状态
// 注意:这里不能直接访问mBinding.widget.seek,因为CustomSeekView不包含这个引用
// 这个优化将在VideoActivity的onSeekEnd方法中实现
// 立即设置进度条位置到目标位置,避免圆球跳回原始位置
timeBar.setPosition(position);
positionView.setText(player.stringToTime(position));
// 调整播放位置
seekToTimeBarPosition(position);
// 确保播放状态正确
@@ -73,6 +73,7 @@
<string name="setting_subscription">订阅管理</string>
<string name="setting_player">播放设置</string>
<string name="setting_incognito">无痕模式</string>
<string name="setting_live_tab_visible">隐藏直播</string>
<string name="setting_quality">图片品质</string>
<string name="setting_size">图片尺寸</string>
<string name="setting_doh">DoH</string>
+1
View File
@@ -78,6 +78,7 @@
<string name="setting_data">Data Management</string>
<string name="setting_player">Player setting</string>
<string name="setting_incognito">Incognito mode</string>
<string name="setting_live_tab_visible">Hide Live Tab</string>
<string name="setting_quality">Image quality</string>
<string name="setting_size">Image size</string>
<string name="setting_doh">DoH</string>
@@ -213,13 +213,26 @@ public class Updater implements Download.Callback {
private void confirm(View view) {
// 跳转到GitHub Releases页面而不是直接下载
try {
String url = "https://github.com/Tosencen/XMBOX/releases/tag/v3.0.8";
Logger.d("Updater: Attempting to open URL: " + url);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse("https://github.com/Tosencen/XMBOX/releases/tag/v3.0.8"));
intent.setData(Uri.parse(url));
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// 检查是否有应用可以处理这个Intent
if (intent.resolveActivity(App.get().getPackageManager()) != null) {
App.get().startActivity(intent);
Logger.d("Updater: Successfully started browser intent");
dismiss();
} else {
Logger.e("Updater: No app can handle the URL");
Notify.show("没有找到可以打开链接的应用,请手动访问GitHub下载");
dismiss();
}
} catch (Exception e) {
Logger.e("Failed to open GitHub releases page: " + e.getMessage());
Logger.e("Updater: Failed to open GitHub releases page: " + e.getMessage());
e.printStackTrace();
Notify.show("无法打开更新页面,请手动访问GitHub下载");
dismiss();
}
@@ -154,7 +154,7 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt
private void setNavigation() {
mBinding.navigation.getMenu().findItem(R.id.vod).setVisible(true);
mBinding.navigation.getMenu().findItem(R.id.setting).setVisible(true);
mBinding.navigation.getMenu().findItem(R.id.live).setVisible(LiveConfig.hasUrl());
mBinding.navigation.getMenu().findItem(R.id.live).setVisible(LiveConfig.hasUrl() && !Setting.isLiveTabVisible());
}
private boolean openLive() {
@@ -65,17 +65,19 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
protected void initEvent() {
mBinding.back.setOnClickListener(v -> finish());
mBinding.ua.setOnClickListener(this::onUa);
mBinding.aac.setOnClickListener(this::setAAC);
mBinding.scale.setOnClickListener(this::onScale);
mBinding.speed.setOnClickListener(this::onSpeed);
mBinding.buffer.setOnClickListener(this::onBuffer);
mBinding.render.setOnClickListener(this::setRender);
mBinding.tunnel.setOnClickListener(this::setTunnel);
mBinding.caption.setOnClickListener(this::setCaption);
mBinding.caption.setOnLongClickListener(this::onCaption);
mBinding.background.setOnClickListener(this::onBackground);
mBinding.audioDecode.setOnClickListener(this::setAudioDecode);
mBinding.danmakuLoad.setOnClickListener(this::setDanmakuLoad);
// 直接给开关按钮设置点击监听器,避免双重点击冲突
mBinding.tunnelSwitch.setOnClickListener(this::setTunnel);
mBinding.audioDecodeSwitch.setOnClickListener(this::setAudioDecode);
mBinding.aacSwitch.setOnClickListener(this::setAAC);
mBinding.danmakuLoadSwitch.setOnClickListener(this::setDanmakuLoad);
}
private void onUa(View view) {
@@ -91,7 +93,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
private void setAAC(View view) {
boolean isChecked = !Setting.isPreferAAC();
Setting.putPreferAAC(isChecked);
mBinding.aacSwitch.setChecked(isChecked);
// 不需要再次调用 setChecked,因为点击已经触发了状态变化
}
private void onScale(View view) {
@@ -132,7 +134,7 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
private void setTunnel(View view) {
boolean isChecked = !Setting.isTunnel();
Setting.putTunnel(isChecked);
mBinding.tunnelSwitch.setChecked(isChecked);
// 不需要再次调用 setChecked,因为点击已经触发了状态变化
if (isChecked && Setting.getRender() == 1) setRender(view);
}
@@ -157,12 +159,12 @@ public class SettingPlayerActivity extends BaseActivity implements UaCallback, B
private void setAudioDecode(View view) {
boolean isChecked = !Setting.isAudioPrefer();
Setting.putAudioPrefer(isChecked);
mBinding.audioDecodeSwitch.setChecked(isChecked);
// 不需要再次调用 setChecked,因为点击已经触发了状态变化
}
private void setDanmakuLoad(View view) {
boolean isChecked = !Setting.isDanmakuLoad();
Setting.putDanmakuLoad(isChecked);
mBinding.danmakuLoadSwitch.setChecked(isChecked);
// 不需要再次调用 setChecked,因为点击已经触发了状态变化
}
}
@@ -126,6 +126,8 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis
private void setSpeed(@NonNull Slider slider, float value, boolean fromUser) {
parent.control.action.speed.setText(player.setSpeed(value));
if (history != null) history.setSpeed(player.getSpeed());
// 实时更新倍速数值显示
binding.speedValue.setText(String.format("%.1fx", value));
}
private void setScaleText() {
@@ -179,6 +181,8 @@ public class ControlDialog extends BaseDialog implements ParseAdapter.OnClickLis
binding.player.setText(parent.control.action.player.getText());
binding.decode.setVisibility(parent.control.action.decode.getVisibility());
binding.danmaku.setVisibility(parent.control.action.danmaku.getVisibility());
// 初始化倍速数值显示
binding.speedValue.setText(String.format("%.1fx", Math.max(player.getSpeed(), 0.5f)));
}
public void setParseVisible(boolean visible) {
@@ -60,6 +60,8 @@ public class TimerDialog extends BaseDialog implements Timer.Callback {
binding.time2.setOnClickListener(this::setTimer);
binding.time3.setOnClickListener(this::setTimer);
binding.time4.setOnClickListener(this::setTimer);
binding.time5.setOnClickListener(this::setTimer);
binding.time6.setOnClickListener(this::setTimer);
}
private void setTimer(View view) {
@@ -8,9 +8,11 @@ import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.text.style.RelativeSizeSpan;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
@@ -101,7 +103,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
protected void initView() {
setSourceHintText(mBinding.vodUrl, VodConfig.getDesc(), R.string.source_hint_setting);
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc(), R.string.source_hint_live);
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall);
// setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall); // 壁纸功能已移除
mBinding.versionText.setText(getString(R.string.setting_version) + " " + BuildConfig.VERSION_NAME);
setOtherText();
@@ -115,7 +117,30 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
mBinding.dohText.setText(getDohList()[getDohIndex()]);
mBinding.proxyText.setText(getProxy(Setting.getProxy()));
mBinding.incognitoSwitch.setChecked(Setting.isIncognito());
mBinding.liveTabVisibleSwitch.setChecked(Setting.isLiveTabVisible());
mBinding.sizeText.setText((size = ResUtil.getStringArray(R.array.select_size))[Setting.getSize()]);
setLiveSettingsVisibility();
}
private void setLiveSettingsVisibility() {
boolean isLiveTabVisible = !Setting.isLiveTabVisible(); // 注意:这里取反,因为开关是"隐藏直播"
// 获取直播容器的布局参数
LinearLayout.LayoutParams liveContainerParams = (LinearLayout.LayoutParams) mBinding.liveContainer.getLayoutParams();
if (isLiveTabVisible) {
// 直播开关打开:显示直播模块,间距为12dp
mBinding.liveContainer.setVisibility(View.VISIBLE);
liveContainerParams.topMargin = (int) TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics());
} else {
// 直播开关关闭:隐藏直播模块,间距为0dp(这样视频模块和下一个模块之间会有正常间距)
mBinding.liveContainer.setVisibility(View.GONE);
liveContainerParams.topMargin = 0;
}
// 应用布局参数
mBinding.liveContainer.setLayoutParams(liveContainerParams);
}
private void setCacheText() {
@@ -131,7 +156,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
protected void initEvent() {
mBinding.vod.setOnClickListener(this::onVod);
mBinding.live.setOnClickListener(this::onLive);
mBinding.wall.setOnClickListener(this::onWall);
// mBinding.wall.setOnClickListener(this::onWall); // 壁纸功能已移除
mBinding.proxy.setOnClickListener(this::onProxy);
mBinding.cache.setOnClickListener(this::onCache);
mBinding.backup.setOnClickListener(this::onBackup);
@@ -143,13 +168,14 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
mBinding.vodHome.setOnClickListener(this::onVodHome);
mBinding.live.setOnLongClickListener(this::onLiveEdit);
mBinding.liveHome.setOnClickListener(this::onLiveHome);
mBinding.wall.setOnLongClickListener(this::onWallEdit);
// mBinding.wall.setOnLongClickListener(this::onWallEdit); // 壁纸功能已移除
mBinding.vodHistory.setOnClickListener(this::onVodHistory);
mBinding.version.setOnLongClickListener(this::onVersionDev);
mBinding.liveHistory.setOnClickListener(this::onLiveHistory);
mBinding.wallDefault.setOnClickListener(this::setWallDefault);
mBinding.wallRefresh.setOnClickListener(this::setWallRefresh);
mBinding.incognito.setOnClickListener(this::setIncognito);
// mBinding.wallDefault.setOnClickListener(this::setWallDefault); // 壁纸功能已移除
// mBinding.wallRefresh.setOnClickListener(this::setWallRefresh); // 壁纸功能已移除
mBinding.incognitoSwitch.setOnClickListener(this::setIncognito);
mBinding.liveTabVisibleSwitch.setOnClickListener(this::setLiveTabVisible);
mBinding.size.setOnClickListener(this::setSize);
mBinding.doh.setOnClickListener(this::setDoh);
}
@@ -200,9 +226,9 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
case 2:
Notify.progress(getActivity());
WallConfig.load(config, getCallback(2));
if (mBinding != null && mBinding.wallUrl != null) {
mBinding.wallUrl.setText(config.getDesc());
}
// if (mBinding != null && mBinding.wallUrl != null) { // 壁纸功能已移除
// mBinding.wallUrl.setText(config.getDesc());
// }
break;
}
} catch (Exception e) {
@@ -241,7 +267,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc(), R.string.source_hint_live);
break;
case 2:
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall);
// setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall); // 壁纸功能已移除
break;
}
}
@@ -257,7 +283,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
RefreshEvent.config();
setSourceHintText(mBinding.vodUrl, VodConfig.getDesc(), R.string.source_hint_setting);
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc(), R.string.source_hint_live);
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall);
// setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall); // 壁纸功能已移除
break;
case 1:
setCacheText();
@@ -268,7 +294,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
case 2:
setCacheText();
Notify.dismiss();
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall);
// setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall); // 壁纸功能已移除
break;
}
}
@@ -379,7 +405,17 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
private void setIncognito(View view) {
boolean isChecked = !Setting.isIncognito();
Setting.putIncognito(isChecked);
mBinding.incognitoSwitch.setChecked(isChecked);
// 不需要再次调用 setChecked,因为点击已经触发了状态变化
}
private void setLiveTabVisible(View view) {
boolean isChecked = !Setting.isLiveTabVisible();
Setting.putLiveTabVisible(isChecked);
// 发送刷新事件,通知主界面更新导航栏
RefreshEvent.config();
// 更新直播设置项的可见性
setLiveSettingsVisibility();
// 不需要再次调用 setChecked,因为点击已经触发了状态变化
}
private void setSize(View view) {
@@ -473,7 +509,7 @@ public class SettingFragment extends BaseFragment implements ConfigCallback, Sit
if (hidden) return;
setSourceHintText(mBinding.vodUrl, VodConfig.getDesc(), R.string.source_hint_setting);
setSourceHintText(mBinding.liveUrl, LiveConfig.getDesc(), R.string.source_hint_live);
setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall);
// setSourceHintText(mBinding.wallUrl, WallConfig.getDesc(), R.string.source_hint_wall); // 壁纸功能已移除
setCacheText();
}
@@ -59,7 +59,7 @@ public class Timer {
public void delay() {
cancel();
set(TimeUnit.MINUTES.toMillis(5) + tick);
set(TimeUnit.MINUTES.toMillis(15) + tick);
}
public void reset() {
@@ -3,7 +3,7 @@
android:color="?attr/colorControlHighlight">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@color/yellow_50" />
<solid android:color="@color/primary" />
<corners android:radius="8dp" />
<padding
android:bottom="14dp"
@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:id="@android:id/mask">
<shape android:shape="rectangle">
<corners android:radius="8dp" />
<solid android:color="#f5f5f5" />
</shape>
</item>
<item>
<shape android:shape="rectangle">
<solid android:color="@color/black_20" />
<corners android:radius="8dp" />
<padding
android:bottom="8dp"
android:left="12dp"
android:right="12dp"
android:top="8dp" />
</shape>
</item>
</ripple>
@@ -3,7 +3,7 @@
android:color="?attr/colorControlHighlight">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@color/yellow_50" />
<solid android:color="@color/primary" />
<corners android:radius="8dp" />
<padding
android:bottom="10dp"
@@ -3,7 +3,7 @@
android:color="?attr/colorControlHighlight">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@color/yellow_50" />
<solid android:color="@color/primary" />
<corners android:radius="8dp" />
<padding
android:bottom="18dp"
@@ -3,7 +3,7 @@
android:color="?attr/colorControlHighlight">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@color/yellow_50" />
<solid android:color="@color/primary" />
<corners android:radius="8dp" />
<padding
android:bottom="18dp"
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@color/primary" />
<corners android:radius="8dp" />
<padding
android:bottom="12dp"
android:left="16dp"
android:right="16dp"
android:top="12dp" />
</shape>
</item>
</ripple>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?attr/colorControlHighlight">
<item android:id="@android:id/background">
<shape android:shape="rectangle">
<solid android:color="@color/black_20" />
<corners android:radius="8dp" />
<padding
android:bottom="12dp"
android:left="16dp"
android:right="16dp"
android:top="12dp" />
</shape>
</item>
</ripple>
+1 -1
View File
@@ -54,7 +54,7 @@
android:layout_marginTop="24dp"
android:background="@drawable/shape_about_button"
android:text="我的GitHub"
android:textColor="@color/white"
android:textColor="@color/black"
android:textSize="14sp"
android:padding="12dp"/>
+7 -4
View File
@@ -15,9 +15,12 @@
android:stepSize="1"
android:valueFrom="1"
android:valueTo="10"
app:thumbColor="@color/yellow_500"
app:tickVisible="false"
app:trackColorActive="@color/yellow_500"
app:trackColorInactive="@color/yellow_50" />
app:thumbColor="@color/accent"
app:thumbRadius="10dp"
app:tickVisible="true"
app:tickColor="@color/black_50"
app:trackColorActive="@color/accent"
app:trackColorInactive="@color/white_20"
app:trackHeight="6dp" />
</LinearLayout>
+27 -6
View File
@@ -8,13 +8,31 @@
android:padding="16dp"
tools:background="@color/white">
<TextView
android:layout_width="wrap_content"
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical">
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/control_speed"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp" />
<TextView
android:id="@+id/speedValue"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="1.0x"
android:textColor="?android:attr/textColorPrimary"
android:textSize="16sp"
android:textStyle="bold" />
</LinearLayout>
<com.google.android.material.slider.Slider
android:id="@+id/speed"
android:layout_width="match_parent"
@@ -24,10 +42,13 @@
android:stepSize="0.25"
android:valueFrom="0.5"
android:valueTo="5"
app:thumbColor="@color/yellow_500"
app:tickVisible="false"
app:trackColorActive="@color/yellow_500"
app:trackColorInactive="@color/yellow_50" />
app:thumbColor="@color/accent"
app:thumbRadius="10dp"
app:tickVisible="true"
app:tickColor="@color/black_50"
app:trackColorActive="@color/accent"
app:trackColorInactive="@color/white_20"
app:trackHeight="6dp" />
<TextView
android:id="@+id/parseText"
+6 -2
View File
@@ -15,8 +15,12 @@
android:stepSize="0.5"
android:valueFrom="2"
android:valueTo="5"
app:tickVisible="false"
app:thumbColor="@color/accent"
app:thumbRadius="10dp"
app:tickVisible="true"
app:tickColor="@color/black_50"
app:trackColorActive="@color/accent"
app:trackColorInactive="@color/yellow_50" />
app:trackColorInactive="@color/white_20"
app:trackHeight="6dp" />
</LinearLayout>
+64 -18
View File
@@ -29,50 +29,80 @@
<TextView
android:id="@+id/time1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="56dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/shape_accent"
android:background="@drawable/shape_accent_no_border"
android:tag="5"
android:text="@string/timer_5"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp" />
android:textSize="14sp"
android:gravity="center" />
<TextView
android:id="@+id/time2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="56dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/shape_accent"
android:background="@drawable/shape_accent_no_border"
android:tag="15"
android:text="@string/timer_15"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp" />
android:textSize="14sp"
android:gravity="center" />
<TextView
android:id="@+id/time3"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="56dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/shape_accent"
android:background="@drawable/shape_accent_no_border"
android:tag="30"
android:text="@string/timer_30"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp" />
android:textSize="14sp"
android:gravity="center" />
<TextView
android:id="@+id/time4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_height="56dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/shape_accent"
android:background="@drawable/shape_accent_no_border"
android:tag="60"
android:text="@string/timer_60"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp" />
android:textSize="14sp"
android:gravity="center" />
<TextView
android:id="@+id/time5"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/shape_accent_no_border"
android:tag="120"
android:text="@string/timer_120"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp"
android:gravity="center" />
<TextView
android:id="@+id/time6"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:background="@drawable/shape_accent_no_border"
android:tag="180"
android:text="@string/timer_180"
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp"
android:gravity="center" />
</LinearLayout>
@@ -96,25 +126,41 @@
android:textStyle="bold"
tools:text="5:00" />
<com.google.android.material.button.MaterialButton
<TextView
android:id="@+id/delay"
style="?attr/materialButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@drawable/shape_timer_delay_button"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:singleLine="true"
android:text="@string/timer_delay"
android:textColor="@color/white" />
android:textColor="@color/black"
android:textSize="14sp" />
<com.google.android.material.button.MaterialButton
<TextView
android:id="@+id/reset"
style="?attr/materialButtonOutlinedStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:background="@drawable/shape_timer_reset_button"
android:clickable="true"
android:focusable="true"
android:gravity="center"
android:paddingStart="30dp"
android:paddingEnd="30dp"
android:paddingTop="12dp"
android:paddingBottom="12dp"
android:singleLine="true"
android:text="@string/timer_cancel"
android:textColor="?android:attr/textColorPrimary" />
android:textColor="?android:attr/textColorPrimary"
android:textSize="14sp" />
</LinearLayout>
</LinearLayout>
+34 -60
View File
@@ -44,6 +44,7 @@
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="10dp"
android:fillViewport="true"
android:overScrollMode="never"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
@@ -145,6 +146,7 @@
</LinearLayout>
<LinearLayout
android:id="@+id/liveContainer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
@@ -205,66 +207,6 @@
</LinearLayout>
<!-- 壁纸功能已隐藏 -->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:gravity="center_vertical"
android:orientation="horizontal"
android:visibility="gone">
<LinearLayout
android:id="@+id/wall"
android:layout_width="0dp"
android:layout_height="56dp"
android:layout_marginEnd="12dp"
android:layout_weight="1"
android:background="@drawable/shape_item"
android:gravity="center_vertical"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="@string/setting_wall"
android:textColor="@color/white"
android:textSize="16sp" />
<TextView
android:id="@+id/wallUrl"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="middle"
android:gravity="end"
android:singleLine="true"
android:textColor="@color/white"
android:textSize="16sp"
tools:text="https://" />
</LinearLayout>
<ImageView
android:id="@+id/wallDefault"
android:layout_width="56dp"
android:layout_height="56dp"
android:layout_marginEnd="12dp"
android:background="@drawable/shape_item"
android:padding="16dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_setting_switch" />
<ImageView
android:id="@+id/wallRefresh"
android:layout_width="56dp"
android:layout_height="56dp"
android:background="@drawable/shape_item"
android:padding="16dp"
android:scaleType="fitCenter"
android:src="@drawable/ic_setting_refresh" />
</LinearLayout>
<!-- 应用设置分组 -->
<TextView
@@ -342,6 +284,38 @@
</LinearLayout>
<!-- 显示直播 -->
<LinearLayout
android:id="@+id/liveTabVisible"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical"
android:paddingTop="16dp"
android:paddingBottom="16dp">
<ImageView
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginEnd="16dp"
android:src="@drawable/ic_nav_live"
android:tint="@color/white" />
<TextView
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/setting_live_tab_visible"
android:textColor="@color/white"
android:textSize="16sp" />
<com.fongmi.android.tv.ui.custom.CustomSwitch
android:id="@+id/liveTabVisibleSwitch"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
<!-- 图片尺寸 -->
<LinearLayout
android:id="@+id/size"
@@ -23,6 +23,8 @@
android:layout_marginEnd="8dp"
android:layout_weight="1"
app:bar_height="2dp"
app:scrubber_enabled_size="12dp"
app:scrubber_disabled_size="12dp"
app:played_color="#FFEB3B"
app:scrubber_color="#FFEB3B"
app:buffered_color="#80FFEB3B" />
+3 -1
View File
@@ -43,7 +43,9 @@
<string name="timer_15">15 分钟</string>
<string name="timer_30">30 分钟</string>
<string name="timer_60">1 小时</string>
<string name="timer_delay">延长 5 分钟</string>
<string name="timer_120">2 小时</string>
<string name="timer_180">3 小时</string>
<string name="timer_delay">延长 15 分钟</string>
<string name="timer_cancel">取消定时器</string>
<!-- Hint -->
+3 -1
View File
@@ -41,7 +41,9 @@
<string name="timer_15">15 分鐘</string>
<string name="timer_30">30 分鐘</string>
<string name="timer_60">1 小時</string>
<string name="timer_delay">延長 5 分鐘</string>
<string name="timer_120">2 小時</string>
<string name="timer_180">3 小時</string>
<string name="timer_delay">延長 15 分鐘</string>
<string name="timer_cancel">取消定時器</string>
<!-- Hint -->
+3
View File
@@ -5,5 +5,8 @@
<color name="accent">#FFEB3B</color>
<color name="indicator">@color/white_80</color>
<color name="yellow_50">#4DFFEB3B</color>
<color name="white_50">#80FFFFFF</color>
<color name="black_50">#80000000</color>
<color name="white_30">#4DFFFFFF</color>
</resources>
+3 -1
View File
@@ -43,7 +43,9 @@
<string name="timer_15">15 minutes</string>
<string name="timer_30">30 minutes</string>
<string name="timer_60">1 hour</string>
<string name="timer_delay">Add 5 minutes</string>
<string name="timer_120">2 hours</string>
<string name="timer_180">3 hours</string>
<string name="timer_delay">Add 15 minutes</string>
<string name="timer_cancel">Cancel timer</string>
<!-- Hint -->
+3 -3
View File
@@ -9,7 +9,7 @@ tasks.register('clean', Delete) {
}
project.ext {
gsonVersion = '2.13.1'
media3Version = '1.8.0'
okhttpVersion = '5.1.0'
gsonVersion = '2.11.0'
media3Version = '1.4.1'
okhttpVersion = '4.12.0'
}