Improve layout and top blur, fix light theme.

pull/85/head
Fox2Code 2 years ago
parent 63224b76fd
commit 6f7c40393e

@ -3,21 +3,17 @@ package com.fox2code.mmm;
import androidx.annotation.NonNull;
import androidx.appcompat.widget.SearchView;
import androidx.cardview.widget.CardView;
import androidx.core.view.WindowInsetsCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.TextView;
@ -36,7 +32,8 @@ import eightbitlab.com.blurview.BlurView;
import eightbitlab.com.blurview.RenderScriptBlur;
public class MainActivity extends CompatActivity implements SwipeRefreshLayout.OnRefreshListener,
SearchView.OnQueryTextListener, SearchView.OnCloseListener {
SearchView.OnQueryTextListener, SearchView.OnCloseListener,
OverScrollManager.OverScrollHelper {
private static final String TAG = "MainActivity";
private static final int PRECISION = 10000;
public final ModuleViewListBuilder moduleViewListBuilder;
@ -46,6 +43,8 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
private int swipeRefreshLayoutOrigStartOffset;
private int swipeRefreshLayoutOrigEndOffset;
private long swipeRefreshBlocker = 0;
private int overScrollInsetTop;
private int overScrollInsetBottom;
private TextView actionBarPadding;
private BlurView actionBarBlur;
private RecyclerView moduleList;
@ -70,9 +69,10 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
this.setTitle(R.string.app_name);
this.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS,
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION |
WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS);
setActionBarBackground(null);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
WindowManager.LayoutParams layoutParams = this.getWindow().getAttributes();
layoutParams.layoutInDisplayCutoutMode = // Support cutout in Android 9
@ -95,6 +95,7 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
this.moduleList.setAdapter(this.moduleViewAdapter);
this.moduleList.setLayoutManager(new LinearLayoutManager(this));
this.moduleList.setItemViewCacheSize(4); // Default is 2
OverScrollManager.install(this.moduleList, this);
this.swipeRefreshLayout.setOnRefreshListener(this);
this.actionBarBlur.setupWith(this.moduleList).setFrameClearDrawable(
this.getWindow().getDecorView().getBackground())
@ -109,7 +110,7 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
}
});
this.searchView.setImeOptions(EditorInfo.IME_ACTION_SEARCH |
EditorInfo.IME_FLAG_NO_FULLSCREEN | EditorInfo.IME_FLAG_FORCE_ASCII);
EditorInfo.IME_FLAG_NO_FULLSCREEN);
this.searchView.setOnQueryTextListener(this);
this.searchView.setOnCloseListener(this);
this.searchView.setOnQueryTextFocusChangeListener((v, h) -> {
@ -230,10 +231,13 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
swipeRefreshLayoutOrigStartOffset + combinedBarsHeight,
swipeRefreshLayoutOrigEndOffset + combinedBarsHeight);
this.moduleViewListBuilder.setHeaderPx(actionBarHeight);
this.moduleViewListBuilder.setFooterPx((landscape ? 0 :
this.getNavigationBarHeight()) + this.searchCard.getHeight());
int bottomInset = (landscape ? 0 : this.getNavigationBarHeight());
this.moduleViewListBuilder.setFooterPx(
bottomInset + this.searchCard.getHeight());
this.moduleViewListBuilder.updateInsets();
this.actionBarBlur.invalidate();
this.overScrollInsetTop = combinedBarsHeight;
this.overScrollInsetBottom = bottomInset;
}
@Override
@ -360,4 +364,14 @@ public class MainActivity extends CompatActivity implements SwipeRefreshLayout.O
}
return false;
}
@Override
public int getOverScrollInsetTop() {
return this.overScrollInsetTop;
}
@Override
public int getOverScrollInsetBottom() {
return this.overScrollInsetBottom;
}
}

@ -103,6 +103,7 @@ public class ModuleViewListBuilder {
this.updating = true;
final ArrayList<ModuleHolder> moduleHolders;
final int newNotificationsLen;
final boolean first;
final ModuleHolder[] headerFooter = new ModuleHolder[2];
try {
synchronized (this.updateLock) {
@ -120,6 +121,7 @@ public class ModuleViewListBuilder {
moduleHolders.add(new ModuleHolder(notificationType));
}
}
first = moduleViewAdapter.moduleHolders.isEmpty();
newNotificationsLen = this.notifications.size() + 1 - special;
EnumSet<ModuleHolder.Type> headerTypes = EnumSet.of(ModuleHolder.Type.SEPARATOR,
ModuleHolder.Type.NOTIFICATION, ModuleHolder.Type.FOOTER);
@ -170,9 +172,7 @@ public class ModuleViewListBuilder {
this.updateInsets = RUNNABLE;
final EnumSet<NotificationType> oldNotifications =
EnumSet.noneOf(NotificationType.class);
boolean isTop = // Force isTop if empty
moduleViewAdapter.moduleHolders.isEmpty() ||
!moduleList.canScrollVertically(-1);
boolean isTop = first || !moduleList.canScrollVertically(-1);
boolean isBottom = !isTop && !moduleList.canScrollVertically(1);
int oldNotificationsLen = 0;
int oldOfflineModulesLen = 0;
@ -182,7 +182,8 @@ public class ModuleViewListBuilder {
oldNotifications.add(notificationType);
if (!notificationType.special)
oldNotificationsLen++;
} else if (moduleHolder.footerPx != -1)
} else if (moduleHolder.footerPx != -1 &&
moduleHolder.filterLevel == 1)
oldNotificationsLen++; // Fix header
if (moduleHolder.separator == ModuleHolder.Type.INSTALLABLE)
break;

@ -0,0 +1,92 @@
package com.fox2code.mmm;
import android.util.Log;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.fox2code.mmm.compat.CompatDisplay;
import com.mikepenz.aboutlibraries.LibsConfiguration;
public class OverScrollManager {
private static final String TAG = "OverScrollManager";
public interface OverScrollHelper {
int getOverScrollInsetTop();
int getOverScrollInsetBottom();
}
public static class LibsOverScroll implements LibsConfiguration.LibsUIListener {
private final OverScrollHelper overScrollHelper;
public LibsOverScroll() {
this.overScrollHelper = null;
}
public LibsOverScroll(OverScrollHelper overScrollHelper) {
this.overScrollHelper = overScrollHelper;
}
@NonNull
@Override
public View preOnCreateView(@NonNull View view) {
return view;
}
@NonNull
@Override
public View postOnCreateView(@NonNull View view) {
OverScrollManager.install(
view.findViewById(R.id.cardListView),
this.overScrollHelper);
return view;
}
}
public static void install(final RecyclerView recyclerView) {
OverScrollManager.install(recyclerView, null);
}
public static void install(final RecyclerView recyclerView,
final OverScrollHelper overScrollHelper) {
if (recyclerView == null) return;
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
int prevState = -1, lastTranslation = 0;
@Override
public void onScrollStateChanged(@NonNull RecyclerView recyclerView, int newState) {
if (newState == RecyclerView.SCROLL_STATE_IDLE && this.prevState != newState) {
if (recyclerView.getOverScrollMode() != View.OVER_SCROLL_NEVER)
recyclerView.setOverScrollMode(View.OVER_SCROLL_NEVER);
final int threshold = CompatDisplay.dpToPixel(16);
final int lastTranslation = this.lastTranslation;
if (lastTranslation < threshold) {
this.prevState = newState;
return;
}
final int insetTop;
final int insetBottom;
if (overScrollHelper == null) {
insetTop = 0;
insetBottom = 0;
} else {
insetTop = overScrollHelper.getOverScrollInsetTop();
insetBottom = overScrollHelper.getOverScrollInsetBottom();
}
Log.d(TAG, "Overscroll: " + lastTranslation + " -> ("
+ insetTop + ", " + insetBottom + ")");
// TODO Overscroll effect for 5.0 (With settings toggle)
}
this.prevState = newState;
}
@Override
public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) {
this.lastTranslation = dy;
}
});
}
}

@ -78,11 +78,16 @@ public class AndroidacyActivity extends CompatActivity {
String title = intent.getStringExtra(Constants.EXTRA_ANDROIDACY_ACTIONBAR_TITLE);
String config = intent.getStringExtra(Constants.EXTRA_ANDROIDACY_ACTIONBAR_CONFIG);
this.setContentView(R.layout.webview);
setActionBarBackground(null);
this.setDisplayHomeAsUpEnabled(true);
if (title == null || title.isEmpty()) {
this.setTitle(title);
} else {
this.setTitle("Androidacy");
}
if (allowInstall || title == null || title.isEmpty()) {
this.hideActionBar();
} else { // Only used for note section
this.setTitle(title);
this.setDisplayHomeAsUpEnabled(true);
if (config != null && !config.isEmpty()) {
String configPkg = IntentHelper.getPackageOfConfig(config);
try {

@ -5,6 +5,7 @@ import android.app.Application;
import android.content.Context;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.os.Build;
@ -17,6 +18,7 @@ import android.view.View;
import androidx.annotation.CallSuper;
import androidx.annotation.Dimension;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.Px;
import androidx.annotation.StringRes;
@ -322,6 +324,13 @@ public class CompatActivity extends AppCompatActivity {
}
}
@Override
public void onConfigurationChanged(@NonNull Configuration newConfig) {
this.compatConfigHelper.checkResourcesOverrides(this.getTheme(),
this.forceEnglish, this.nightModeOverride);
super.onConfigurationChanged(newConfig);
}
public void setOnBackPressedCallback(OnBackPressedCallback onBackPressedCallback) {
this.onBackPressedCallback = onBackPressedCallback;
}

@ -14,9 +14,13 @@ import java.util.Locale;
final class CompatConfigHelper {
// ENGLISH like this is an unnatural local, as it doesn't precise the country
// All english locales settable by the user precise the country (Ex: en-US)
private static final Locale english = Locale.ENGLISH;
private static final Locale englishLocale = Locale.ENGLISH;
private static final Object englishLocales =
Build.VERSION.SDK_INT >= Build.VERSION_CODES.N ?
new LocaleList(englishLocale) : null;
private final Context context;
private Object userLocales;
private Locale userLocale;
CompatConfigHelper(Context context) {
@ -32,22 +36,35 @@ final class CompatConfigHelper {
void checkResourcesOverrides(Resources.Theme theme, boolean forceEnglish,
Boolean nightModeOverride) {
final Resources res = theme.getResources();
final Configuration conf = res.getConfiguration();
Resources res = theme.getResources();
if (this.checkResourcesOverrides(res.getConfiguration(),
forceEnglish, nightModeOverride)) {
res.updateConfiguration(
res.getConfiguration(),
res.getDisplayMetrics());
}
}
boolean checkResourcesOverrides(Configuration conf, boolean forceEnglish,
Boolean nightModeOverride) {
Locale current = conf.locale;
boolean didChange = false;
if (forceEnglish != current.equals(english)) {
boolean wasForceEnglish = englishLocale.equals(current);
if (forceEnglish != wasForceEnglish) {
didChange = true;
if (forceEnglish) {
this.userLocale = conf.locale;
conf.locale = english;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
conf.setLocales(LocaleList.getEmptyLocaleList());
this.userLocales = conf.getLocales();
}
conf.locale = englishLocale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
conf.setLocales((LocaleList) englishLocales);
}
} else {
conf.locale = this.userLocale;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
conf.setLocales(LocaleList.getAdjustedDefault());
conf.setLocales((LocaleList) this.userLocales);
}
}
}
@ -62,15 +79,16 @@ final class CompatConfigHelper {
Configuration.UI_MODE_NIGHT_YES : Configuration.UI_MODE_NIGHT_NO;
conf.uiMode = nightMode | (conf.uiMode & ~Configuration.UI_MODE_NIGHT_MASK);
}
if (didChange) {
res.updateConfiguration(conf, null);
if (!forceEnglish) this.userLocale = null;
if (!forceEnglish && !wasForceEnglish) {
this.userLocale = null;
this.userLocales = null;
}
return didChange;
}
public Locale getUserLocale() {
// Only use cached value if force english
Locale locale = this.context.getResources().getConfiguration().locale;
return english.equals(locale) ? this.userLocale : locale;
return englishLocale.equals(locale) ? this.userLocale : locale;
}
}

@ -57,6 +57,7 @@ public class InstallerActivity extends CompatActivity {
Log.e(TAG, "Failed to mkdir module cache dir!");
super.onCreate(savedInstanceState);
this.setDisplayHomeAsUpEnabled(true);
setActionBarBackground(null);
this.setOnBackPressedCallback(a -> {
this.canceled = true; return false;
});

@ -43,8 +43,9 @@ public class MarkdownActivity extends CompatActivity {
String config = intent.getExtras()
.getString(Constants.EXTRA_MARKDOWN_CONFIG);
if (title != null && !title.isEmpty()) {
setTitle(title);
this.setTitle(title);
}
setActionBarBackground(null);
this.getWindow().setFlags(
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION,
WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);

@ -1,19 +1,23 @@
package com.fox2code.mmm.settings;
import android.os.Bundle;
import android.view.View;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.fox2code.mmm.AppUpdateManager;
import com.fox2code.mmm.BuildConfig;
import com.fox2code.mmm.Constants;
import com.fox2code.mmm.MainApplication;
import com.fox2code.mmm.OverScrollManager;
import com.fox2code.mmm.R;
import com.fox2code.mmm.compat.CompatActivity;
import com.fox2code.mmm.compat.CompatThemeWrapper;
@ -23,6 +27,8 @@ import com.fox2code.mmm.repo.RepoManager;
import com.fox2code.mmm.utils.Http;
import com.fox2code.mmm.utils.IntentHelper;
import com.mikepenz.aboutlibraries.LibsBuilder;
import com.mikepenz.aboutlibraries.LibsConfiguration;
import com.mikepenz.aboutlibraries.ui.LibsSupportFragment;
import com.topjohnwu.superuser.internal.UiThreadHandler;
public class SettingsActivity extends CompatActivity {
@ -35,6 +41,7 @@ public class SettingsActivity extends CompatActivity {
this.setDisplayHomeAsUpEnabled(true);
setContentView(R.layout.settings_activity);
setTitle(R.string.app_name);
setActionBarBackground(null);
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
@ -50,6 +57,7 @@ public class SettingsActivity extends CompatActivity {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getPreferenceManager().setSharedPreferencesName("mmm");
setPreferencesFromResource(R.xml.root_preferences, rootKey);
OverScrollManager.install(getListView());
findPreference("pref_manage_repos").setOnPreferenceClickListener(p -> {
devModeStep = 0;
openFragment(new RepoFragment(), R.string.manage_repos_pref);
@ -100,7 +108,8 @@ public class SettingsActivity extends CompatActivity {
}
final LibsBuilder libsBuilder = new LibsBuilder().withShowLoadingProgress(false)
.withLicenseShown(true).withAboutMinimalDesign(false);
.withLicenseShown(true).withAboutMinimalDesign(false)
.withUiListener(new OverScrollManager.LibsOverScroll());
Preference update = findPreference("pref_update");
update.setVisible(AppUpdateManager.getAppUpdateManager().peekHasUpdate());
update.setOnPreferenceClickListener(p -> {
@ -162,6 +171,7 @@ public class SettingsActivity extends CompatActivity {
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
getPreferenceManager().setSharedPreferencesName("mmm");
setPreferencesFromResource(R.xml.repo_preferences, rootKey);
OverScrollManager.install(getListView());
setRepoData(RepoManager.MAGISK_ALT_REPO,
"Magisk Modules Alt Repo", RepoManager.MAGISK_ALT_REPO_HOMEPAGE,
null, null,

@ -50,15 +50,15 @@
android:id="@+id/search_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginLeft="12dp"
android:layout_marginRight="12dp"
android:layout_marginTop="8dp"
android:layout_marginBottom="8dp"
android:gravity="center_vertical"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:gravity="right"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:fitsSystemWindowsInsets="bottom">
app:fitsSystemWindowsInsets="bottom"
tools:ignore="RtlHardcoded">
<androidx.cardview.widget.CardView
android:id="@+id/search_card"
android:layout_gravity="center"
@ -68,6 +68,7 @@
android:background="@null"
app:cardCornerRadius="75dp"
app:strokeColor="@android:color/transparent"
app:cardElevation="0dp"
app:strokeWidth="0dp">
<androidx.appcompat.widget.SearchView
android:id="@+id/search_bar"

@ -18,6 +18,7 @@
app:cardCornerRadius="@dimen/card_corner_radius"
app:strokeColor="@android:color/transparent"
app:cardPreventCornerOverlap="true"
app:cardElevation="0dp"
app:strokeWidth="0dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="status_bar_color">@color/transparent</color>
</resources>

@ -9,6 +9,8 @@
<color name="orange_200">#FFA726</color>
<color name="black_transparent">#80000000</color>
<color name="white_transparent">#80FFFFFF</color>
<color name="transparent">#00000000</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
<color name="status_bar_color">@color/black_transparent</color>
</resources>

@ -4,7 +4,7 @@
tools:targetApi="q">true</item>
<item name="isLightTheme">true</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/white</item>
<item name="colorPrimary">@color/orange_200</item>
<item name="colorPrimaryVariant">@color/white</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
@ -12,7 +12,8 @@
<item name="colorSecondaryVariant">@color/orange_200</item>
<item name="colorOnSecondary">@color/white</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:statusBarColor">@color/status_bar_color</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">true</item>
<!-- Customize your theme here. -->
<item name="android:windowActivityTransitions">true</item>
<!-- <item name="android:activityOpenEnterAnimation">@*android:anim/slide_in_right</item>
@ -25,13 +26,12 @@
<item name="dialogCornerRadius">@dimen/card_corner_radius</item>
</style>
<!-- Base application theme. -->
<style name="Theme.MagiskModuleManager.Dark" parent="Theme.MaterialComponents">
<item name="android:isLightTheme"
tools:targetApi="q">false</item>
<item name="isLightTheme">false</item>
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimary">@color/orange_200</item>
<item name="colorPrimaryVariant">@color/black</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
@ -39,7 +39,8 @@
<item name="colorSecondaryVariant">@color/orange_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<item name="android:statusBarColor">@color/status_bar_color</item>
<item name="android:windowLightStatusBar" tools:targetApi="m">false</item>
<!-- Customize your theme here. -->
<item name="android:windowActivityTransitions">true</item>
<!-- <item name="android:activityOpenEnterAnimation">@*android:anim/slide_in_right</item>

Loading…
Cancel
Save