Cherish: Add support for UI Styles
Not a great previewer but for now it'll do the work [nurkeinneid]: - adapt to our ThemeUtils - restore original copyright header - crdroid did nothing here Change-Id: I432578a4b3c652d7ad3e00a93e11bfb3e199b4a5 Signed-off-by: NurKeinNeid <mralexman3000@gmail.com> Signed-off-by: Hưng Phan <phandinhhungvp2001@gmail.com>
This commit is contained in:
@@ -781,4 +781,8 @@
|
|||||||
|
|
||||||
<string name="click_partial_screenshot_title">Click to partial screenshot</string>
|
<string name="click_partial_screenshot_title">Click to partial screenshot</string>
|
||||||
<string name="click_partial_screenshot_summary">Short click Volume Down and Power to take partial screenshot</string>
|
<string name="click_partial_screenshot_summary">Short click Volume Down and Power to take partial screenshot</string>
|
||||||
|
|
||||||
|
<!-- UI styles -->
|
||||||
|
<string name="theme_customization_ui_style_title">UI Style</string>
|
||||||
|
<string name="theme_customization_ui_style_summary">Set custom style for your interface</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -59,6 +59,12 @@
|
|||||||
android:summary="@string/dark_ui_mode_summary"
|
android:summary="@string/dark_ui_mode_summary"
|
||||||
android:fragment="com.android.settings.display.darkmode.DarkModeSettingsFragment"
|
android:fragment="com.android.settings.display.darkmode.DarkModeSettingsFragment"
|
||||||
settings:controller="com.android.settings.display.DarkUIPreferenceController" />
|
settings:controller="com.android.settings.display.DarkUIPreferenceController" />
|
||||||
|
|
||||||
|
<Preference
|
||||||
|
android:key="android.theme.customization.style"
|
||||||
|
android:title="@string/theme_customization_ui_style_title"
|
||||||
|
android:summary="@string/theme_customization_ui_style_summary"
|
||||||
|
android:fragment="com.cherish.settings.fragments.ui.UIStyles"/>
|
||||||
|
|
||||||
<!-- QS style -->
|
<!-- QS style -->
|
||||||
<com.cherish.settings.preferences.SystemSettingListPreference
|
<com.cherish.settings.preferences.SystemSettingListPreference
|
||||||
|
|||||||
264
src/com/cherish/settings/fragments/ui/UIStyles.java
Normal file
264
src/com/cherish/settings/fragments/ui/UIStyles.java
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 AospExtended ROM Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.cherish.settings.fragments.ui;
|
||||||
|
|
||||||
|
import android.content.ContentResolver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
|
import android.provider.SearchIndexableResource;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.Gravity;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.LinearLayout;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
import android.widget.Toast;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import androidx.preference.PreferenceViewHolder;
|
||||||
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
|
||||||
|
import androidx.annotation.ColorInt;
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.recyclerview.widget.GridLayoutManager;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView.ViewHolder;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
import android.net.Uri;
|
||||||
|
import androidx.core.content.res.ResourcesCompat;
|
||||||
|
import androidx.preference.Preference;
|
||||||
|
import androidx.preference.Preference.OnPreferenceChangeListener;
|
||||||
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
|
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
|
import com.android.settingslib.search.Indexable;
|
||||||
|
import com.android.settings.SettingsPreferenceFragment;
|
||||||
|
|
||||||
|
import com.android.internal.util.cherish.ThemeUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
import org.json.JSONException;
|
||||||
|
|
||||||
|
public class UIStyles extends SettingsPreferenceFragment {
|
||||||
|
|
||||||
|
private RecyclerView mRecyclerView;
|
||||||
|
private ThemeUtils mThemeUtils;
|
||||||
|
private String mCategory = "android.theme.customization.style.android";
|
||||||
|
|
||||||
|
private List<String> mPkgs;
|
||||||
|
|
||||||
|
private ExecutorService mExecutor = Executors.newSingleThreadExecutor();
|
||||||
|
private Handler mHandler = new Handler();
|
||||||
|
private final AtomicBoolean mApplyingOverlays = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
Map<String, String> overlayMap = new HashMap<String, String>();
|
||||||
|
{
|
||||||
|
overlayMap.put("com.android.settings", "android.theme.customization.style.settings");
|
||||||
|
overlayMap.put("com.android.systemui", "android.theme.customization.style.systemui");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
getActivity().setTitle(R.string.theme_customization_ui_style_title);
|
||||||
|
|
||||||
|
mThemeUtils = new ThemeUtils(getActivity());
|
||||||
|
mPkgs = mThemeUtils.getOverlayPackagesForCategory(mCategory, "android");
|
||||||
|
Collections.sort(mPkgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
View view = inflater.inflate(
|
||||||
|
R.layout.item_view, container, false);
|
||||||
|
|
||||||
|
mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
||||||
|
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity(), 1);
|
||||||
|
mRecyclerView.setLayoutManager(gridLayoutManager);
|
||||||
|
Adapter mAdapter = new Adapter(getActivity());
|
||||||
|
mRecyclerView.setAdapter(mAdapter);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
return MetricsEvent.CHERISH_SETTINGS;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Adapter extends RecyclerView.Adapter<Adapter.CustomViewHolder> {
|
||||||
|
Context context;
|
||||||
|
String mSelectedPkg;
|
||||||
|
String mAppliedPkg;
|
||||||
|
|
||||||
|
public Adapter(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CustomViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.fonts_option, parent, false);
|
||||||
|
CustomViewHolder vh = new CustomViewHolder(v);
|
||||||
|
return vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(CustomViewHolder holder, final int position) {
|
||||||
|
String pkg = mPkgs.get(position);
|
||||||
|
String label = getLabel(holder.itemView.getContext(), pkg);
|
||||||
|
|
||||||
|
String currentPackageName = mThemeUtils.getOverlayInfos(mCategory).stream()
|
||||||
|
.filter(info -> info.isEnabled())
|
||||||
|
.map(info -> info.packageName)
|
||||||
|
.findFirst()
|
||||||
|
.orElse("android");
|
||||||
|
|
||||||
|
holder.title.setText("android".equals(pkg) ? "Default" : label);
|
||||||
|
holder.title.setTextSize(20);
|
||||||
|
holder.title.setBackgroundColor(getStyleColor(holder.title.getContext(), pkg));
|
||||||
|
holder.name.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
if (currentPackageName.equals(pkg)) {
|
||||||
|
mAppliedPkg = pkg;
|
||||||
|
if (mSelectedPkg == null) {
|
||||||
|
mSelectedPkg = pkg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.itemView.setActivated(pkg == mSelectedPkg);
|
||||||
|
holder.itemView.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mApplyingOverlays.get()) return;
|
||||||
|
updateActivatedStatus(mSelectedPkg, false);
|
||||||
|
updateActivatedStatus(pkg, true);
|
||||||
|
mSelectedPkg = pkg;
|
||||||
|
enableOverlays(position);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mPkgs.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CustomViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
TextView name;
|
||||||
|
TextView title;
|
||||||
|
public CustomViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
title = (TextView) itemView.findViewById(R.id.option_title);
|
||||||
|
name = (TextView) itemView.findViewById(R.id.option_label);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateActivatedStatus(String pkg, boolean isActivated) {
|
||||||
|
int index = mPkgs.indexOf(pkg);
|
||||||
|
if (index < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RecyclerView.ViewHolder holder = mRecyclerView.findViewHolderForAdapterPosition(index);
|
||||||
|
if (holder != null && holder.itemView != null) {
|
||||||
|
holder.itemView.setActivated(isActivated);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public @ColorInt int getStyleColor(Context context, String pkg) {
|
||||||
|
try {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
Resources res = pkg.equals("android") ? Resources.getSystem()
|
||||||
|
: pm.getResourcesForApplication(pkg);
|
||||||
|
Configuration configuration = context.getResources().getConfiguration();
|
||||||
|
boolean nightMode = (configuration.uiMode & Configuration.UI_MODE_NIGHT_MASK)
|
||||||
|
== Configuration.UI_MODE_NIGHT_YES ? true : false;
|
||||||
|
@ColorInt int styleColor = nightMode ? res.getColor(res.getIdentifier(
|
||||||
|
"system_neutral1_900", "color", pkg), null) : res.getColor(
|
||||||
|
res.getIdentifier(
|
||||||
|
"system_neutral1_100", "color", pkg), null);
|
||||||
|
return styleColor;
|
||||||
|
}
|
||||||
|
catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return Color.TRANSPARENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel(Context context, String pkg) {
|
||||||
|
PackageManager pm = context.getPackageManager();
|
||||||
|
try {
|
||||||
|
return pm.getApplicationInfo(pkg, 0)
|
||||||
|
.loadLabel(pm).toString();
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return pkg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enableOverlays(int position) {
|
||||||
|
mApplyingOverlays.set(true);
|
||||||
|
mExecutor.execute(() -> {
|
||||||
|
mThemeUtils.setOverlayEnabled(mCategory, mPkgs.get(position));
|
||||||
|
String pattern = "android".equals(mPkgs.get(position)) ? ""
|
||||||
|
: mPkgs.get(position).split("\\.")[4];
|
||||||
|
for (Map.Entry<String, String> entry : overlayMap.entrySet()) {
|
||||||
|
enableOverlay(entry.getValue(), entry.getKey(), pattern);
|
||||||
|
}
|
||||||
|
mHandler.post(() -> mApplyingOverlays.set(false));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enableOverlay(String category, String target, String pattern) {
|
||||||
|
if (pattern.isEmpty()) {
|
||||||
|
mThemeUtils.setOverlayEnabled(category, "android");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (String pkg: mThemeUtils.getOverlayPackagesForCategory(category, target)) {
|
||||||
|
if (pkg.contains(pattern)) {
|
||||||
|
mThemeUtils.setOverlayEnabled(category, pkg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user