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:
9
res/drawable/ic_delete.xml
Normal file
9
res/drawable/ic_delete.xml
Normal 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>
|
||||||
5
res/drawable/list_item_background.xml
Normal file
5
res/drawable/list_item_background.xml
Normal 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>
|
||||||
10
res/menu/menu_action_mode.xml
Normal file
10
res/menu/menu_action_mode.xml
Normal 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>
|
||||||
@@ -4,5 +4,7 @@
|
|||||||
<color name="theme_primary_dark">#ff000000</color>
|
<color name="theme_primary_dark">#ff000000</color>
|
||||||
<color name="theme_accent">#ff009688</color>
|
<color name="theme_accent">#ff009688</color>
|
||||||
|
|
||||||
|
<color name="background_selected">#ffdddddd</color>
|
||||||
|
|
||||||
<color name="white">#f5f5f5</color>
|
<color name="white">#f5f5f5</color>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
<string name="menu_refresh">Refresh</string>
|
<string name="menu_refresh">Refresh</string>
|
||||||
<string name="menu_auto_updates_check">Auto updates check</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="dialog_checking_for_updates">Checking for updates</string>
|
||||||
<string name="snack_updates_found">New updates found</string>
|
<string name="snack_updates_found">New updates found</string>
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
<item name="colorPrimary">@color/theme_primary</item>
|
<item name="colorPrimary">@color/theme_primary</item>
|
||||||
<item name="colorPrimaryDark">@color/theme_primary_dark</item>
|
<item name="colorPrimaryDark">@color/theme_primary_dark</item>
|
||||||
<item name="colorAccent">@color/theme_accent</item>
|
<item name="colorAccent">@color/theme_accent</item>
|
||||||
|
<item name="windowActionModeOverlay">true</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style name="AppTheme.NoActionBar">
|
<style name="AppTheme.NoActionBar">
|
||||||
|
|||||||
@@ -18,11 +18,15 @@ package org.lineageos.updater;
|
|||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
import android.support.design.widget.Snackbar;
|
import android.support.design.widget.Snackbar;
|
||||||
import android.support.v7.app.AlertDialog;
|
import android.support.v7.app.AlertDialog;
|
||||||
|
import android.support.v7.view.ActionMode;
|
||||||
import android.support.v7.widget.RecyclerView;
|
import android.support.v7.widget.RecyclerView;
|
||||||
import android.text.format.Formatter;
|
import android.text.format.Formatter;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
@@ -48,8 +52,10 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
private final float mAlphaDisabledValue;
|
private final float mAlphaDisabledValue;
|
||||||
|
|
||||||
private List<String> mDownloadIds;
|
private List<String> mDownloadIds;
|
||||||
|
private String mSelectedDownload;
|
||||||
private Controller mUpdaterController;
|
private Controller mUpdaterController;
|
||||||
private UpdatesListActivity mActivity;
|
private UpdatesListActivity mActivity;
|
||||||
|
private ActionMode mActionMode;
|
||||||
|
|
||||||
private enum Action {
|
private enum Action {
|
||||||
DOWNLOAD,
|
DOWNLOAD,
|
||||||
@@ -99,6 +105,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
|
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
|
||||||
View view = LayoutInflater.from(viewGroup.getContext())
|
View view = LayoutInflater.from(viewGroup.getContext())
|
||||||
.inflate(R.layout.update_item_view, viewGroup, false);
|
.inflate(R.layout.update_item_view, viewGroup, false);
|
||||||
|
view.setBackground(mActivity.getDrawable(R.drawable.list_item_background));
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,8 +164,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
viewHolder.mProgressBar.setProgress(update.getProgress());
|
viewHolder.mProgressBar.setProgress(update.getProgress());
|
||||||
}
|
}
|
||||||
|
|
||||||
viewHolder.itemView.setOnLongClickListener(
|
viewHolder.itemView.setOnLongClickListener(getLongClickListener(update, canDelete));
|
||||||
canDelete ? getDeleteClickListener(update.getDownloadId()) : null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void handleNotActiveStatus(ViewHolder viewHolder, UpdateDownload update) {
|
private void handleNotActiveStatus(ViewHolder viewHolder, UpdateDownload update) {
|
||||||
@@ -170,11 +176,10 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
viewHolder.mBuildVersion.setText(buildVersion);
|
viewHolder.mBuildVersion.setText(buildVersion);
|
||||||
|
|
||||||
if (update.getPersistentStatus() == UpdateStatus.Persistent.VERIFIED) {
|
if (update.getPersistentStatus() == UpdateStatus.Persistent.VERIFIED) {
|
||||||
viewHolder.itemView.setOnLongClickListener(
|
viewHolder.itemView.setOnLongClickListener(getLongClickListener(update, true));
|
||||||
getDeleteClickListener(update.getDownloadId()));
|
|
||||||
setButtonAction(viewHolder.mAction, Action.INSTALL, update.getDownloadId(), !isBusy());
|
setButtonAction(viewHolder.mAction, Action.INSTALL, update.getDownloadId(), !isBusy());
|
||||||
} else {
|
} else {
|
||||||
viewHolder.itemView.setOnLongClickListener(null);
|
viewHolder.itemView.setOnLongClickListener(getLongClickListener(update, false));
|
||||||
setButtonAction(viewHolder.mAction, Action.DOWNLOAD, update.getDownloadId(), !isBusy());
|
setButtonAction(viewHolder.mAction, Action.DOWNLOAD, update.getDownloadId(), !isBusy());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -195,6 +200,8 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
viewHolder.itemView.setSelected(downloadId.equals(mSelectedDownload));
|
||||||
|
|
||||||
boolean activeLayout;
|
boolean activeLayout;
|
||||||
switch (update.getPersistentStatus()) {
|
switch (update.getPersistentStatus()) {
|
||||||
case UpdateStatus.Persistent.UNKNOWN:
|
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,
|
private void setButtonAction(ImageButton button, Action action, final String downloadId,
|
||||||
boolean enabled) {
|
boolean enabled) {
|
||||||
|
final View.OnClickListener clickListener;
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case DOWNLOAD:
|
case DOWNLOAD:
|
||||||
button.setImageResource(R.drawable.ic_download);
|
button.setImageResource(R.drawable.ic_download);
|
||||||
button.setContentDescription(
|
button.setContentDescription(
|
||||||
mActivity.getString(R.string.action_description_download));
|
mActivity.getString(R.string.action_description_download));
|
||||||
button.setEnabled(enabled);
|
button.setEnabled(enabled);
|
||||||
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
|
clickListener = !enabled ? null : new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
mUpdaterController.startDownload(downloadId);
|
mUpdaterController.startDownload(downloadId);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
break;
|
break;
|
||||||
case PAUSE:
|
case PAUSE:
|
||||||
button.setImageResource(R.drawable.ic_pause);
|
button.setImageResource(R.drawable.ic_pause);
|
||||||
button.setContentDescription(
|
button.setContentDescription(
|
||||||
mActivity.getString(R.string.action_description_pause));
|
mActivity.getString(R.string.action_description_pause));
|
||||||
button.setEnabled(enabled);
|
button.setEnabled(enabled);
|
||||||
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
|
clickListener = !enabled ? null : new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
mUpdaterController.pauseDownload(downloadId);
|
mUpdaterController.pauseDownload(downloadId);
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
break;
|
break;
|
||||||
case RESUME: {
|
case RESUME: {
|
||||||
button.setImageResource(R.drawable.ic_resume);
|
button.setImageResource(R.drawable.ic_resume);
|
||||||
@@ -275,7 +283,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
button.setEnabled(enabled);
|
button.setEnabled(enabled);
|
||||||
UpdateDownload update = mUpdaterController.getUpdate(downloadId);
|
UpdateDownload update = mUpdaterController.getUpdate(downloadId);
|
||||||
final boolean canInstall = Utils.canInstall(update);
|
final boolean canInstall = Utils.canInstall(update);
|
||||||
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
|
clickListener = !enabled ? null : new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
if (canInstall) {
|
if (canInstall) {
|
||||||
@@ -285,7 +293,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
Snackbar.LENGTH_LONG);
|
Snackbar.LENGTH_LONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case INSTALL: {
|
case INSTALL: {
|
||||||
@@ -295,7 +303,7 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
button.setEnabled(enabled);
|
button.setEnabled(enabled);
|
||||||
UpdateDownload update = mUpdaterController.getUpdate(downloadId);
|
UpdateDownload update = mUpdaterController.getUpdate(downloadId);
|
||||||
final boolean canInstall = Utils.canInstall(update);
|
final boolean canInstall = Utils.canInstall(update);
|
||||||
button.setOnClickListener(!enabled ? null : new View.OnClickListener() {
|
clickListener = !enabled ? null : new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
if (canInstall) {
|
if (canInstall) {
|
||||||
@@ -305,11 +313,24 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
Snackbar.LENGTH_LONG);
|
Snackbar.LENGTH_LONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
};
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
default:
|
||||||
|
clickListener = null;
|
||||||
}
|
}
|
||||||
button.setAlpha(enabled ? 1.f : mAlphaDisabledValue);
|
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() {
|
private boolean isBusy() {
|
||||||
@@ -331,11 +352,14 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
.setNegativeButton(android.R.string.cancel, null);
|
.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() {
|
return new View.OnLongClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onLongClick(View view) {
|
public boolean onLongClick(View view) {
|
||||||
getDeleteDialog(downloadId).show();
|
if (mActionMode == null) {
|
||||||
|
startActionMode(update, canDelete);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -372,4 +396,73 @@ public class UpdatesListAdapter extends RecyclerView.Adapter<UpdatesListAdapter.
|
|||||||
})
|
})
|
||||||
.setNegativeButton(android.R.string.cancel, null);
|
.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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user