jenkins-bot has submitted this change and it was merged.

Change subject: Tweak title pronunciation icon appearance
......................................................................


Tweak title pronunciation icon appearance

* Reduce the size of the icon[0] and increase the hit area.
* Seperate the view and collision concerns.

[0] https://veuwer.com/i/3e7s,3e7t

Bug: T114524
Change-Id: I5d506c96069584bc861441fd6612e04d17d58067
---
M app/src/main/java/org/wikipedia/richtext/AudioUrlSpan.java
M app/src/main/java/org/wikipedia/richtext/ClickSpan.java
A app/src/main/java/org/wikipedia/richtext/DefaultClickSpan.java
M app/src/main/java/org/wikipedia/richtext/DrawableSpan.java
M app/src/main/java/org/wikipedia/richtext/TextViewSpanOnTouchListener.java
M app/src/main/res/values/dimens.xml
6 files changed, 170 insertions(+), 68 deletions(-)

Approvals:
  Dbrant: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/app/src/main/java/org/wikipedia/richtext/AudioUrlSpan.java 
b/app/src/main/java/org/wikipedia/richtext/AudioUrlSpan.java
index b7ec392..35c0972 100644
--- a/app/src/main/java/org/wikipedia/richtext/AudioUrlSpan.java
+++ b/app/src/main/java/org/wikipedia/richtext/AudioUrlSpan.java
@@ -1,7 +1,11 @@
 package org.wikipedia.richtext;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.LevelListDrawable;
 import android.support.annotation.ColorInt;
@@ -18,6 +22,7 @@
 import org.wikipedia.media.AvPlayer;
 
 public class AudioUrlSpan extends AnimatedImageSpan implements ClickSpan {
+
     private static final int STOP_ICON_LEVEL = 0;
     private static final int PLAY_ICON_LEVEL = 1;
 
@@ -30,6 +35,9 @@
     @NonNull
     private final String path;
 
+    @NonNull
+    private final DefaultClickSpan clickSpan;
+
     public AudioUrlSpan(@NonNull View view,
                         @NonNull AvPlayer player,
                         @NonNull String path,
@@ -37,6 +45,7 @@
         super(view, drawable(view.getContext()), verticalAlignment);
         this.player = player;
         this.path = path;
+        clickSpan = clickSpan(view.getResources());
     }
 
     public void setTint(@ColorInt int color) {
@@ -44,8 +53,13 @@
     }
 
     @Override
-    public void onClick(TextView textView) {
+    public void onClick(@NonNull TextView textView) {
         toggle();
+    }
+
+    @Override
+    public boolean contains(@NonNull PointF point) {
+        return clickSpan.contains(point);
     }
 
     @Override
@@ -74,6 +88,28 @@
         return super.getDrawable();
     }
 
+    @Override
+    @SuppressWarnings("checkstyle:parameternumber")
+    public void draw(Canvas canvas,
+                     CharSequence text,
+                     int start,
+                     int end,
+                     float x,
+                     int top,
+                     int y,
+                     int bottom,
+                     Paint paint) {
+        super.draw(canvas, text, start, end, x, top, y, bottom, paint);
+
+        clickSpan.setOriginX(x + getDrawable().getBounds().centerX());
+        clickSpan.setOriginY(drawY(y, bottom) + 
getDrawable().getBounds().centerY());
+
+        final boolean debugClickBounds = false;
+        if (debugClickBounds) {
+            clickSpan.draw(canvas);
+        }
+    }
+
     private void showIcon(int level) {
         getDrawable().setLevel(level);
     }
@@ -82,23 +118,37 @@
         return getDrawable().getLevel();
     }
 
+    @NonNull
     private static Drawable drawable(Context context) {
         LevelListDrawable levels = new AppLevelListDrawable();
         levels.addLevel(PLAY_ICON_LEVEL, PLAY_ICON_LEVEL, 
spinnerDrawable(context));
         levels.addLevel(STOP_ICON_LEVEL, STOP_ICON_LEVEL, 
speakerDrawable(context));
+        int radius = getDimensionPixelSize(context, 
R.dimen.audio_url_span_loading_spinner_radius);
+        levels.setBounds(0, 0, radius * 2, radius * 2);
         return levels;
     }
 
+    @NonNull
     private static Drawable speakerDrawable(Context context) {
         return getDrawable(context, R.drawable.ic_volume_up_black_24dp);
     }
 
+    @NonNull
     private static Drawable spinnerDrawable(Context context) {
         return new CircularProgressDrawable(Color.WHITE,
                 getDimensionPixelSize(context, 
R.dimen.audio_url_span_loading_spinner_border_thickness),
                 getDimensionPixelSize(context, 
R.dimen.audio_url_span_loading_spinner_radius));
     }
 
+    @NonNull
+    private DefaultClickSpan clickSpan(Resources resources) {
+        DefaultClickSpan span = new DefaultClickSpan();
+        float leg = resources.getDimension(R.dimen.audio_url_span_click_size);
+        span.setWidth(leg);
+        span.setHeight(leg);
+        return span;
+    }
+
     private static Drawable getDrawable(Context context, @DrawableRes int id) {
         return context.getResources().getDrawable(id);
     }
diff --git a/app/src/main/java/org/wikipedia/richtext/ClickSpan.java 
b/app/src/main/java/org/wikipedia/richtext/ClickSpan.java
index e47cbe4..d0ea480 100644
--- a/app/src/main/java/org/wikipedia/richtext/ClickSpan.java
+++ b/app/src/main/java/org/wikipedia/richtext/ClickSpan.java
@@ -1,7 +1,11 @@
 package org.wikipedia.richtext;
 
+import android.graphics.PointF;
+import android.support.annotation.NonNull;
 import android.widget.TextView;
 
 public interface ClickSpan {
-    void onClick(TextView textView);
+    void onClick(@NonNull TextView textView);
+    /** @param point Click coordinates relative the host View. */
+    boolean contains(@NonNull PointF point);
 }
\ No newline at end of file
diff --git a/app/src/main/java/org/wikipedia/richtext/DefaultClickSpan.java 
b/app/src/main/java/org/wikipedia/richtext/DefaultClickSpan.java
new file mode 100644
index 0000000..cfa6990
--- /dev/null
+++ b/app/src/main/java/org/wikipedia/richtext/DefaultClickSpan.java
@@ -0,0 +1,65 @@
+package org.wikipedia.richtext;
+
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.PointF;
+import android.graphics.RectF;
+import android.support.annotation.NonNull;
+import android.widget.TextView;
+
+public class DefaultClickSpan implements ClickSpan {
+    // The click collision area relative the host View with origin at 
centerpoint.
+    @NonNull
+    private final RectF bounds = new RectF();
+
+    /** @param x Icon origin x coordinate relative the host View. */
+    public void setOriginX(float x) {
+        setOrigin(x, bounds.centerY());
+    }
+
+    /** @param y Icon origin y coordinate relative the host View. */
+    public void setOriginY(float y) {
+        setOrigin(bounds.centerX(), y);
+    }
+
+    public void setOrigin(float x, float y) {
+        bounds.offset(x - bounds.centerX(), y - bounds.centerY());
+    }
+
+    public void setWidth(float width) {
+        setRect(width, bounds.height());
+    }
+
+    public void setHeight(float height) {
+        setRect(bounds.width(), height);
+    }
+
+    public void setRect(float width, float height) {
+        float x = bounds.centerX();
+        float y = bounds.centerY();
+
+        float a = width / 2;
+        float b = height / 2;
+        bounds.set(-a, -b, a, b);
+
+        setOrigin(x, y);
+    }
+
+    public void draw(Canvas canvas) {
+        Paint debugPaint = new Paint();
+        debugPaint.setStyle(Paint.Style.STROKE);
+        debugPaint.setColor(Color.RED);
+
+        canvas.drawRect(bounds, debugPaint);
+    }
+
+    @Override
+    public void onClick(@NonNull TextView textView) {
+    }
+
+    @Override
+    public boolean contains(@NonNull PointF point) {
+        return bounds.contains(point.x, point.y);
+    }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/wikipedia/richtext/DrawableSpan.java 
b/app/src/main/java/org/wikipedia/richtext/DrawableSpan.java
index 206fa71..8f56804 100644
--- a/app/src/main/java/org/wikipedia/richtext/DrawableSpan.java
+++ b/app/src/main/java/org/wikipedia/richtext/DrawableSpan.java
@@ -82,22 +82,15 @@
                      float x,
                      int top,
                      int y,
-                     int bottom, Paint paint) {
+                     int bottom,
+                     Paint paint) {
         if (drawable == null) {
             return;
         }
 
         canvas.save();
 
-        int transY;
-        if (mVerticalAlignment == ALIGN_BOTTOM) {
-            transY = bottom;
-        } else {
-            transY = y;
-        }
-        transY -= drawable.getBounds().bottom;
-
-        canvas.translate(x, transY);
+        canvas.translate(x, drawY(y, bottom));
         drawable.draw(canvas);
         canvas.restore();
     }
@@ -112,6 +105,17 @@
         }
     }
 
+    protected int drawY(int y, int bottom) {
+        int ret;
+        if (mVerticalAlignment == ALIGN_BASELINE) {
+            ret = y;
+        } else {
+            ret = bottom;
+        }
+        ret -= drawable == null ? 0 : drawable.getBounds().bottom;
+        return ret;
+    }
+
     private void init() {
         // super.getDrawable() is convoluted:
         // * May return an original or a new Drawable; does not keep a 
reference in the latter
diff --git 
a/app/src/main/java/org/wikipedia/richtext/TextViewSpanOnTouchListener.java 
b/app/src/main/java/org/wikipedia/richtext/TextViewSpanOnTouchListener.java
index e40604f..1a2bc67 100644
--- a/app/src/main/java/org/wikipedia/richtext/TextViewSpanOnTouchListener.java
+++ b/app/src/main/java/org/wikipedia/richtext/TextViewSpanOnTouchListener.java
@@ -1,13 +1,15 @@
 package org.wikipedia.richtext;
 
-import android.graphics.Rect;
+import android.graphics.PointF;
 import android.support.annotation.NonNull;
 import android.support.annotation.Nullable;
-import android.text.Layout;
 import android.text.Spanned;
 import android.view.MotionEvent;
 import android.view.View;
 import android.widget.TextView;
+
+import java.util.ArrayList;
+import java.util.List;
 
 public class TextViewSpanOnTouchListener implements View.OnTouchListener {
     @NonNull private TextView textView;
@@ -18,53 +20,51 @@
 
     @Override
     public boolean onTouch(View view, MotionEvent event) {
-        ClickSpan span = getSpanned() == null ? null : 
getEventClickSpan(getSpanned(), event);
-        if (span == null) {
+        List<ClickSpan> contains = getSpanned() == null
+                ? null
+                : filterContains(allClickSpans(getSpanned()), 
getEventPoint(event));
+        if (contains == null || contains.isEmpty()) {
             return false;
         }
 
+
         int action = event.getAction();
         if (action == MotionEvent.ACTION_UP) {
-            span.onClick(textView);
+            for (ClickSpan span : contains) {
+                span.onClick(textView);
+            }
         }
 
         return action == MotionEvent.ACTION_UP || action == 
MotionEvent.ACTION_DOWN;
     }
 
-    @Nullable
-    private ClickSpan getEventClickSpan(@NonNull Spanned spanned, @NonNull 
MotionEvent event) {
-        return getEventSpan(spanned, event, ClickSpan.class);
-    }
-
-    @Nullable
-    private <T> T getEventSpan(@NonNull Spanned spanned,
-                               @NonNull MotionEvent event,
-                               @NonNull Class<T> clazz) {
-        Integer offset = getEventCharacterOffset(event);
-        if (offset == null) {
-            return null;
+    @NonNull
+    private List<ClickSpan> filterContains(@NonNull ClickSpan[] spans, 
@NonNull PointF point) {
+        List<ClickSpan> contains = new ArrayList<>();
+        for (ClickSpan span : spans) {
+            if (span.contains(point)) {
+                contains.add(span);
+            }
         }
-
-        T[] spans = spanned.getSpans(offset, offset, clazz);
-        return spans.length > 0 ? spans[0] : null;
+        return contains;
     }
 
-    @Nullable
-    private Integer getEventCharacterOffset(@NonNull MotionEvent event) {
-        int x = getEventX(event);
-        int y = getEventY(event);
-        int line = getLineOffset(y);
-
-        Rect bounds = getLineBounds(line);
-        return bounds.contains(x, y) ? getCharacterOffset(line, x) : null;
+    @NonNull
+    private ClickSpan[] allClickSpans(Spanned spanned) {
+        return spanned.getSpans(0, spanned.length(), ClickSpan.class);
     }
 
-    private int getEventX(@NonNull MotionEvent event) {
-        return Math.round(event.getX()) - getTotalPaddingLeft() + getScrollX();
+    @NonNull
+    private PointF getEventPoint(@NonNull MotionEvent event) {
+        return new PointF(getEventX(event), getEventY(event));
     }
 
-    private int getEventY(@NonNull MotionEvent event) {
-        return Math.round(event.getY()) - getTotalPaddingTop() + getScrollY();
+    private float getEventX(@NonNull MotionEvent event) {
+        return event.getX() - getTotalPaddingLeft() + getScrollX();
+    }
+
+    private float getEventY(@NonNull MotionEvent event) {
+        return event.getY() - getTotalPaddingTop() + getScrollY();
     }
 
     @Nullable
@@ -74,28 +74,6 @@
 
     private CharSequence getText() {
         return textView.getText();
-    }
-
-    private Rect getLineBounds(int line) {
-        Rect bounds = new Rect();
-        getLayout().getLineBounds(line, bounds);
-        // Left and right are set to the bounds of the TextView, not the 
bounds of the line. See
-        // Layout.getLineBounds.
-        bounds.left = Math.round(getLayout().getLineLeft(line));
-        bounds.right = Math.round(getLayout().getLineRight(line));
-        return bounds;
-    }
-
-    private int getCharacterOffset(int line, int x) {
-        return getLayout().getOffsetForHorizontal(line, x);
-    }
-
-    private int getLineOffset(int y) {
-        return getLayout().getLineForVertical(y);
-    }
-
-    private Layout getLayout() {
-        return textView.getLayout();
     }
 
     private int getScrollX() {
diff --git a/app/src/main/res/values/dimens.xml 
b/app/src/main/res/values/dimens.xml
index a32ffaa..6b580c1 100644
--- a/app/src/main/res/values/dimens.xml
+++ b/app/src/main/res/values/dimens.xml
@@ -70,8 +70,9 @@
     <item name="lead_subtitle_leading_scalar" format="float" 
type="dimen">1.35</item>
     <item name="lead_subtitle_paragraph_scalar" format="float" 
type="dimen">1.15</item>
 
-    <dimen name="audio_url_span_loading_spinner_border_thickness">3dp</dimen>
-    <dimen name="audio_url_span_loading_spinner_radius">12dp</dimen>
+    <dimen name="audio_url_span_loading_spinner_border_thickness">2dp</dimen>
+    <dimen name="audio_url_span_loading_spinner_radius">8dp</dimen>
+    <dimen name="audio_url_span_click_size">48dp</dimen>
 
     <!-- Maps -->
     <integer name="map_default_zoom">12</integer>

-- 
To view, visit https://gerrit.wikimedia.org/r/255057
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I5d506c96069584bc861441fd6612e04d17d58067
Gerrit-PatchSet: 4
Gerrit-Project: apps/android/wikipedia
Gerrit-Branch: master
Gerrit-Owner: Niedzielski <[email protected]>
Gerrit-Reviewer: BearND <[email protected]>
Gerrit-Reviewer: Brion VIBBER <[email protected]>
Gerrit-Reviewer: Dbrant <[email protected]>
Gerrit-Reviewer: Mholloway <[email protected]>
Gerrit-Reviewer: Niedzielski <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to