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_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>
|
||||
|
||||
@@ -59,6 +59,12 @@
|
||||
android:summary="@string/dark_ui_mode_summary"
|
||||
android:fragment="com.android.settings.display.darkmode.DarkModeSettingsFragment"
|
||||
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 -->
|
||||
<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