Bug 1090364 - Add fading edge to tab strip (r=mcomella)
authorLucas Rocha <lucasr@lucasr.org>
Wed, 26 Nov 2014 19:45:48 +0000
changeset 217694 5c804aa57e4b6449d0607b6d17a449cbb9be2663
parent 217693 b16c0306ec5711c600f4d104ae62dc977b2d1e10
child 217695 ce3eeca4f7933f0334116fb7e0c8a3f42e71fc8e
push id27887
push userryanvm@gmail.com
push dateThu, 27 Nov 2014 02:08:38 +0000
treeherdermozilla-central@c63e741bca2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmcomella
bugs1090364
milestone36.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1090364 - Add fading edge to tab strip (r=mcomella)
mobile/android/base/resources/values/dimens.xml
mobile/android/base/tabs/TabStripView.java
--- a/mobile/android/base/resources/values/dimens.xml
+++ b/mobile/android/base/resources/values/dimens.xml
@@ -21,16 +21,17 @@
     <dimen name="new_tablet_nav_button_width">42dp</dimen>
     <dimen name="new_tablet_nav_button_width_half">21dp</dimen>
     <dimen name="new_tablet_nav_button_width_plus_half">63dp</dimen>
 
     <dimen name="new_tablet_tab_strip_height">44dp</dimen>
     <dimen name="new_tablet_tab_strip_item_width">208dp</dimen>
     <dimen name="new_tablet_tab_strip_item_margin">-28dp</dimen>
     <dimen name="new_tablet_tab_strip_favicon_size">16dp</dimen>
+    <dimen name="new_tablet_tab_strip_fading_edge_size">15dp</dimen>
     <dimen name="new_tablet_site_security_height">60dp</dimen>
     <dimen name="new_tablet_site_security_width">34dp</dimen>
     <!-- We primarily use padding (instead of margins) to increase the hit area. -->
     <dimen name="new_tablet_site_security_padding_vertical">21dp</dimen>
     <dimen name="new_tablet_site_security_padding_horizontal">8dp</dimen>
     <dimen name="new_tablet_site_security_right_margin">1dp</dimen>
     <dimen name="new_tablet_browser_toolbar_height">60dp</dimen>
     <dimen name="new_tablet_browser_toolbar_menu_right_margin">6dp</dimen>
--- a/mobile/android/base/tabs/TabStripView.java
+++ b/mobile/android/base/tabs/TabStripView.java
@@ -3,23 +3,24 @@
  * 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.tabs;
 
 import android.content.Context;
 import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.LinearGradient;
+import android.graphics.Paint;
 import android.graphics.Rect;
+import android.graphics.Shader;
 import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.animation.DecelerateInterpolator;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 import android.view.ViewTreeObserver.OnPreDrawListener;
 
 import com.nineoldandroids.animation.Animator;
 import com.nineoldandroids.animation.Animator.AnimatorListener;
 import com.nineoldandroids.animation.AnimatorSet;
 import com.nineoldandroids.animation.ObjectAnimator;
 
 import java.util.ArrayList;
@@ -44,16 +45,19 @@ public class TabStripView extends TwoWay
     private final TabAnimatorListener animatorListener;
 
     // Filled by calls to ShapeDrawable.getPadding();
     // saved to prevent allocation in draw().
     private final Rect dividerPadding = new Rect();
 
     private boolean isPrivate;
 
+    private final Paint fadingEdgePaint;
+    private final int fadingEdgeSize;
+
     public TabStripView(Context context, AttributeSet attrs) {
         super(context, attrs);
 
         setOrientation(Orientation.HORIZONTAL);
         setChoiceMode(ChoiceMode.SINGLE);
         setItemsCanFocus(true);
         setChildrenDrawingOrderEnabled(true);
         setWillNotDraw(false);
@@ -64,16 +68,20 @@ public class TabStripView extends TwoWay
         divider.getPadding(dividerPadding);
 
         final int itemMargin =
                 resources.getDimensionPixelSize(R.dimen.new_tablet_tab_strip_item_margin);
         setItemMargin(itemMargin);
 
         animatorListener = new TabAnimatorListener();
 
+        fadingEdgePaint = new Paint();
+        fadingEdgeSize =
+                resources.getDimensionPixelOffset(R.dimen.new_tablet_tab_strip_fading_edge_size);
+
         adapter = new TabStripAdapter(context);
         setAdapter(adapter);
     }
 
     private View getViewForTab(Tab tab) {
         final int position = adapter.getPositionForTab(tab);
         return getChildAt(position - getFirstVisiblePosition());
     }
@@ -260,16 +268,45 @@ public class TabStripView extends TwoWay
 
     void updateTab(Tab tab) {
         final TabStripItemView item = (TabStripItemView) getViewForTab(tab);
         if (item != null) {
             item.updateFromTab(tab);
         }
     }
 
+    private float getFadingEdgeStrength() {
+        final int childCount = getChildCount();
+        if (childCount == 0) {
+            return 0.0f;
+        } else {
+            if (getFirstVisiblePosition() + childCount - 1 < adapter.getCount() - 1) {
+                return 1.0f;
+            }
+
+            final int right = getChildAt(childCount - 1).getRight();
+            final int paddingRight = getPaddingRight();
+            final int width = getWidth();
+
+            final float strength = (right > width - paddingRight ?
+                    (float) (right - width + paddingRight) / fadingEdgeSize : 0.0f);
+
+            return Math.max(0.0f, Math.min(strength, 1.0f));
+        }
+    }
+
+    @Override
+    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
+        super.onSizeChanged(w, h, oldw, oldh);
+
+        fadingEdgePaint.setShader(new LinearGradient(w - fadingEdgeSize, 0, w, 0,
+                new int[] { 0x0, 0x11292C29, 0xDD292C29 },
+                new float[] { 0, 0.4f, 1.0f }, Shader.TileMode.CLAMP));
+    }
+
     @Override
     protected int getChildDrawingOrder(int childCount, int i) {
         final int checkedIndex = getCheckedIndex(childCount);
         if (checkedIndex == INVALID_POSITION) {
             return i;
         }
 
         // Always draw the currently selected tab on top of all
@@ -278,20 +315,17 @@ public class TabStripView extends TwoWay
             return checkedIndex;
         } else if (checkedIndex <= i) {
             return i + 1;
         } else {
             return i;
         }
     }
 
-    @Override
-    public void draw(Canvas canvas) {
-        super.draw(canvas);
-
+    private void drawDividers(Canvas canvas) {
         final int bottom = getHeight() - getPaddingBottom() - dividerPadding.bottom;
         final int top = bottom - divider.getIntrinsicHeight();
 
         final int dividerWidth = divider.getIntrinsicWidth();
         final int itemMargin = getItemMargin();
 
         final int childCount = getChildCount();
         final int checkedIndex = getCheckedIndex(childCount);
@@ -311,16 +345,32 @@ public class TabStripView extends TwoWay
             final int left = child.getLeft() - (itemMargin / 2) - dividerWidth;
             final int right = left + dividerWidth;
 
             divider.setBounds(left, top, right, bottom);
             divider.draw(canvas);
         }
     }
 
+    private void drawFadingEdge(Canvas canvas) {
+        final float strength = getFadingEdgeStrength();
+        if (strength > 0.0f) {
+            final int r = getRight();
+            canvas.drawRect(r - fadingEdgeSize, getTop(), r, getBottom(), fadingEdgePaint);
+            fadingEdgePaint.setAlpha((int) (strength * 255));
+        }
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        super.draw(canvas);
+        drawDividers(canvas);
+        drawFadingEdge(canvas);
+    }
+
     private class TabAnimatorListener implements AnimatorListener {
         private void setLayerType(int layerType) {
             final int childCount = getChildCount();
             for (int i = 0; i < childCount; i++) {
                 getChildAt(i).setLayerType(layerType, null);
             }
         }