Enable action mode on card long press

This will allow to perform different operations, although currently
it's only used to delete updates.
This commit is contained in:
Gabriele M
2017-07-19 21:11:46 +02:00
parent ebe0bb2e42
commit 257ab087d6
7 changed files with 136 additions and 15 deletions

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/background_selected" android:state_selected="true" />
<item android:drawable="@color/cardview_light_background" android:state_selected="false" />
</selector>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/menu_delete_action"
android:icon="@drawable/ic_delete"
android:title="@string/menu_delete_update"
android:visible="false"
app:showAsAction="ifRoom" />
</menu>

View File

@@ -4,5 +4,7 @@
<color name="theme_primary_dark">#ff000000</color>
<color name="theme_accent">#ff009688</color>
<color name="background_selected">#ffdddddd</color>
<color name="white">#f5f5f5</color>
</resources>

View File

@@ -49,6 +49,7 @@
<string name="menu_refresh">Refresh</string>
<string name="menu_auto_updates_check">Auto updates check</string>
<string name="menu_delete_update">Delete</string>
<string name="dialog_checking_for_updates">Checking for updates</string>
<string name="snack_updates_found">New updates found</string>

View File

@@ -4,6 +4,7 @@
<item name="colorPrimary">@color/theme_primary</item>
<item name="colorPrimaryDark">@color/theme_primary_dark</item>
<item name="colorAccent">@color/theme_accent</item>
<item name="windowActionModeOverlay">true</item>
</style>
<style name="AppTheme.NoActionBar">

View File

@@ -18,11 +18,15 @@ package org.lineageos.updater;
import android.content.DialogInterface;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.support.v7.view.ActionMode;
import android.support.v7.widget.RecyclerView;
import android.text.format.Formatter;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageButton;
@@ -48,8 +52,10 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
private final float mAlphaDisabledValue;
private List<String> mDownloadIds;
private String mSelectedDownload;
private Controller mUpdaterController;
private UpdatesListActivity mActivity;
private ActionMode mActionMode;
private enum Action {
DOWNLOAD,
@@ -99,6 +105,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.update_item_view, viewGroup, false);
view.setBackground(mActivity.getDrawable(R.drawable.list_item_background));
return new ViewHolder(view);
}
@@ -157,8 +164,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
viewHolder.mProgressBar.setProgress(update.getProgress());
}
viewHolder.itemView.setOnLongClickListener(
canDelete ? getDeleteClickListener(update.getDownloadId()) : null);
viewHolder.itemView.setOnLongClickListener(getLongClickListener(update, canDelete));
}
private void handleNotActiveStatus(ViewHolder viewHolder, UpdateDownload update) {
@@ -170,11 +176,10 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
viewHolder.mBuildVersion.setText(buildVersion);
if (update.getPersistentStatus() == UpdateStatus.Persistent.VERIFIED) {
viewHolder.itemView.setOnLongClickListener(
getDeleteClickListener(update.getDownloadId()));
viewHolder.itemView.setOnLongClickListener(getLongClickListener(update, true));
setButtonAction(viewHolder.mAction, Action.INSTALL, update.getDownloadId(), !isBusy());
} else {
viewHolder.itemView.setOnLongClickListener(null);
viewHolder.itemView.setOnLongClickListener(getLongClickListener(update, false));
setButtonAction(viewHolder.mAction, Action.DOWNLOAD, update.getDownloadId(), !isBusy());
}
}
@@ -195,6 +200,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
return;
}
viewHolder.itemView.setSelected(downloadId.equals(mSelectedDownload));
boolean activeLayout;
switch (update.getPersistentStatus()) {
case UpdateStatus.Persistent.UNKNOWN:
@@ -243,30 +250,31 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
private void setButtonAction(ImageButton button, Action action, final String downloadId,
boolean enabled) {
final View.OnClickListener clickListener;
switch (action) {
case DOWNLOAD:
button.setImageResource(R.drawable.ic_download);
button.setContentDescription(
mActivity.getString(R.string.action_description_download));
button.setEnabled(enabled);
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
clickListener = !enabled ? null : new View.OnClickListener() {
@Override
public void onClick(View view) {
mUpdaterController.startDownload(downloadId);
}
});
};
break;
case PAUSE:
button.setImageResource(R.drawable.ic_pause);
button.setContentDescription(
mActivity.getString(R.string.action_description_pause));
button.setEnabled(enabled);
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
clickListener = !enabled ? null : new View.OnClickListener() {
@Override
public void onClick(View view) {
mUpdaterController.pauseDownload(downloadId);
}
});
};
break;
case RESUME: {
button.setImageResource(R.drawable.ic_resume);
@@ -275,7 +283,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
button.setEnabled(enabled);
UpdateDownload update = mUpdaterController.getUpdate(downloadId);
final boolean canInstall = Utils.canInstall(update);
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
clickListener = !enabled ? null : new View.OnClickListener() {
@Override
public void onClick(View view) {
if (canInstall) {
@@ -285,7 +293,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
Snackbar.LENGTH_LONG);
}
}
});
};
}
break;
case INSTALL: {
@@ -295,7 +303,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
button.setEnabled(enabled);
UpdateDownload update = mUpdaterController.getUpdate(downloadId);
final boolean canInstall = Utils.canInstall(update);
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
clickListener = !enabled ? null : new View.OnClickListener() {
@Override
public void onClick(View view) {
if (canInstall) {
@@ -305,11 +313,24 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
Snackbar.LENGTH_LONG);
}
}
});
};
}
break;
default:
clickListener = null;
}
button.setAlpha(enabled ? 1.f : mAlphaDisabledValue);
// Disable action mode when a button is clicked
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (clickListener != null) {
clickListener.onClick(v);
stopActionMode();
}
}
});
}
private boolean isBusy() {
@@ -331,11 +352,14 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
.setNegativeButton(android.R.string.cancel, null);
}
private View.OnLongClickListener getDeleteClickListener(final String downloadId) {
private View.OnLongClickListener getLongClickListener(final UpdateDownload update,
final boolean canDelete) {
return new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
getDeleteDialog(downloadId).show();
if (mActionMode == null) {
startActionMode(update, canDelete);
}
return true;
}
};
@@ -372,4 +396,73 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
})
.setNegativeButton(android.R.string.cancel, null);
}
private void stopActionMode() {
if (mActionMode != null) {
mActionMode.finish();
}
}
private void startActionMode(final UpdateDownload update, final boolean canDelete) {
if (mActionMode != null) {
Log.d(TAG, "Action mode already enabled");
return;
}
mSelectedDownload = update.getDownloadId();
notifyItemChanged(update.getDownloadId());
// Hide Action Bar not to steal the focus when using a D-pad
final boolean showActionBar;
if (mActivity.getSupportActionBar() != null &&
mActivity.getSupportActionBar().isShowing()) {
showActionBar = true;
mActivity.getSupportActionBar().hide();
} else {
showActionBar = false;
}
mActionMode = mActivity.startSupportActionMode(new ActionMode.Callback() {
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
MenuInflater inflater = mode.getMenuInflater();
inflater.inflate(R.menu.menu_action_mode, menu);
menu.findItem(R.id.menu_delete_action).setVisible(canDelete);
return true;
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_delete_action:
getDeleteDialog(update.getDownloadId())
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mode.finish();
}
})
.show();
return true;
}
return false;
}
@Override
public void onDestroyActionMode(ActionMode mode) {
mSelectedDownload = null;
mActionMode = null;
notifyItemChanged(update.getDownloadId());
if (showActionBar) {
mActivity.getSupportActionBar().show();
}
}
});
}
}