From 4935e547dc033744880382e52e43c9d99c18ee24 Mon Sep 17 00:00:00 2001 From: FongMi Date: Tue, 12 May 2026 00:44:17 +0800 Subject: [PATCH] Optimize theme setting --- app/build.gradle | 2 +- .../fongmi/android/tv/event/RefreshEvent.java | 6 ++- .../fongmi/android/tv/setting/Setting.java | 13 +++++ .../android/tv/ui/custom/CustomWallView.java | 48 +++++++++++++++++-- .../android/tv/ui/activity/HomeActivity.java | 12 +++-- .../android/tv/ui/adapter/ThemeAdapter.java | 21 ++------ .../android/tv/ui/base/BaseActivity.java | 6 +-- .../tv/ui/custom/FragmentStateManager.java | 1 - .../tv/ui/fragment/SettingFragment.java | 3 +- 9 files changed, 81 insertions(+), 31 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index cc436e282..ee0689f1d 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -107,6 +107,7 @@ dependencies { implementation libs.appcompat implementation libs.lifecycle.service implementation libs.media + implementation libs.palette implementation libs.recyclerview implementation libs.room.runtime implementation libs.splashscreen @@ -129,7 +130,6 @@ dependencies { implementation libs.textdrawable leanbackImplementation libs.leanback leanbackImplementation libs.androidautosize - mobileImplementation libs.palette mobileImplementation libs.biometric mobileImplementation libs.zxing.android.embedded annotationProcessor libs.room.compiler diff --git a/app/src/main/java/com/fongmi/android/tv/event/RefreshEvent.java b/app/src/main/java/com/fongmi/android/tv/event/RefreshEvent.java index 7044bf46e..2e58156ae 100644 --- a/app/src/main/java/com/fongmi/android/tv/event/RefreshEvent.java +++ b/app/src/main/java/com/fongmi/android/tv/event/RefreshEvent.java @@ -30,6 +30,10 @@ public class RefreshEvent { EventBus.getDefault().post(new RefreshEvent(Type.SIZE)); } + public static void theme() { + EventBus.getDefault().post(new RefreshEvent(Type.THEME)); + } + public static void live() { EventBus.getDefault().post(new RefreshEvent(Type.LIVE)); } @@ -81,6 +85,6 @@ public class RefreshEvent { } public enum Type { - HOME, CATEGORY, HISTORY, KEEP, SIZE, LIVE, DETAIL, PLAYER, SUBTITLE, DANMAKU, VOD + HOME, CATEGORY, HISTORY, KEEP, SIZE, THEME, LIVE, DETAIL, PLAYER, SUBTITLE, DANMAKU, VOD } } diff --git a/app/src/main/java/com/fongmi/android/tv/setting/Setting.java b/app/src/main/java/com/fongmi/android/tv/setting/Setting.java index d86505637..def3cd943 100644 --- a/app/src/main/java/com/fongmi/android/tv/setting/Setting.java +++ b/app/src/main/java/com/fongmi/android/tv/setting/Setting.java @@ -115,4 +115,17 @@ public class Setting { public static void putThemeColor(int color) { Prefers.put("theme_color", color); } + + public static int getWallColor() { + return Prefers.getInt("wall_color", 0); + } + + public static void putWallColor(int color) { + Prefers.put("wall_color", color); + } + + public static int getDynamicColor() { + int color = getThemeColor(); + return color == 0 ? getWallColor() : color; + } } diff --git a/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWallView.java b/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWallView.java index 38c8b8c37..0b2eb29ca 100644 --- a/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWallView.java +++ b/app/src/main/java/com/fongmi/android/tv/ui/custom/CustomWallView.java @@ -1,6 +1,8 @@ package com.fongmi.android.tv.ui.custom; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import android.net.Uri; import android.util.AttributeSet; @@ -16,10 +18,12 @@ import androidx.media3.common.MediaItem; import androidx.media3.common.Player; import androidx.media3.exoplayer.ExoPlayer; import androidx.media3.ui.PlayerView; +import androidx.palette.graphics.Palette; import com.fongmi.android.tv.R; import com.fongmi.android.tv.databinding.ViewWallBinding; import com.fongmi.android.tv.event.ConfigEvent; +import com.fongmi.android.tv.event.RefreshEvent; import com.fongmi.android.tv.setting.Setting; import com.fongmi.android.tv.utils.FileUtil; @@ -34,11 +38,11 @@ import pl.droidsonroids.gif.GifDrawable; public class CustomWallView extends FrameLayout implements DefaultLifecycleObserver { + private static final int[] WALL_PAPERS = {0, R.drawable.wallpaper_1, R.drawable.wallpaper_2, R.drawable.wallpaper_3, R.drawable.wallpaper_4}; + private static final int[] WALL_COLORS = {0, 0xFF40C090, 0xFF4870E0, 0xFF48B0C0, 0xFF404040}; private static final int TYPE_RES = 0; private static final int TYPE_GIF = 1; private static final int TYPE_VIDEO = 2; - private static final int[] BUILT_IN = {0, R.drawable.wallpaper_1, R.drawable.wallpaper_2, R.drawable.wallpaper_3, R.drawable.wallpaper_4}; - private ViewWallBinding binding; private GifDrawable drawable; private PlayerView video; @@ -65,6 +69,7 @@ public class CustomWallView extends FrameLayout implements DefaultLifecycleObser private void refresh() { stop(); load(); + theme(); } private void stop() { @@ -86,12 +91,17 @@ public class CustomWallView extends FrameLayout implements DefaultLifecycleObser private void load() { int wall = Setting.getWall(); int type = Setting.getWallType(); - if (type == TYPE_RES && wall > 0 && wall < BUILT_IN.length) loadRes(BUILT_IN[wall]); + if (isBuiltIn(wall, type)) loadRes(WALL_PAPERS[wall]); else if (type == TYPE_VIDEO) loadVideo(FileUtil.getWall(wall)); else if (type == TYPE_GIF) loadGif(FileUtil.getWall(wall)); else loadImage(); } + private void theme() { + Setting.putWallColor(getWallColor()); + if (Setting.getThemeColor() == 0) RefreshEvent.theme(); + } + private void loadRes(int resId) { binding.image.setImageResource(resId); } @@ -149,6 +159,38 @@ public class CustomWallView extends FrameLayout implements DefaultLifecycleObser return player != null && video != null && video.getVisibility() == VISIBLE && player.getMediaItemCount() > 0; } + private int getWallColor() { + int wall = Setting.getWall(); + int type = Setting.getWallType(); + if (isBuiltIn(wall, type)) return WALL_COLORS[wall]; + File file = FileUtil.getWallCache(); + return file.exists() ? paletteColor(file) : WALL_COLORS[1]; + } + + private int paletteColor(File file) { + Bitmap bitmap = decodeBitmap(file); + if (bitmap == null) return WALL_COLORS[1]; + Palette palette = Palette.from(bitmap).maximumColorCount(8).generate(); + bitmap.recycle(); + return swatchColor(palette); + } + + private Bitmap decodeBitmap(File file) { + BitmapFactory.Options opts = new BitmapFactory.Options(); + opts.inSampleSize = 8; + return BitmapFactory.decodeFile(file.getAbsolutePath(), opts); + } + + private int swatchColor(Palette palette) { + Palette.Swatch swatch = palette.getVibrantSwatch(); + if (swatch == null) swatch = palette.getDominantSwatch(); + return swatch != null ? swatch.getRgb() : WALL_COLORS[1]; + } + + private boolean isBuiltIn(int wall, int type) { + return type == TYPE_RES && wall > 0 && wall < WALL_PAPERS.length; + } + @Override public void onCreate(@NonNull LifecycleOwner owner) { EventBus.getDefault().register(this); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/HomeActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/HomeActivity.java index 00960ad8b..bd71c7ecb 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/activity/HomeActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/activity/HomeActivity.java @@ -77,14 +77,14 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt @Override protected void initView(Bundle savedInstanceState) { orientation = getResources().getConfiguration().orientation; + mBinding.navigation.setOnItemSelectedListener(this); + initFragment(savedInstanceState == null); Updater.create().start(this); - initFragment(); initConfig(); } @Override protected void initEvent() { - mBinding.navigation.setOnItemSelectedListener(this); mBinding.navigation.findViewById(R.id.live).setOnLongClickListener(this::addShortcut); } @@ -107,7 +107,7 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt } } - private void initFragment() { + private void initFragment(boolean init) { mManager = new FragmentStateManager(mBinding.container, getSupportFragmentManager()) { @Override public Fragment getItem(int position) { @@ -118,6 +118,7 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt return null; } }; + if (init) change(0); } private void initConfig() { @@ -189,6 +190,11 @@ public class HomeActivity extends BaseActivity implements NavigationBarView.OnIt } } + @Subscribe(threadMode = ThreadMode.MAIN) + public void onRefreshEvent(RefreshEvent event) { + if (event.getType() == RefreshEvent.Type.THEME) recreate(); + } + @Subscribe(threadMode = ThreadMode.MAIN) public void onServerEvent(ServerEvent event) { if (event.type() == ServerEvent.Type.PUSH) VideoActivity.push(this, event.text()); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/adapter/ThemeAdapter.java b/app/src/mobile/java/com/fongmi/android/tv/ui/adapter/ThemeAdapter.java index c163a2f32..be88d0e52 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/adapter/ThemeAdapter.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/adapter/ThemeAdapter.java @@ -8,21 +8,19 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; -import com.fongmi.android.tv.App; import com.fongmi.android.tv.databinding.AdapterThemeBinding; -import com.google.android.material.color.DynamicColors; -import com.google.android.material.color.MaterialColors; +import com.fongmi.android.tv.setting.Setting; public class ThemeAdapter extends RecyclerView.Adapter { private final OnClickListener listener; private final int[] mItems; - private int selected; + private final int selected; public ThemeAdapter(OnClickListener listener, int[] items, int selected) { this.listener = listener; - this.mItems = items; this.selected = selected; + this.mItems = items; } public interface OnClickListener { @@ -30,11 +28,6 @@ public class ThemeAdapter extends RecyclerView.Adapter void onItemClick(int color); } - public void setSelected(int color) { - selected = color; - notifyItemRangeChanged(0, getItemCount()); - } - @Override public int getItemCount() { return mItems.length; @@ -49,22 +42,18 @@ public class ThemeAdapter extends RecyclerView.Adapter @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { int color = mItems[position]; - holder.binding.circle.setBackground(getCircle(color)); holder.binding.getRoot().setOnClickListener(v -> listener.onItemClick(color)); holder.binding.check.setVisibility(selected == color ? View.VISIBLE : View.INVISIBLE); + holder.binding.circle.setBackground(getCircle(color == 0 ? Setting.getWallColor() : color)); } private GradientDrawable getCircle(int color) { GradientDrawable circle = new GradientDrawable(); circle.setShape(GradientDrawable.OVAL); - circle.setColor(color == 0 ? getPrimaryColor() : color); + circle.setColor(color); return circle; } - private int getPrimaryColor() { - return MaterialColors.getColor(DynamicColors.wrapContextIfAvailable(App.get()), android.R.attr.colorPrimary, 0xFF6750A4); - } - public class ViewHolder extends RecyclerView.ViewHolder { private final AdapterThemeBinding binding; diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/base/BaseActivity.java b/app/src/mobile/java/com/fongmi/android/tv/ui/base/BaseActivity.java index 4d85f9608..666f4a0b8 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/base/BaseActivity.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/base/BaseActivity.java @@ -32,9 +32,9 @@ public abstract class BaseActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); enableEdgeToEdge(); enableDynamicColor(); + super.onCreate(savedInstanceState); setContentView(getBinding().getRoot()); EventBus.getDefault().register(this); initView(savedInstanceState); @@ -109,9 +109,7 @@ public abstract class BaseActivity extends AppCompatActivity { } private void enableDynamicColor() { - DynamicColors.applyToActivityIfAvailable(this); - int color = Setting.getThemeColor(); - if (color != 0) DynamicColors.applyToActivityIfAvailable(this, new DynamicColorsOptions.Builder().setContentBasedSource(color).build()); + DynamicColors.applyToActivityIfAvailable(this, new DynamicColorsOptions.Builder().setContentBasedSource(Setting.getDynamicColor()).build()); } @Subscribe(threadMode = ThreadMode.MAIN) diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/custom/FragmentStateManager.java b/app/src/mobile/java/com/fongmi/android/tv/ui/custom/FragmentStateManager.java index 23a786c63..353b9d27e 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/custom/FragmentStateManager.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/custom/FragmentStateManager.java @@ -18,7 +18,6 @@ public abstract class FragmentStateManager { public FragmentStateManager(ViewGroup container, FragmentManager fm) { this.container = container; this.fm = fm; - change(0); } public abstract Fragment getItem(int position); diff --git a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java index 257b8e10d..1ce5e1e9a 100644 --- a/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java +++ b/app/src/mobile/java/com/fongmi/android/tv/ui/fragment/SettingFragment.java @@ -198,8 +198,7 @@ public class SettingFragment extends BaseFragment implements ConfigListener, Sit @Override public void setTheme(int color) { Setting.putThemeColor(color); - requireActivity().recreate(); - getRoot().change(0); + RefreshEvent.theme(); } private void onVod(View view) {