Bug 1091519 - Re-implement tab strip shapes with ResizablePathDrawable (r=mcomella)

This commit is contained in:
Lucas Rocha 2014-11-07 11:27:18 +00:00
parent 2afb9a0e66
commit 2af6bd8828
5 changed files with 65 additions and 78 deletions

View File

@ -8,45 +8,27 @@
<item android:state_pressed="true" <item android:state_pressed="true"
android:state_checked="true" android:state_checked="true"
gecko:state_private="true"> gecko:state_private="true"
<shape> android:color="@color/highlight_nav_pb" />
<solid android:color="@color/highlight_nav_pb" />
</shape>
</item>
<item android:state_checked="true" <item android:state_checked="true"
gecko:state_private="true"> gecko:state_private="true"
<shape> android:color="@color/background_private" />
<solid android:color="@color/background_private" />
</shape>
</item>
<item android:state_pressed="true" <item android:state_pressed="true"
gecko:state_private="true"> gecko:state_private="true"
<shape> android:color="@color/highlight_dark_focused" />
<solid android:color="@color/highlight_dark_focused" />
</shape>
</item>
<item android:state_pressed="true" <item android:state_pressed="true"
android:state_checked="true"> android:state_checked="true"
<shape> android:color="@color/new_tablet_highlight" />
<solid android:color="@color/new_tablet_highlight" />
</shape>
</item>
<item android:state_checked="true"> <item android:state_checked="true"
<shape> android:color="@color/background_normal" />
<solid android:color="@color/background_normal" />
</shape>
</item>
<item android:state_pressed="true"> <item android:state_pressed="true"
<shape> android:color="@color/new_tablet_highlight_dark" />
<solid android:color="@color/new_tablet_highlight_dark" />
</shape>
</item>
<item android:drawable="@android:color/transparent"/> <item android:color="@android:color/transparent"/>
</selector> </selector>

View File

@ -10,8 +10,6 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_weight="1" android:layout_weight="1"
android:requiresFadingEdge="horizontal"
android:fadingEdgeLength="10dp"
android:paddingTop="8dp"/> android:paddingTop="8dp"/>
<ImageButton <ImageButton

View File

@ -9,6 +9,5 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="@dimen/new_tablet_tab_strip_item_width" android:layout_width="@dimen/new_tablet_tab_strip_item_width"
android:layout_height="match_parent" android:layout_height="match_parent"
android:background="@drawable/new_tablet_tab_strip_item_bg"
android:paddingLeft="28dp" android:paddingLeft="28dp"
android:paddingRight="12dp"/> android:paddingRight="12dp"/>

View File

@ -40,12 +40,12 @@ public class TabCurve {
private TabCurve() { private TabCurve() {
} }
public static int getWidthForHeight(int height) { public static float getWidthForHeight(float height) {
return (int) (height * ASPECT_RATIO); return (int) (height * ASPECT_RATIO);
} }
public static void drawFromTop(Path path, int from, int height, Direction dir) { public static void drawFromTop(Path path, float from, float height, Direction dir) {
final int width = getWidthForHeight(height); final float width = getWidthForHeight(height);
path.cubicTo(from + width * W_M1 * dir.value, 0.0f, path.cubicTo(from + width * W_M1 * dir.value, 0.0f,
from + width * W_M2 * dir.value, height * H_M1, from + width * W_M2 * dir.value, height * H_M1,
@ -55,8 +55,8 @@ public class TabCurve {
from + width * dir.value, height); from + width * dir.value, height);
} }
public static void drawFromBottom(Path path, int from, int height, Direction dir) { public static void drawFromBottom(Path path, float from, float height, Direction dir) {
final int width = getWidthForHeight(height); final float width = getWidthForHeight(height);
path.cubicTo(from + width * (1f - W_M3) * dir.value, height * H_M4, path.cubicTo(from + width * (1f - W_M3) * dir.value, height * H_M4,
from + width * (1f - W_M2) * dir.value, height * H_M3, from + width * (1f - W_M2) * dir.value, height * H_M3,

View File

@ -9,11 +9,15 @@ import org.mozilla.gecko.AboutPages;
import org.mozilla.gecko.R; import org.mozilla.gecko.R;
import org.mozilla.gecko.Tab; import org.mozilla.gecko.Tab;
import org.mozilla.gecko.Tabs; import org.mozilla.gecko.Tabs;
import org.mozilla.gecko.widget.ResizablePathDrawable;
import org.mozilla.gecko.widget.ResizablePathDrawable.NonScaledPathShape;
import org.mozilla.gecko.widget.ThemedImageButton; import org.mozilla.gecko.widget.ThemedImageButton;
import org.mozilla.gecko.widget.ThemedLinearLayout; import org.mozilla.gecko.widget.ThemedLinearLayout;
import org.mozilla.gecko.widget.ThemedTextView; import org.mozilla.gecko.widget.ThemedTextView;
import android.content.Context; import android.content.Context;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Canvas; import android.graphics.Canvas;
import android.graphics.Paint; import android.graphics.Paint;
@ -45,10 +49,10 @@ public class TabStripItemView extends ThemedLinearLayout
private final ThemedTextView titleView; private final ThemedTextView titleView;
private final ThemedImageButton closeView; private final ThemedImageButton closeView;
private final Paint tabPaint; private final ResizablePathDrawable backgroundDrawable;
private final Path tabShape;
private final Region tabRegion; private final Region tabRegion;
private final Region tabClipRegion; private final Region tabClipRegion;
private boolean tabRegionNeedsUpdate;
private final int faviconSize; private final int faviconSize;
private Bitmap lastFavicon; private Bitmap lastFavicon;
@ -61,17 +65,17 @@ public class TabStripItemView extends ThemedLinearLayout
super(context, attrs); super(context, attrs);
setOrientation(HORIZONTAL); setOrientation(HORIZONTAL);
tabShape = new Path();
tabRegion = new Region(); tabRegion = new Region();
tabClipRegion = new Region(); tabClipRegion = new Region();
tabPaint = new Paint(); final Resources res = context.getResources();
tabPaint.setAntiAlias(true);
tabPaint.setColor(0xFFFF0000);
tabPaint.setStrokeWidth(0.0f);
tabPaint.setXfermode(new PorterDuffXfermode(Mode.DST_IN));
faviconSize = getResources().getDimensionPixelSize(R.dimen.new_tablet_tab_strip_favicon_size); final ColorStateList tabColors =
res.getColorStateList(R.drawable.new_tablet_tab_strip_item_bg);
backgroundDrawable = new ResizablePathDrawable(new TabCurveShape(), tabColors);
setBackgroundDrawable(backgroundDrawable);
faviconSize = res.getDimensionPixelSize(R.dimen.new_tablet_tab_strip_favicon_size);
LayoutInflater.from(context).inflate(R.layout.tab_strip_item_view, this); LayoutInflater.from(context).inflate(R.layout.tab_strip_item_view, this);
setOnClickListener(new View.OnClickListener() { setOnClickListener(new View.OnClickListener() {
@ -106,36 +110,10 @@ public class TabStripItemView extends ThemedLinearLayout
protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) {
super.onSizeChanged(width, height, oldWidth, oldHeight); super.onSizeChanged(width, height, oldWidth, oldHeight);
tabShape.reset(); // Queue a tab region update in the next draw() call. We don't
// update it immediately here because we need the new path from
final int curveWidth = TabCurve.getWidthForHeight(height); // the background drawable to be updated first.
tabRegionNeedsUpdate = true;
tabShape.moveTo(0, height);
TabCurve.drawFromBottom(tabShape, 0, height, TabCurve.Direction.RIGHT);
tabShape.lineTo(width - curveWidth, 0);
TabCurve.drawFromTop(tabShape, width - curveWidth, height, TabCurve.Direction.RIGHT);
tabShape.lineTo(0, height);
tabClipRegion.set(0, 0, width, height);
tabRegion.setPath(tabShape, tabClipRegion);
}
@Override
public void draw(Canvas canvas) {
final int saveCount = canvas.saveLayer(0, 0,
getWidth(), getHeight(), null,
Canvas.MATRIX_SAVE_FLAG |
Canvas.CLIP_SAVE_FLAG |
Canvas.HAS_ALPHA_LAYER_SAVE_FLAG |
Canvas.FULL_COLOR_LAYER_SAVE_FLAG |
Canvas.CLIP_TO_LAYER_SAVE_FLAG);
super.draw(canvas);
canvas.drawPath(tabShape, tabPaint);
canvas.restoreToCount(saveCount);
} }
@Override @Override
@ -152,6 +130,18 @@ public class TabStripItemView extends ThemedLinearLayout
return super.onTouchEvent(event); return super.onTouchEvent(event);
} }
@Override
public void draw(Canvas canvas) {
super.draw(canvas);
if (tabRegionNeedsUpdate) {
final Path path = backgroundDrawable.getPath();
tabClipRegion.set(0, 0, getWidth(), getHeight());
tabRegion.setPath(path, tabClipRegion);
tabRegionNeedsUpdate = false;
}
}
@Override @Override
public int[] onCreateDrawableState(int extraSpace) { public int[] onCreateDrawableState(int extraSpace) {
final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); final int[] drawableState = super.onCreateDrawableState(extraSpace + 1);
@ -237,4 +227,22 @@ public class TabStripItemView extends ThemedLinearLayout
Bitmap.createScaledBitmap(favicon, faviconSize, faviconSize, false); Bitmap.createScaledBitmap(favicon, faviconSize, faviconSize, false);
faviconView.setImageBitmap(scaledFavicon); faviconView.setImageBitmap(scaledFavicon);
} }
private static class TabCurveShape extends NonScaledPathShape {
@Override
protected void onResize(float width, float height) {
final Path path = getPath();
path.reset();
final float curveWidth = TabCurve.getWidthForHeight(height);
path.moveTo(0, height);
TabCurve.drawFromBottom(path, 0, height, TabCurve.Direction.RIGHT);
path.lineTo(width - curveWidth, 0);
TabCurve.drawFromTop(path, width - curveWidth, height, TabCurve.Direction.RIGHT);
path.lineTo(0, height);
}
}
} }