Use recyclerview for account/identity selection

pull/213/head
M66B 11 months ago
parent 4852aea444
commit 94aaa0c9fd

@ -23,17 +23,19 @@ import static android.app.Activity.RESULT_OK;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.Group;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
@ -44,36 +46,34 @@ public class FragmentDialogSelectAccount extends FragmentDialogBase {
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
final Context context = getContext();
final int dp6 = Helper.dp2pixels(context, 6);
final int dp12 = Helper.dp2pixels(context, 12);
final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_account_select, null);
RecyclerView rvSelect = dview.findViewById(R.id.rvSelect);
final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait);
final Group grpReady = dview.findViewById(R.id.grpReady);
final ArrayAdapter<EntityAccount> adapter = new ArrayAdapter<EntityAccount>(context, R.layout.spinner_account, android.R.id.text1) {
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = super.getView(position, convertView, parent);
try {
EntityAccount account = getItem(position);
View vwColor = view.findViewById(R.id.vwColor);
TextView tv = view.findViewById(android.R.id.text1);
rvSelect.setHasFixedSize(false);
rvSelect.setLayoutManager(new LinearLayoutManager(context));
int vpad = (getCount() > 10 ? dp6 : dp12);
tv.setPadding(0, vpad, 0, vpad);
Dialog dialog = new AlertDialog.Builder(context)
.setIcon(R.drawable.twotone_account_circle_24)
.setTitle(R.string.title_list_accounts)
.setView(dview)
.setNegativeButton(android.R.string.cancel, null)
.create();
vwColor.setBackgroundColor(account.color == null ? Color.TRANSPARENT : account.color);
tv.setText(account.name);
} catch (Throwable ex) {
Log.e(ex);
}
new SimpleTask<List<EntityAccount>>() {
@Override
protected void onPreExecute(Bundle args) {
pbWait.setVisibility(View.VISIBLE);
grpReady.setVisibility(View.GONE);
}
return view;
@Override
protected void onPostExecute(Bundle args) {
pbWait.setVisibility(View.GONE);
grpReady.setVisibility(View.VISIBLE);
}
};
// TODO: spinner
new SimpleTask<List<EntityAccount>>() {
@Override
protected List<EntityAccount> onExecute(Context context, Bundle args) {
boolean all = (args != null && args.getBoolean("all"));
@ -91,31 +91,114 @@ public class FragmentDialogSelectAccount extends FragmentDialogBase {
for (EntityAccount account : new ArrayList<>(accounts))
if (!account.isOutlook())
accounts.remove(account);
adapter.addAll(accounts);
}
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getParentFragmentManager(), ex);
}
}.execute(this, getArguments(), "select:account");
return new AlertDialog.Builder(context)
.setIcon(R.drawable.twotone_account_circle_24)
.setTitle(R.string.title_list_accounts)
.setAdapter(adapter, new DialogInterface.OnClickListener() {
AdapterAccount adapter = new AdapterAccount(context, accounts, new AdapterAccount.IListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
EntityAccount account = adapter.getItem(which);
public void onSelected(EntityAccount account) {
Bundle args = getArguments();
args.putLong("account", account.id);
args.putInt("protocol", account.protocol);
args.putString("name", account.name);
args.putString("user", account.user);
sendResult(RESULT_OK);
dialog.dismiss();
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
});
rvSelect.setAdapter(adapter);
}
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getParentFragmentManager(), ex);
}
}.execute(this, getArguments(), "select:account");
return dialog;
}
public static class AdapterAccount extends RecyclerView.Adapter<AdapterAccount.ViewHolder> {
private Context context;
private LayoutInflater inflater;
private int dp6;
private int dp12;
private List<EntityAccount> items;
private IListener listener;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private View vwColor;
private TextView tv;
ViewHolder(View itemView) {
super(itemView);
vwColor = itemView.findViewById(R.id.vwColor);
tv = itemView.findViewById(android.R.id.text1);
}
private void wire() {
itemView.setOnClickListener(this);
}
private void unwire() {
itemView.setOnClickListener(null);
}
private void bindTo(EntityAccount account) {
int vpad = (getItemCount() > 10 ? dp6 : dp12);
tv.setPadding(0, vpad, 0, vpad);
vwColor.setBackgroundColor(account.color == null ? Color.TRANSPARENT : account.color);
tv.setText(account.name);
}
@Override
public void onClick(View v) {
int pos = getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
return;
EntityAccount account = items.get(pos);
listener.onSelected(account);
}
}
AdapterAccount(Context context, List<EntityAccount> accounts, IListener listener) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.dp6 = Helper.dp2pixels(context, 6);
this.dp12 = Helper.dp2pixels(context, 12);
setHasStableIds(true);
this.items = accounts;
this.listener = listener;
}
@Override
public long getItemId(int position) {
return items.get(position).id;
}
@Override
public int getItemCount() {
return items.size();
}
@Override
@NonNull
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(inflater.inflate(R.layout.spinner_account, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.unwire();
EntityAccount account = items.get(position);
holder.bindTo(account);
holder.wire();
}
public interface IListener {
void onSelected(EntityAccount account);
}
}
}
}

@ -23,17 +23,19 @@ import static android.app.Activity.RESULT_OK;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.constraintlayout.widget.Group;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
@ -43,37 +45,34 @@ public class FragmentDialogSelectIdentity extends FragmentDialogBase {
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
final Context context = getContext();
final int dp6 = Helper.dp2pixels(context, 6);
final int dp12 = Helper.dp2pixels(context, 12);
final View dview = LayoutInflater.from(context).inflate(R.layout.dialog_account_select, null);
RecyclerView rvSelect = dview.findViewById(R.id.rvSelect);
final ContentLoadingProgressBar pbWait = dview.findViewById(R.id.pbWait);
final Group grpReady = dview.findViewById(R.id.grpReady);
final ArrayAdapter<TupleIdentityEx> adapter = new ArrayAdapter<TupleIdentityEx>(context, R.layout.spinner_account, android.R.id.text1) {
@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
View view = super.getView(position, convertView, parent);
try {
TupleIdentityEx identity = getItem(position);
View vwColor = view.findViewById(R.id.vwColor);
TextView tv = view.findViewById(android.R.id.text1);
rvSelect.setHasFixedSize(false);
rvSelect.setLayoutManager(new LinearLayoutManager(context));
int vpad = (getCount() > 10 ? dp6 : dp12);
tv.setPadding(0, vpad, 0, vpad);
Dialog dialog = new AlertDialog.Builder(context)
.setIcon(R.drawable.twotone_person_24)
.setTitle(R.string.title_list_identities)
.setView(dview)
.setNegativeButton(android.R.string.cancel, null)
.create();
Integer color = (identity.color == null ? identity.accountColor : identity.color);
vwColor.setBackgroundColor(color == null ? Color.TRANSPARENT : color);
tv.setText(identity.getDisplayName());
} catch (Throwable ex) {
Log.e(ex);
}
new SimpleTask<List<TupleIdentityEx>>() {
@Override
protected void onPreExecute(Bundle args) {
pbWait.setVisibility(View.VISIBLE);
grpReady.setVisibility(View.GONE);
}
return view;
@Override
protected void onPostExecute(Bundle args) {
pbWait.setVisibility(View.GONE);
grpReady.setVisibility(View.VISIBLE);
}
};
// TODO: spinner
new SimpleTask<List<TupleIdentityEx>>() {
@Override
protected List<TupleIdentityEx> onExecute(Context context, Bundle args) {
DB db = DB.getInstance(context);
@ -82,8 +81,17 @@ public class FragmentDialogSelectIdentity extends FragmentDialogBase {
@Override
protected void onExecuted(Bundle args, List<TupleIdentityEx> identities) {
EntityLog.log(context, "Composable identities=" + (identities == null ? null : identities.size()));
adapter.addAll(identities);
AdapterIdentity adapter = new AdapterIdentity(context, identities, new AdapterIdentity.IListener() {
@Override
public void onSelected(TupleIdentityEx identity) {
Bundle args = getArguments();
args.putLong("id", identity.id);
args.putString("html", identity.signature);
sendResult(RESULT_OK);
dialog.dismiss();
}
});
rvSelect.setAdapter(adapter);
}
@Override
@ -92,20 +100,93 @@ public class FragmentDialogSelectIdentity extends FragmentDialogBase {
}
}.execute(this, getArguments(), "select:identity");
return new AlertDialog.Builder(context)
.setIcon(R.drawable.twotone_person_24)
.setTitle(R.string.title_list_identities)
.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
TupleIdentityEx identity = adapter.getItem(which);
Bundle args = getArguments();
args.putLong("id", identity.id);
args.putString("html", identity.signature);
sendResult(RESULT_OK);
}
})
.setNegativeButton(android.R.string.cancel, null)
.create();
return dialog;
}
public static class AdapterIdentity extends RecyclerView.Adapter<AdapterIdentity.ViewHolder> {
private Context context;
private LayoutInflater inflater;
private int dp6;
private int dp12;
private List<TupleIdentityEx> items;
private IListener listener;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
private View vwColor;
private TextView tv;
ViewHolder(View itemView) {
super(itemView);
vwColor = itemView.findViewById(R.id.vwColor);
tv = itemView.findViewById(android.R.id.text1);
}
private void wire() {
itemView.setOnClickListener(this);
}
private void unwire() {
itemView.setOnClickListener(null);
}
private void bindTo(TupleIdentityEx identity) {
int vpad = (getItemCount() > 10 ? dp6 : dp12);
tv.setPadding(0, vpad, 0, vpad);
Integer color = (identity.color == null ? identity.accountColor : identity.color);
vwColor.setBackgroundColor(color == null ? Color.TRANSPARENT : color);
tv.setText(identity.getDisplayName());
}
@Override
public void onClick(View v) {
int pos = getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
return;
TupleIdentityEx identity = items.get(pos);
listener.onSelected(identity);
}
}
AdapterIdentity(Context context, List<TupleIdentityEx> identities, IListener listener) {
this.context = context;
this.inflater = LayoutInflater.from(context);
this.dp6 = Helper.dp2pixels(context, 6);
this.dp12 = Helper.dp2pixels(context, 12);
setHasStableIds(true);
this.items = identities;
this.listener = listener;
}
@Override
public long getItemId(int position) {
return items.get(position).id;
}
@Override
public int getItemCount() {
return items.size();
}
@Override
@NonNull
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
return new ViewHolder(inflater.inflate(R.layout.spinner_account, parent, false));
}
@Override
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
holder.unwire();
TupleIdentityEx identity = items.get(position);
holder.bindTo(identity);
holder.wire();
}
public interface IListener {
void onSelected(TupleIdentityEx identity);
}
}
}
}

@ -0,0 +1,46 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:descendantFocusability="beforeDescendants"
android:focusable="true"
android:focusableInTouchMode="true"
android:padding="12dp">
<eu.faircode.email.FixedRecyclerView
android:id="@+id/rvSelect"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:scrollbarStyle="outsideOverlay"
android:scrollbars="none"
app:fastScrollEnabled="false"
app:fastScrollHorizontalThumbDrawable="@drawable/scroll_thumb"
app:fastScrollHorizontalTrackDrawable="@drawable/scroll_track"
app:fastScrollVerticalThumbDrawable="@drawable/scroll_thumb"
app:fastScrollVerticalTrackDrawable="@drawable/scroll_track"
app:layout_constrainedHeight="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<eu.faircode.email.ContentLoadingProgressBar
android:id="@+id/pbWait"
style="@style/Base.Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:padding="24dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpReady"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="rvSelect" />
</androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save