Bug 1315717 - Add ripple feedback to AS context menu buttons on Android >= 5 r?sebastian
The circular ripple is only available on API >= 21. We can fallback to a different solution
for older devices, see following patch.
MozReview-Commit-ID: C0aBqsKsuZ5
--- a/mobile/android/base/java/org/mozilla/gecko/home/activitystream/StreamItem.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/StreamItem.java
@@ -22,16 +22,17 @@ import org.mozilla.gecko.db.BrowserContr
import org.mozilla.gecko.home.HomePager;
import org.mozilla.gecko.home.activitystream.menu.ActivityStreamContextMenu;
import org.mozilla.gecko.home.activitystream.topsites.CirclePageIndicator;
import org.mozilla.gecko.home.activitystream.topsites.TopSitesPagerAdapter;
import org.mozilla.gecko.icons.IconCallback;
import org.mozilla.gecko.icons.IconResponse;
import org.mozilla.gecko.icons.Icons;
import org.mozilla.gecko.util.DrawableUtil;
+import org.mozilla.gecko.util.ViewUtil;
import org.mozilla.gecko.util.TouchTargetUtil;
import org.mozilla.gecko.widget.FaviconView;
import java.util.concurrent.Future;
import static org.mozilla.gecko.activitystream.ActivityStream.extractLabel;
public abstract class StreamItem extends RecyclerView.ViewHolder {
@@ -119,16 +120,18 @@ public abstract class StreamItem extends
public void onClick(View v) {
ActivityStreamContextMenu.show(v.getContext(),
menuButton,
ActivityStreamContextMenu.MenuMode.HIGHLIGHT,
title, url, onUrlOpenListener, onUrlOpenInBackgroundListener,
vIconView.getWidth(), vIconView.getHeight());
}
});
+
+ ViewUtil.enableTouchRipple(menuButton);
}
public void bind(Cursor cursor, int tilesWidth, int tilesHeight) {
final long time = cursor.getLong(cursor.getColumnIndexOrThrow(BrowserContract.Highlights.DATE));
final String ago = DateUtils.getRelativeTimeSpanString(time, System.currentTimeMillis(), DateUtils.MINUTE_IN_MILLIS, 0).toString();
title = cursor.getString(cursor.getColumnIndexOrThrow(BrowserContract.History.TITLE));
--- a/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java
+++ b/mobile/android/base/java/org/mozilla/gecko/home/activitystream/topsites/TopSitesCard.java
@@ -14,16 +14,17 @@ import android.widget.TextView;
import org.mozilla.gecko.R;
import org.mozilla.gecko.activitystream.ActivityStream;
import org.mozilla.gecko.home.HomePager;
import org.mozilla.gecko.home.activitystream.menu.ActivityStreamContextMenu;
import org.mozilla.gecko.icons.IconCallback;
import org.mozilla.gecko.icons.IconResponse;
import org.mozilla.gecko.icons.Icons;
import org.mozilla.gecko.util.DrawableUtil;
+import org.mozilla.gecko.util.ViewUtil;
import org.mozilla.gecko.util.TouchTargetUtil;
import org.mozilla.gecko.widget.FaviconView;
import java.util.EnumSet;
import java.util.concurrent.Future;
class TopSitesCard extends RecyclerView.ViewHolder
implements IconCallback, View.OnClickListener {
@@ -48,16 +49,18 @@ class TopSitesCard extends RecyclerView.
this.onUrlOpenListener = onUrlOpenListener;
this.onUrlOpenInBackgroundListener = onUrlOpenInBackgroundListener;
card.setOnClickListener(this);
TouchTargetUtil.ensureTargetHitArea(menuButton, card);
menuButton.setOnClickListener(this);
+
+ ViewUtil.enableTouchRipple(menuButton);
}
void bind(final TopSitesPageAdapter.TopSite topSite) {
ActivityStream.extractLabel(itemView.getContext(), topSite.url, true, new ActivityStream.LabelCallback() {
@Override
public void onLabelExtracted(String label) {
title.setText(label);
}
new file mode 100644
--- /dev/null
+++ b/mobile/android/base/java/org/mozilla/gecko/util/ViewUtil.java
@@ -0,0 +1,33 @@
+/* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+package org.mozilla.gecko.util;
+
+import android.content.res.TypedArray;
+import android.view.View;
+
+import org.mozilla.gecko.AppConstants;
+import org.mozilla.gecko.R;
+
+public class ViewUtil {
+
+ /**
+ * Enable a circular touch ripple for a given view. This is intended for borderless views,
+ * such as (3-dot) menu buttons.
+ *
+ * Because of platform limitations a square ripple is used on Android 4.
+ */
+ public static void enableTouchRipple(View view) {
+ final TypedArray backgroundDrawableArray;
+ if (AppConstants.Versions.feature21Plus) {
+ backgroundDrawableArray = view.getContext().obtainStyledAttributes(new int[] { R.attr.selectableItemBackgroundBorderless });
+ } else {
+ backgroundDrawableArray = view.getContext().obtainStyledAttributes(new int[] { R.attr.selectableItemBackground });
+ }
+
+ // This call is deprecated, but the replacement setBackground(Drawable) isn't available
+ // until API 16.
+ view.setBackgroundDrawable(backgroundDrawableArray.getDrawable(0));
+ }
+}
--- a/mobile/android/base/moz.build
+++ b/mobile/android/base/moz.build
@@ -737,16 +737,17 @@ gbjar.sources += ['java/org/mozilla/geck
'trackingprotection/TrackingProtectionPrompt.java',
'updater/PostUpdateHandler.java',
'updater/UpdateService.java',
'updater/UpdateServiceHelper.java',
'util/ColorUtil.java',
'util/DrawableUtil.java',
'util/ResourceDrawableUtils.java',
'util/TouchTargetUtil.java',
+ 'util/ViewUtil.java',
'widget/ActivityChooserModel.java',
'widget/AllCapsTextView.java',
'widget/AnchoredPopup.java',
'widget/AnimatedHeightLayout.java',
'widget/BasicColorPicker.java',
'widget/CheckableLinearLayout.java',
'widget/ClickableWhenDisabledEditText.java',
'widget/ContentSecurityDoorHanger.java',