Add master switch for scope list
This commit is contained in:
parent
ec08cc85e6
commit
840d54cccf
|
|
@ -16,14 +16,14 @@ 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.ScopeAdapter;
|
||||
import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding;
|
||||
import org.meowcat.edxposed.manager.databinding.ActivityScopeListBinding;
|
||||
|
||||
public class ModuleScopeActivity extends BaseActivity implements AppAdapter.Callback {
|
||||
private SearchView searchView;
|
||||
private AppAdapter appAdapter;
|
||||
private ScopeAdapter appAdapter;
|
||||
|
||||
private SearchView.OnQueryTextListener searchListener;
|
||||
private ActivityBlackListBinding binding;
|
||||
private ActivityScopeListBinding binding;
|
||||
private final Runnable runnable = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
|
@ -37,7 +37,7 @@ public class ModuleScopeActivity extends BaseActivity implements AppAdapter.Call
|
|||
super.onCreate(savedInstanceState);
|
||||
String modulePackageName = getIntent().getStringExtra("modulePackageName");
|
||||
String moduleName = getIntent().getStringExtra("moduleName");
|
||||
binding = ActivityBlackListBinding.inflate(getLayoutInflater());
|
||||
binding = ActivityScopeListBinding.inflate(getLayoutInflater());
|
||||
setContentView(binding.getRoot());
|
||||
setSupportActionBar(binding.toolbar);
|
||||
binding.toolbar.setNavigationOnClickListener(view -> finish());
|
||||
|
|
@ -47,7 +47,7 @@ public class ModuleScopeActivity extends BaseActivity implements AppAdapter.Call
|
|||
bar.setSubtitle(moduleName);
|
||||
}
|
||||
setupWindowInsets(binding.snackbar, binding.recyclerView);
|
||||
appAdapter = new ScopeAdapter(this, modulePackageName);
|
||||
appAdapter = new ScopeAdapter(this, modulePackageName, binding.masterSwitch);
|
||||
appAdapter.setHasStableIds(true);
|
||||
binding.recyclerView.setAdapter(appAdapter);
|
||||
binding.recyclerView.setLayoutManager(new LinearLayoutManager(this));
|
||||
|
|
|
|||
|
|
@ -205,6 +205,11 @@ public class AppAdapter extends RecyclerView.Adapter<AppAdapter.ViewHolder> impl
|
|||
|
||||
holder.mSwitch.setOnCheckedChangeListener(null);
|
||||
holder.mSwitch.setChecked(checkedList.contains(info.packageName));
|
||||
if (this instanceof ScopeAdapter) {
|
||||
holder.mSwitch.setEnabled(((ScopeAdapter) this).enabled);
|
||||
} else {
|
||||
holder.mSwitch.setEnabled(true);
|
||||
}
|
||||
holder.mSwitch.setOnCheckedChangeListener((v, isChecked) ->
|
||||
onCheckedChange(v, isChecked, info));
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
|
|
|
|||
|
|
@ -354,6 +354,7 @@ public class AppHelper {
|
|||
static boolean saveScopeList(String modulePackageName, List<String> list) {
|
||||
File file = new File(BASE_PATH + String.format(SCOPE_LIST_PATH, modulePackageName));
|
||||
if (list.size() == 0) {
|
||||
scopeList.put(modulePackageName, list);
|
||||
return file.delete();
|
||||
}
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -1,11 +1,13 @@
|
|||
package org.meowcat.edxposed.manager.adapters;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.widget.CompoundButton;
|
||||
|
||||
import org.meowcat.edxposed.manager.R;
|
||||
import org.meowcat.edxposed.manager.util.ToastUtil;
|
||||
import org.meowcat.edxposed.manager.widget.MasterSwitch;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
|
@ -13,11 +15,23 @@ import java.util.List;
|
|||
public class ScopeAdapter extends AppAdapter {
|
||||
|
||||
protected final String modulePackageName;
|
||||
protected boolean enabled = true;
|
||||
private List<String> checkedList;
|
||||
private final MasterSwitch masterSwitch;
|
||||
|
||||
public ScopeAdapter(Context context, String modulePackageName) {
|
||||
public ScopeAdapter(Context context, String modulePackageName, MasterSwitch masterSwitch) {
|
||||
super(context);
|
||||
this.modulePackageName = modulePackageName;
|
||||
this.masterSwitch = masterSwitch;
|
||||
masterSwitch.setTitle(context.getString(R.string.enable_scope));
|
||||
masterSwitch.setOnCheckedChangedListener(new MasterSwitch.OnCheckedChangeListener() {
|
||||
@Override
|
||||
public void onCheckedChanged(boolean checked) {
|
||||
enabled = checked;
|
||||
AppHelper.saveScopeList(modulePackageName, enabled ? checkedList : new ArrayList<>());
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -30,6 +44,8 @@ public class ScopeAdapter extends AppAdapter {
|
|||
}
|
||||
scopeList.retainAll(list);
|
||||
checkedList = scopeList;
|
||||
enabled = checkedList.size() != 0;
|
||||
((Activity) context).runOnUiThread(() -> masterSwitch.setChecked(enabled));
|
||||
return checkedList;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,112 @@
|
|||
package org.meowcat.edxposed.manager.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.graphics.drawable.StateListDrawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.widget.Checkable;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
|
||||
import org.meowcat.edxposed.manager.R;
|
||||
|
||||
public class MasterSwitch extends FrameLayout implements View.OnClickListener, Checkable {
|
||||
|
||||
private TextView masterTitle;
|
||||
private SwitchCompat switchCompat;
|
||||
|
||||
private String title;
|
||||
|
||||
private OnCheckedChangeListener listener;
|
||||
|
||||
private boolean isChecked;
|
||||
|
||||
public MasterSwitch(@NonNull Context context, @Nullable AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public MasterSwitch(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
public MasterSwitch(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
|
||||
super(context, attrs, defStyleAttr, defStyleRes);
|
||||
init(context, attrs);
|
||||
}
|
||||
|
||||
private void init(Context context, AttributeSet attrs) {
|
||||
LayoutInflater inflater = LayoutInflater.from(getContext());
|
||||
inflater.inflate(R.layout.master_switch, this, true);
|
||||
|
||||
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MasterSwitch);
|
||||
int colorOn = a.getColor(R.styleable.MasterSwitch_masterSwitchBackgroundOn, 0);
|
||||
int colorOff = a.getColor(R.styleable.MasterSwitch_masterSwitchBackgroundOff, 0);
|
||||
a.recycle();
|
||||
|
||||
StateListDrawable drawable = new StateListDrawable();
|
||||
drawable.addState(new int[]{android.R.attr.state_selected}, new ColorDrawable(colorOn));
|
||||
drawable.addState(new int[]{}, new ColorDrawable(colorOff));
|
||||
setBackground(drawable);
|
||||
|
||||
masterTitle = findViewById(android.R.id.title);
|
||||
switchCompat = findViewById(R.id.switchWidget);
|
||||
|
||||
setOnClickListener(this);
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
masterTitle.setText(title);
|
||||
}
|
||||
|
||||
private void updateViews() {
|
||||
if (switchCompat != null) {
|
||||
setSelected(isChecked);
|
||||
switchCompat.setChecked(isChecked);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChecked() {
|
||||
return isChecked;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toggle() {
|
||||
setChecked(!isChecked);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChecked(boolean checked) {
|
||||
final boolean changed = isChecked != checked;
|
||||
if (changed) {
|
||||
isChecked = checked;
|
||||
updateViews();
|
||||
if (listener != null) {
|
||||
listener.onCheckedChanged(checked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setOnCheckedChangedListener(OnCheckedChangeListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
public static abstract class OnCheckedChangeListener {
|
||||
public abstract void onCheckedChanged(boolean checked);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
toggle();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/snackbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false">
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior"
|
||||
android:orientation="vertical">
|
||||
|
||||
<com.google.android.material.appbar.AppBarLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:theme="?actionBarTheme"
|
||||
app:elevation="4dp">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="?attr/actionBarSize"
|
||||
android:background="?colorActionBar"
|
||||
app:popupTheme="?actionBarPopupTheme" />
|
||||
|
||||
</com.google.android.material.appbar.AppBarLayout>
|
||||
|
||||
<org.meowcat.edxposed.manager.widget.MasterSwitch
|
||||
android:id="@+id/master_switch"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_width="match_parent"
|
||||
android:theme="@style/MasterSwitch"
|
||||
android:foreground="?selectableItemBackground" />
|
||||
|
||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||
android:id="@+id/swipeRefreshLayout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false"
|
||||
android:orientation="vertical"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/recyclerView"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:clipToPadding="false" />
|
||||
|
||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<merge xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/master_switch_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:baselineAligned="false"
|
||||
android:clipToPadding="false"
|
||||
android:gravity="center_vertical"
|
||||
android:minHeight="?android:attr/listPreferredItemHeightSmall"
|
||||
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
|
||||
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
|
||||
|
||||
<RelativeLayout
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
android:id="@android:id/title"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?masterSwitchTextAppearance" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@android:id/widget_frame"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="match_parent"
|
||||
android:gravity="end|center_vertical"
|
||||
android:orientation="vertical"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="0dp">
|
||||
|
||||
<androidx.appcompat.widget.SwitchCompat
|
||||
android:id="@+id/switchWidget"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:clickable="false"
|
||||
android:focusable="false" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</merge>
|
||||
|
|
@ -311,4 +311,5 @@
|
|||
<string name="settings_title_disable_hidden_api_bypass">禁用绕过隐藏 API 的限制</string>
|
||||
<string name="settings_summary_disable_hidden_api_bypass">禁用绕过隐藏 API 的限制将会通过某些检测(如Snapchat)\n<b>警告:</b> 启用此选项可能会使某些功能无法正常工作,或出现一些其他问题</string>
|
||||
<string name="menu_scope">作用域</string>
|
||||
<string name="enable_scope">启用作用域</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -9,4 +9,11 @@
|
|||
<attr name="downloadVerticalPadding" format="dimension" />
|
||||
<attr name="actionBarPopupTheme" format="reference" />
|
||||
<attr name="tabLayoutTheme" format="reference" />
|
||||
|
||||
<declare-styleable name="MasterSwitch">
|
||||
<attr name="masterSwitchTextAppearance" format="reference" />
|
||||
<attr name="masterSwitchBackgroundOn" format="color" />
|
||||
<attr name="masterSwitchBackgroundOff" format="color" />
|
||||
<attr name="masterSwitchForeground" format="color" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
|
|
@ -342,4 +342,5 @@
|
|||
<string name="settings_title_disable_hidden_api_bypass">Disable hidden API restrictions bypass</string>
|
||||
<string name="settings_summary_disable_hidden_api_bypass">Disable hidden API restrictions bypass will pass some detection (eg Snapchat), these APIs are disabled by default\n<b>WARNING:</b> Enable this option may cause some features do not work properly, or some other problems</string>
|
||||
<string name="menu_scope">Scope</string>
|
||||
<string name="enable_scope">Enable scope</string>
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -33,6 +33,24 @@
|
|||
|
||||
<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.MaterialComponents.Light" />
|
||||
|
||||
<style name="MasterSwitch">
|
||||
<item name="masterSwitchBackgroundOff">#80868b</item>
|
||||
<item name="masterSwitchBackgroundOn">?colorAccent</item>
|
||||
<item name="masterSwitchTextAppearance">@style/MasterSwitch.TextAppearance</item>
|
||||
<item name="switchStyle">@style/MasterSwitch.Switch</item>
|
||||
<item name="android:theme">@style/ThemeOverlay.AppCompat.Dark</item>
|
||||
</style>
|
||||
|
||||
<style name="MasterSwitch.Switch" parent="@style/Widget.AppCompat.CompoundButton.Switch">
|
||||
<item name="trackTint">#33ffffff</item>
|
||||
<item name="thumbTint">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="MasterSwitch.TextAppearance" parent="@style/TextAppearance.AppCompat.Body2">
|
||||
<item name="android:textSize">18sp</item>
|
||||
<item name="android:textColor">@android:color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="ThemeOverlay" />
|
||||
|
||||
<style name="ThemeOverlay.Md2">
|
||||
|
|
|
|||
Loading…
Reference in New Issue