diff options
5 files changed, 80 insertions, 27 deletions
diff --git a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java index f8b03b25..f9634eba 100644 --- a/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java +++ b/app/src/main/java/com/wireguard/android/fragment/TunnelListFragment.java @@ -41,6 +41,7 @@ import com.wireguard.android.model.Tunnel; import com.wireguard.android.util.ExceptionLoggers; import com.wireguard.android.util.ObservableSortedKeyedList; import com.wireguard.android.widget.MonkeyedSnackbar; +import com.wireguard.android.widget.MultiselectableRelativeLayout; import com.wireguard.android.widget.fab.FloatingActionsMenuRecyclerViewScrollListener; import com.wireguard.config.Config; @@ -263,30 +264,20 @@ public class TunnelListFragment extends BaseFragment { super.onPause(); } + private MultiselectableRelativeLayout viewForTunnel(final Tunnel tunnel, final List tunnels) { + return (MultiselectableRelativeLayout)binding.tunnelList.findViewHolderForAdapterPosition(tunnels.indexOf(tunnel)).itemView; + } + @Override public void onSelectedTunnelChanged(@Nullable final Tunnel oldTunnel, @Nullable final Tunnel newTunnel) { if (binding == null) return; Application.getTunnelManager().getTunnels().thenAccept(tunnels -> { if (newTunnel != null) - binding.tunnelList.findViewHolderForAdapterPosition(tunnels.indexOf(newTunnel)).itemView.setActivated(true); + viewForTunnel(newTunnel, tunnels).setSingleSelected(true); if (oldTunnel != null) - binding.tunnelList.findViewHolderForAdapterPosition(tunnels.indexOf(oldTunnel)).itemView.setActivated(false); - + viewForTunnel(oldTunnel, tunnels).setSingleSelected(false); }); - - /* Alternative 1: results in sluggish change: - - if (binding.tunnelList.getAdapter() == null) - return; - - - * Alternative 2: results in overly quick change: - - binding.tunnelList.getAdapter().notifyDataSetChanged(); - - * Hence, we go with the above. - */ } private void onTunnelDeletionFinished(final Integer count, @Nullable final Throwable throwable) { @@ -373,10 +364,9 @@ public class TunnelListFragment extends BaseFragment { }); if (actionMode != null) - binding.getRoot().setActivated(actionModeListener.checkedItems.contains(position)); + ((MultiselectableRelativeLayout)binding.getRoot()).setMultiSelected(actionModeListener.checkedItems.contains(position)); else - binding.getRoot().setActivated(getSelectedTunnel() == tunnel); - + ((MultiselectableRelativeLayout)binding.getRoot()).setSingleSelected(getSelectedTunnel() == tunnel); }); } @@ -433,7 +423,6 @@ public class TunnelListFragment extends BaseFragment { public void onDestroyActionMode(final ActionMode mode) { actionMode = null; resources = null; - checkedItems.clear(); binding.tunnelList.getAdapter().notifyDataSetChanged(); } diff --git a/app/src/main/java/com/wireguard/android/widget/MultiselectableRelativeLayout.java b/app/src/main/java/com/wireguard/android/widget/MultiselectableRelativeLayout.java new file mode 100644 index 00000000..c64dc320 --- /dev/null +++ b/app/src/main/java/com/wireguard/android/widget/MultiselectableRelativeLayout.java @@ -0,0 +1,57 @@ +/* + * Copyright © 2018 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +package com.wireguard.android.widget; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +import com.wireguard.android.R; + +public class MultiselectableRelativeLayout extends RelativeLayout { + public MultiselectableRelativeLayout(final Context context) { + super(context); + } + public MultiselectableRelativeLayout(final Context context, final AttributeSet attrs) { + super(context, attrs); + } + public MultiselectableRelativeLayout(final Context context, final AttributeSet attrs, final int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + public MultiselectableRelativeLayout(final Context context, final AttributeSet attrs, final int defStyleAttr, final int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + private static final int[] STATE_MULTISELECTED = { R.attr.state_multiselected }; + + private boolean multiselected; + + @Override + protected int[] onCreateDrawableState(final int extraSpace) { + if (multiselected) { + final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); + mergeDrawableStates(drawableState, STATE_MULTISELECTED); + return drawableState; + } + return super.onCreateDrawableState(extraSpace); + } + + public void setMultiSelected(final boolean on) { + if (!multiselected) { + multiselected = true; + refreshDrawableState(); + } + setActivated(on); + } + + public void setSingleSelected(final boolean on) { + if (multiselected) { + multiselected = false; + refreshDrawableState(); + } + setActivated(on); + } +} diff --git a/app/src/main/res/drawable/list_item_background.xml b/app/src/main/res/drawable/list_item_background.xml index f064676a..d62f3237 100644 --- a/app/src/main/res/drawable/list_item_background.xml +++ b/app/src/main/res/drawable/list_item_background.xml @@ -1,12 +1,13 @@ <?xml version="1.0" encoding="utf-8"?> -<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> +<layer-list xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto"> <item> <selector> - <item android:state_activated="true"> + <item app:state_multiselected="true" android:state_activated="true"> + <color android:color="?android:attr/colorControlActivated" /> + </item> + <item app:state_multiselected="false" android:state_activated="true"> <color android:color="?android:attr/colorControlHighlight" /> - <!-- TODO(msf): depending on whether or not we are in multiselect mode, choose instead: - <color android:color="?android:attr/colorControlActivated" /> - --> </item> </selector> </item> diff --git a/app/src/main/res/layout/tunnel_list_item.xml b/app/src/main/res/layout/tunnel_list_item.xml index ba36fe65..cf25b83e 100644 --- a/app/src/main/res/layout/tunnel_list_item.xml +++ b/app/src/main/res/layout/tunnel_list_item.xml @@ -25,7 +25,7 @@ type="com.wireguard.android.fragment.TunnelListFragment" /> </data> - <RelativeLayout + <com.wireguard.android.widget.MultiselectableRelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/list_item_background" @@ -51,5 +51,5 @@ android:layout_alignParentEnd="true" app:checked="@{item.state == State.UP}" app:onBeforeCheckedChanged="@{fragment::setTunnelState}" /> - </RelativeLayout> + </com.wireguard.android.widget.MultiselectableRelativeLayout> </layout> diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml new file mode 100644 index 00000000..85a987f9 --- /dev/null +++ b/app/src/main/res/values/attrs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<resources> + <declare-styleable name="Multiselected"> + <attr name="state_multiselected" format="boolean"/> + </declare-styleable> +</resources>
\ No newline at end of file |