refactor: add abstract settingsbase fragment

This commit is contained in:
FineFindus 2023-04-21 21:17:20 +02:00
parent fd21b9e568
commit f2c13ed379
No known key found for this signature in database
GPG Key ID: 64873EE210FF8E6B
1 changed files with 415 additions and 0 deletions

View File

@ -0,0 +1,415 @@
package org.joinmastodon.android.fragments.settings;
import android.annotation.SuppressLint;
import android.graphics.Rect;
import android.os.Build;
import android.os.Bundle;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowInsets;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.Switch;
import android.widget.TextView;
import androidx.annotation.DrawableRes;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import org.joinmastodon.android.DomainManager;
import org.joinmastodon.android.R;
import org.joinmastodon.android.api.session.AccountSession;
import org.joinmastodon.android.api.session.AccountSessionManager;
import org.joinmastodon.android.fragments.DomainDisplay;
import org.joinmastodon.android.fragments.MastodonToolbarFragment;
import org.joinmastodon.android.ui.utils.UiUtils;
import java.util.ArrayList;
import java.util.function.Consumer;
import me.grishka.appkit.utils.BindableViewHolder;
import me.grishka.appkit.utils.V;
import me.grishka.appkit.views.UsableRecyclerView;
public abstract class SettingsBaseFragment extends MastodonToolbarFragment implements DomainDisplay {
protected View view;
private UsableRecyclerView list;
private ArrayList<Item> items=new ArrayList<>();
private String accountID;
public abstract void addItems(ArrayList<Item> items);
@Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.N)
setRetainInstance(true);
setTitle(R.string.settings);
accountID=getArguments().getString("account");
AccountSession session = AccountSessionManager.getInstance().getAccount(accountID);
DomainManager.getInstance().setCurrentDomain(session.domain + "/settings");
addItems(items);
}
@Override
public View onCreateContentView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
list=new UsableRecyclerView(getActivity());
list.setLayoutManager(new LinearLayoutManager(getActivity()));
list.setAdapter(new SettingsAdapter());
list.setBackgroundColor(UiUtils.getThemeColor(getActivity(), android.R.attr.colorBackground));
list.setPadding(0, V.dp(16), 0, V.dp(12));
list.setClipToPadding(false);
list.addItemDecoration(new RecyclerView.ItemDecoration(){
@Override
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state){
// Add 32dp gaps between sections
RecyclerView.ViewHolder holder=parent.getChildViewHolder(view);
if((holder instanceof HeaderViewHolder || holder instanceof FooterViewHolder) && holder.getAbsoluteAdapterPosition()>1)
outRect.top=V.dp(32);
}
});
return list;
}
@Override
public void onApplyWindowInsets(WindowInsets insets){
if(Build.VERSION.SDK_INT>=29 && insets.getTappableElementInsets().bottom==0){
list.setPadding(0, V.dp(16), 0, V.dp(12)+insets.getSystemWindowInsetBottom());
insets=insets.inset(0, 0, 0, insets.getSystemWindowInsetBottom());
}
super.onApplyWindowInsets(insets);
}
@Override
public void onViewCreated(View view, Bundle savedInstanceState){
super.onViewCreated(view, savedInstanceState);
this.view = view;
}
private static abstract class Item{
public abstract int getViewType();
}
private class HeaderItem extends Item{
private String text;
public HeaderItem(@StringRes int text){
this.text=getString(text);
}
public HeaderItem(String text){
this.text=text;
}
@Override
public int getViewType(){
return Type.HEADER.ordinal();
}
}
private class SwitchItem extends Item{
private String text;
private int icon;
private boolean checked;
private Consumer<SwitchItem> onChanged;
private boolean enabled=true;
public SwitchItem(@StringRes int text, @DrawableRes int icon, boolean checked, Consumer<SwitchItem> onChanged){
this.text=getString(text);
this.icon=icon;
this.checked=checked;
this.onChanged=onChanged;
}
public SwitchItem(@StringRes int text, @DrawableRes int icon, boolean checked, Consumer<SwitchItem> onChanged, boolean enabled){
this.text=getString(text);
this.icon=icon;
this.checked=checked;
this.onChanged=onChanged;
this.enabled=enabled;
}
@Override
public int getViewType(){
return Type.SWITCH.ordinal();
}
}
public class ButtonItem extends Item{
private int text;
private int icon;
private Consumer<Button> buttonConsumer;
public ButtonItem(@StringRes int text, @DrawableRes int icon, Consumer<Button> buttonConsumer) {
this.text = text;
this.icon = icon;
this.buttonConsumer = buttonConsumer;
}
@Override
public int getViewType(){
return Type.BUTTON.ordinal();
}
}
private class SmallTextItem extends Item {
private String text;
public SmallTextItem(String text) {
this.text = text;
}
@Override
public int getViewType() {
return Type.SMALL_TEXT.ordinal();
}
}
private class TextItem extends Item{
private String text;
private String secondaryText;
private Runnable onClick;
private boolean loading;
private int icon;
public TextItem(@StringRes int text, Runnable onClick) {
this(text, null, onClick, false, 0);
}
public TextItem(@StringRes int text, Runnable onClick, @DrawableRes int icon) {
this(text, null, onClick, false, icon);
}
public TextItem(@StringRes int text, String secondaryText, Runnable onClick, @DrawableRes int icon) {
this(text, secondaryText, onClick, false, icon);
}
public TextItem(@StringRes int text, String secondaryText, Runnable onClick, boolean loading, @DrawableRes int icon){
this.text=getString(text);
this.onClick=onClick;
this.loading=loading;
this.icon=icon;
this.secondaryText = secondaryText;
}
public TextItem(String text, Runnable onClick){
this.text=text;
this.onClick=onClick;
}
public TextItem(String text, Runnable onClick, @DrawableRes int icon){
this.text=text;
this.onClick=onClick;
this.icon=icon;
}
@Override
public int getViewType(){
return Type.TEXT.ordinal();
}
}
private class FooterItem extends Item{
private String text;
private Runnable onClick;
public FooterItem(String text, Runnable onClick){
this.text=text;
this.onClick=onClick;
}
@Override
public int getViewType(){
return Type.FOOTER.ordinal();
}
}
public enum Type{
HEADER,
SWITCH,
TEXT,
FOOTER,
BUTTON,
SMALL_TEXT,
}
private class SettingsAdapter extends RecyclerView.Adapter<BindableViewHolder<Item>>{
@NonNull
@Override
public BindableViewHolder<Item> onCreateViewHolder(@NonNull ViewGroup parent, int viewType){
//noinspection unchecked
return (BindableViewHolder<Item>) switch(Type.values()[viewType]){
case HEADER -> new HeaderViewHolder();
case SWITCH -> new SwitchViewHolder();
case TEXT -> new TextViewHolder();
case FOOTER -> new FooterViewHolder();
case BUTTON -> new ButtonViewHolder();
case SMALL_TEXT -> new SmallTextViewHolder();
};
}
@Override
public void onBindViewHolder(@NonNull BindableViewHolder<Item> holder, int position){
holder.bind(items.get(position));
}
@Override
public int getItemCount(){
return items.size();
}
@Override
public int getItemViewType(int position){
return items.get(position).getViewType();
}
}
private class HeaderViewHolder extends BindableViewHolder<HeaderItem>{
private final TextView text;
public HeaderViewHolder(){
super(getActivity(), R.layout.item_settings_header, list);
text=(TextView) itemView;
}
@Override
public void onBind(HeaderItem item){
text.setText(item.text);
}
}
private class SwitchViewHolder extends BindableViewHolder<SwitchItem> implements UsableRecyclerView.DisableableClickable{
private final TextView text;
private final ImageView icon;
private final Switch checkbox;
public SwitchViewHolder(){
super(getActivity(), R.layout.item_settings_switch, list);
text=findViewById(R.id.text);
icon=findViewById(R.id.icon);
checkbox=findViewById(R.id.checkbox);
}
@Override
public void onBind(SwitchItem item){
text.setText(item.text);
if (item.icon == 0) {
icon.setVisibility(View.GONE);
} else {
icon.setVisibility(View.VISIBLE);
icon.setImageResource(item.icon);
}
checkbox.setChecked(item.checked && item.enabled);
checkbox.setEnabled(item.enabled);
}
@Override
public void onClick(){
item.checked=!item.checked;
checkbox.setChecked(item.checked);
item.onChanged.accept(item);
}
@Override
public boolean isEnabled(){
return item.enabled;
}
}
private class ButtonViewHolder extends BindableViewHolder<ButtonItem>{
private final Button button;
private final ImageView icon;
private final TextView text;
@SuppressLint("ClickableViewAccessibility")
public ButtonViewHolder(){
super(getActivity(), R.layout.item_settings_button, list);
text=findViewById(R.id.text);
icon=findViewById(R.id.icon);
button=findViewById(R.id.button);
}
@Override
public void onBind(ButtonItem item){
text.setText(item.text);
icon.setImageResource(item.icon);
item.buttonConsumer.accept(button);
}
}
private class TextViewHolder extends BindableViewHolder<TextItem> implements UsableRecyclerView.Clickable{
private final TextView text, secondaryText;
private final ProgressBar progress;
private final ImageView icon;
public TextViewHolder(){
super(getActivity(), R.layout.item_settings_text, list);
text = itemView.findViewById(R.id.text);
secondaryText = itemView.findViewById(R.id.secondary_text);
progress = itemView.findViewById(R.id.progress);
icon = itemView.findViewById(R.id.icon);
}
@Override
public void onBind(TextItem item){
icon.setVisibility(item.icon != 0 ? View.VISIBLE : View.GONE);
secondaryText.setVisibility(item.secondaryText != null ? View.VISIBLE : View.GONE);
text.setText(item.text);
progress.animate().alpha(item.loading ? 1 : 0);
icon.setImageResource(item.icon);
secondaryText.setText(item.secondaryText);
}
@Override
public void onClick(){
item.onClick.run();
}
}
private class SmallTextViewHolder extends BindableViewHolder<SmallTextItem> {
private final TextView text;
public SmallTextViewHolder(){
super(getActivity(), R.layout.item_settings_text, list);
text = itemView.findViewById(R.id.text);
text.setTextColor(UiUtils.getThemeColor(getActivity(), android.R.attr.textColorSecondary));
text.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
text.setTextSize(TypedValue.COMPLEX_UNIT_SP, 14);
text.setPaddingRelative(text.getPaddingStart(), 0, text.getPaddingEnd(), text.getPaddingBottom());
}
@Override
public void onBind(SmallTextItem item){
text.setText(item.text);
}
}
private class FooterViewHolder extends BindableViewHolder<FooterItem> implements UsableRecyclerView.Clickable{
private final TextView text;
public FooterViewHolder(){
super(getActivity(), R.layout.item_settings_footer, list);
text=(TextView) itemView;
}
@Override
public void onBind(FooterItem item){
text.setText(item.text);
}
@Override
public void onClick(){
item.onClick.run();
}
}
}