Fix blinking

This commit is contained in:
NekoInverter 2020-03-21 10:39:13 +08:00
parent 0414193c04
commit 80be603f84
No known key found for this signature in database
GPG Key ID: 280D6CCCF95715F9
8 changed files with 71 additions and 124 deletions

View File

@ -22,9 +22,6 @@
<activity <activity
android:name=".CrashReportActivity" android:name=".CrashReportActivity"
android:process=":error_activity" /> android:process=":error_activity" />
<activity
android:name=".CompatListActivity"
android:label="@string/nav_title_compat_list" />
<activity <activity
android:name=".AboutActivity" android:name=".AboutActivity"
android:label="@string/About" /> android:label="@string/About" />

View File

@ -19,11 +19,12 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import org.meowcat.edxposed.manager.adapters.AppAdapter; import org.meowcat.edxposed.manager.adapters.AppAdapter;
import org.meowcat.edxposed.manager.adapters.AppHelper; import org.meowcat.edxposed.manager.adapters.AppHelper;
import org.meowcat.edxposed.manager.adapters.BlackListAdapter; import org.meowcat.edxposed.manager.adapters.BlackListAdapter;
import org.meowcat.edxposed.manager.adapters.CompatListAdapter;
import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding; import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding;
public class BlackListActivity extends BaseActivity implements AppAdapter.Callback { public class BlackListActivity extends BaseActivity implements AppAdapter.Callback {
private SearchView searchView; private SearchView searchView;
private BlackListAdapter appAdapter; private AppAdapter appAdapter;
private SearchView.OnQueryTextListener searchListener; private SearchView.OnQueryTextListener searchListener;
private ActivityBlackListBinding binding; private ActivityBlackListBinding binding;
@ -34,10 +35,12 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
} }
}; };
private Handler handler = new Handler(); private Handler handler = new Handler();
private boolean isCompat;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
isCompat = getIntent().getBooleanExtra("compat_list", false);
binding = ActivityBlackListBinding.inflate(getLayoutInflater()); binding = ActivityBlackListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot()); setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar); setSupportActionBar(binding.toolbar);
@ -47,10 +50,11 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
bar.setDisplayHomeAsUpEnabled(true); bar.setDisplayHomeAsUpEnabled(true);
} }
setupWindowInsets(binding.snackbar, binding.recyclerView); setupWindowInsets(binding.snackbar, binding.recyclerView);
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
final boolean isWhiteListMode = isWhiteListMode(); final boolean isWhiteListMode = isWhiteListMode();
appAdapter = new BlackListAdapter(this, isWhiteListMode, binding); appAdapter = isCompat ? new CompatListAdapter(this, binding) : new BlackListAdapter(this, isWhiteListMode, binding);
appAdapter.setHasStableIds(true);
binding.recyclerView.setAdapter(appAdapter); binding.recyclerView.setAdapter(appAdapter);
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
if (!XposedApp.getPreferences().getBoolean("md2", false)) { if (!XposedApp.getPreferences().getBoolean("md2", false)) {
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this,
DividerItemDecoration.VERTICAL); DividerItemDecoration.VERTICAL);
@ -60,7 +64,6 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
handler.postDelayed(runnable, 300); handler.postDelayed(runnable, 300);
binding.swipeRefreshLayout.setOnRefreshListener(appAdapter::refresh); binding.swipeRefreshLayout.setOnRefreshListener(appAdapter::refresh);
searchListener = new SearchView.OnQueryTextListener() { searchListener = new SearchView.OnQueryTextListener() {
@Override @Override
public boolean onQueryTextSubmit(String query) { public boolean onQueryTextSubmit(String query) {
@ -87,7 +90,7 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
if (!AppHelper.isBlackListMode()) { if (!isCompat && !AppHelper.isBlackListMode()) {
new MaterialAlertDialogBuilder(this) new MaterialAlertDialogBuilder(this)
.setMessage(R.string.warning_list_not_enabled) .setMessage(R.string.warning_list_not_enabled)
.setPositiveButton(R.string.Settings, (dialog, which) -> { .setPositiveButton(R.string.Settings, (dialog, which) -> {
@ -104,7 +107,9 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
private void changeTitle(boolean isBlackListMode, boolean isWhiteListMode) { private void changeTitle(boolean isBlackListMode, boolean isWhiteListMode) {
if (isBlackListMode) { if (isCompat) {
setTitle(R.string.nav_title_compat_list);
} else if (isBlackListMode) {
setTitle(isWhiteListMode ? R.string.title_white_list : R.string.title_black_list); setTitle(isWhiteListMode ? R.string.title_white_list : R.string.title_black_list);
} else { } else {
setTitle(R.string.nav_title_black_list); setTitle(R.string.nav_title_black_list);
@ -124,12 +129,16 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba
handler.removeCallbacks(runnable); handler.removeCallbacks(runnable);
binding.swipeRefreshLayout.setRefreshing(false); binding.swipeRefreshLayout.setRefreshing(false);
String queryStr = searchView != null ? searchView.getQuery().toString() : ""; String queryStr = searchView != null ? searchView.getQuery().toString() : "";
appAdapter.filter(queryStr); runOnUiThread(new Runnable() {
@Override
public void run() {
appAdapter.getFilter().filter(queryStr);
}
});
} }
@Override @Override
public void onItemClick(View v, ApplicationInfo info) { public void onItemClick(View v, ApplicationInfo info) {
getSupportFragmentManager();
AppHelper.showMenu(this, getSupportFragmentManager(), v, info); AppHelper.showMenu(this, getSupportFragmentManager(), v, info);
} }

View File

@ -1,102 +0,0 @@
package org.meowcat.edxposed.manager;
import android.content.pm.ApplicationInfo;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import org.meowcat.edxposed.manager.adapters.AppAdapter;
import org.meowcat.edxposed.manager.adapters.AppHelper;
import org.meowcat.edxposed.manager.adapters.CompatListAdapter;
import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding;
public class CompatListActivity extends BaseActivity implements AppAdapter.Callback {
private SearchView searchView;
private CompatListAdapter appAdapter;
private SearchView.OnQueryTextListener searchListener;
private ActivityBlackListBinding binding;
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityBlackListBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
setSupportActionBar(binding.toolbar);
binding.toolbar.setNavigationOnClickListener(view -> finish());
ActionBar bar = getSupportActionBar();
if (bar != null) {
bar.setDisplayHomeAsUpEnabled(true);
}
setupWindowInsets(binding.snackbar, binding.recyclerView);
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
appAdapter = new CompatListAdapter(this, binding);
binding.recyclerView.setAdapter(appAdapter);
if (!XposedApp.getPreferences().getBoolean("md2", false)) {
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this,
DividerItemDecoration.VERTICAL);
binding.recyclerView.addItemDecoration(dividerItemDecoration);
}
appAdapter.setCallback(this);
binding.swipeRefreshLayout.setRefreshing(true);
binding.swipeRefreshLayout.setOnRefreshListener(appAdapter::refresh);
searchListener = new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
appAdapter.filter(query);
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
appAdapter.filter(newText);
return false;
}
};
}
@Override
public boolean onCreateOptionsMenu(@NonNull Menu menu) {
getMenuInflater().inflate(R.menu.menu_app_list, menu);
searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView();
searchView.setOnQueryTextListener(searchListener);
return super.onCreateOptionsMenu(menu);
}
@Override
public void onDataReady() {
binding.swipeRefreshLayout.setRefreshing(false);
String queryStr = searchView != null ? searchView.getQuery().toString() : "";
appAdapter.filter(queryStr);
}
@Override
public void onItemClick(View v, ApplicationInfo info) {
AppHelper.showMenu(this, getSupportFragmentManager(), v, info);
}
@Override
public void onBackPressed() {
if (searchView.isIconified()) {
super.onBackPressed();
} else {
searchView.setIconified(true);
}
}
@Override
public void onPointerCaptureChanged(boolean hasCapture) {
}
}

View File

@ -196,6 +196,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
}).show(); }).show();
} }
adapter = new ModuleAdapter(); adapter = new ModuleAdapter();
adapter.setHasStableIds(true);
moduleUtil.addListener(this); moduleUtil.addListener(this);
binding.recyclerView.setAdapter(adapter); binding.recyclerView.setAdapter(adapter);
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this)); binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
@ -561,7 +562,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
boolean changed = moduleUtil.isModuleEnabled(packageName) ^ isChecked; boolean changed = moduleUtil.isModuleEnabled(packageName) ^ isChecked;
if (changed) { if (changed) {
moduleUtil.setModuleEnabled(packageName, isChecked); moduleUtil.setModuleEnabled(packageName, isChecked);
moduleUtil.updateModulesList(true); moduleUtil.updateModulesList(true, binding);
} }
}); });
mSwitch.setChecked(moduleUtil.isModuleEnabled(item.packageName)); mSwitch.setChecked(moduleUtil.isModuleEnabled(item.packageName));
@ -617,6 +618,11 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
} }
} }
@Override
public long getItemId(int position) {
return items.get(position).hashCode();
}
class ViewHolder extends RecyclerView.ViewHolder { class ViewHolder extends RecyclerView.ViewHolder {
ImageView appIcon; ImageView appIcon;
TextView appName; TextView appName;

View File

@ -415,7 +415,8 @@ public class SettingsActivity extends BaseActivity {
Activity activity = getActivity(); Activity activity = getActivity();
if (activity != null) { if (activity != null) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.setClass(activity, CompatListActivity.class); intent.putExtra("compat_list",true);
intent.setClass(activity, BlackListActivity.class);
activity.startActivity(intent); activity.startActivity(intent);
} }
return true; return true;

View File

@ -10,6 +10,7 @@ import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.CompoundButton; import android.widget.CompoundButton;
import android.widget.Filter; import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
@ -32,7 +33,7 @@ import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> { public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> implements Filterable {
protected final Context context; protected final Context context;
private final ApplicationInfo.DisplayNameComparator displayNameComparator; private final ApplicationInfo.DisplayNameComparator displayNameComparator;
@ -84,6 +85,7 @@ public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
AppHelper.makeSurePath(); AppHelper.makeSurePath();
checkedList = generateCheckedList(); checkedList = generateCheckedList();
sortApps(); sortApps();
showList = fullList;
if (callback != null) { if (callback != null) {
callback.onDataReady(); callback.onDataReady();
} }
@ -195,6 +197,16 @@ public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
}); });
} }
@Override
public long getItemId(int position) {
return showList.get(position).packageName.hashCode();
}
@Override
public Filter getFilter() {
return new ApplicationFilter();
}
@Override @Override
public int getItemCount() { public int getItemCount() {
return showList.size(); return showList.size();
@ -246,17 +258,18 @@ public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> {
@Override @Override
protected FilterResults performFiltering(CharSequence constraint) { protected FilterResults performFiltering(CharSequence constraint) {
if (constraint == null || constraint.length() == 0) { if (constraint.toString().isEmpty()) {
showList = fullList; showList = fullList;
} else { } else {
showList = new ArrayList<>(); ArrayList<ApplicationInfo> filtered = new ArrayList<>();
String filter = constraint.toString().toLowerCase(); String filter = constraint.toString().toLowerCase();
for (ApplicationInfo info : fullList) { for (ApplicationInfo info : fullList) {
if (lowercaseContains(InstallApkUtil.getAppLabel(info, pm), filter) if (lowercaseContains(InstallApkUtil.getAppLabel(info, pm), filter)
|| lowercaseContains(info.packageName, filter)) { || lowercaseContains(info.packageName, filter)) {
showList.add(info); filtered.add(info);
} }
} }
showList = filtered;
} }
return null; return null;
} }

View File

@ -16,8 +16,11 @@ import android.widget.Toast;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import com.google.android.material.snackbar.Snackbar;
import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.R;
import org.meowcat.edxposed.manager.XposedApp; import org.meowcat.edxposed.manager.XposedApp;
import org.meowcat.edxposed.manager.databinding.ActivityModulesBinding;
import org.meowcat.edxposed.manager.repo.ModuleVersion; import org.meowcat.edxposed.manager.repo.ModuleVersion;
import org.meowcat.edxposed.manager.repo.RepoDb; import org.meowcat.edxposed.manager.repo.RepoDb;
@ -207,11 +210,19 @@ public final class ModuleUtil {
} }
public synchronized void updateModulesList(boolean showToast) { public synchronized void updateModulesList(boolean showToast) {
updateModulesList(showToast, null);
}
public synchronized void updateModulesList(boolean showToast, ActivityModulesBinding binding) {
try { try {
Log.i(XposedApp.TAG, "ModuleUtil -> updating modules.list"); Log.i(XposedApp.TAG, "ModuleUtil -> updating modules.list");
int installedXposedVersion = XposedApp.getXposedVersion(); int installedXposedVersion = XposedApp.getXposedVersion();
if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && installedXposedVersion <= 0 && showToast) { if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && installedXposedVersion <= 0 && showToast) {
Toast.makeText(XposedApp.getInstance(), R.string.notinstalled, Toast.LENGTH_SHORT).show(); if (binding != null) {
Snackbar.make(binding.snackbar, R.string.notinstalled, Snackbar.LENGTH_SHORT).show();
} else {
showToast(R.string.notinstalled);
}
return; return;
} }
@ -221,7 +232,11 @@ public final class ModuleUtil {
for (InstalledModule module : enabledModules) { for (InstalledModule module : enabledModules) {
if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && (module.minVersion > installedXposedVersion || module.minVersion < MIN_MODULE_VERSION) && showToast) { if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && (module.minVersion > installedXposedVersion || module.minVersion < MIN_MODULE_VERSION) && showToast) {
Toast.makeText(XposedApp.getInstance(), R.string.notinstalled, Toast.LENGTH_SHORT).show(); if (binding != null) {
Snackbar.make(binding.snackbar, R.string.notinstalled, Snackbar.LENGTH_SHORT).show();
} else {
showToast(R.string.notinstalled);
}
continue; continue;
} }
@ -241,11 +256,19 @@ public final class ModuleUtil {
FileUtils.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 00664, -1, -1); FileUtils.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 00664, -1, -1);
if (showToast) { if (showToast) {
showToast(R.string.xposed_module_list_updated); if (binding != null) {
Snackbar.make(binding.snackbar, R.string.xposed_module_list_updated, Snackbar.LENGTH_SHORT).show();
} else {
showToast(R.string.xposed_module_list_updated);
}
} }
} catch (IOException e) { } catch (IOException e) {
Log.e(XposedApp.TAG, "ModuleUtil -> cannot write " + MODULES_LIST_FILE, e); Log.e(XposedApp.TAG, "ModuleUtil -> cannot write " + MODULES_LIST_FILE, e);
Toast.makeText(XposedApp.getInstance(), "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show(); if (binding != null) {
Snackbar.make(binding.snackbar, "cannot write " + MODULES_LIST_FILE + e, Snackbar.LENGTH_SHORT).show();
} else {
Toast.makeText(XposedApp.getInstance(), "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show();
}
} }
} }

View File

@ -7,7 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:4.0.0-beta02' classpath 'com.android.tools.build:gradle:4.0.0-beta03'
classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong