зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1193374
- Remove tab panel preview dimension dependency from TopSites r=mcomella
--HG-- extra : commitid : 5b8ohlvHobz extra : rebase_source : a71a39c54444d5c6d9907fb8830aa2ed72756e77
This commit is contained in:
Родитель
4be8844c38
Коммит
d237378102
|
@ -30,9 +30,19 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||
public final class ThumbnailHelper {
|
||||
private static final String LOGTAG = "GeckoThumbnailHelper";
|
||||
|
||||
public static final float THUMBNAIL_ASPECT_RATIO = 0.571f; // this is a 4:7 ratio (as per UX decision)
|
||||
public static final float TABS_PANEL_THUMBNAIL_ASPECT_RATIO = 0.8333333f;
|
||||
public static final float TOP_SITES_THUMBNAIL_ASPECT_RATIO = 0.571428571f; // this is a 4:7 ratio (as per UX decision)
|
||||
private static final float THUMBNAIL_ASPECT_RATIO;
|
||||
|
||||
public static enum CachePolicy {
|
||||
static {
|
||||
// As we only want to generate one thumbnail for each tab, we calculate the
|
||||
// largest aspect ratio required and create the thumbnail based off that.
|
||||
// Any views with a smaller aspect ratio will use a cropped version of the
|
||||
// same image.
|
||||
THUMBNAIL_ASPECT_RATIO = Math.max(TABS_PANEL_THUMBNAIL_ASPECT_RATIO, TOP_SITES_THUMBNAIL_ASPECT_RATIO);
|
||||
}
|
||||
|
||||
public enum CachePolicy {
|
||||
STORE,
|
||||
NO_STORE
|
||||
}
|
||||
|
@ -55,14 +65,10 @@ public final class ThumbnailHelper {
|
|||
private int mWidth;
|
||||
private int mHeight;
|
||||
private ByteBuffer mBuffer;
|
||||
private final float mThumbnailAspectRatio;
|
||||
|
||||
private ThumbnailHelper() {
|
||||
final Resources res = GeckoAppShell.getContext().getResources();
|
||||
|
||||
final TypedValue outValue = new TypedValue();
|
||||
res.getValue(R.dimen.thumbnail_aspect_ratio, outValue, true);
|
||||
mThumbnailAspectRatio = outValue.getFloat();
|
||||
|
||||
mPendingThumbnails = new LinkedList<Tab>();
|
||||
try {
|
||||
|
@ -111,7 +117,7 @@ public final class ThumbnailHelper {
|
|||
private void updateThumbnailSize() {
|
||||
// Apply any pending width updates.
|
||||
mWidth = mPendingWidth.get();
|
||||
mHeight = Math.round(mWidth * mThumbnailAspectRatio);
|
||||
mHeight = Math.round(mWidth * THUMBNAIL_ASPECT_RATIO);
|
||||
|
||||
int pixelSize = (GeckoAppShell.getScreenDepth() == 24) ? 4 : 2;
|
||||
int capacity = mWidth * mHeight * pixelSize;
|
||||
|
|
|
@ -8,36 +8,25 @@ package org.mozilla.gecko.home;
|
|||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.ThumbnailHelper;
|
||||
import org.mozilla.gecko.util.ColorUtils;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.widget.CropImageView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PorterDuff.Mode;
|
||||
import android.graphics.RectF;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
/**
|
||||
* A height constrained ImageView to show thumbnails of top and pinned sites.
|
||||
* A width constrained ImageView to show thumbnails of top and pinned sites.
|
||||
*/
|
||||
public class TopSitesThumbnailView extends ImageView {
|
||||
public class TopSitesThumbnailView extends CropImageView {
|
||||
private static final String LOGTAG = "GeckoTopSitesThumbnailView";
|
||||
|
||||
// 27.34% opacity filter for the dominant color.
|
||||
private static final int COLOR_FILTER = 0x46FFFFFF;
|
||||
|
||||
// Cache variables used in onMeasure.
|
||||
//
|
||||
// Note: we have two matrices because we can't change it in place - see ImageView.getImageMatrix docs.
|
||||
private final RectF mLayoutRect = new RectF();
|
||||
private Matrix mLayoutCurrentMatrix = new Matrix();
|
||||
private Matrix mLayoutNextMatrix = new Matrix();
|
||||
|
||||
// Default filter color for "Add a bookmark" views.
|
||||
private final int mDefaultColor = ColorUtils.getColor(getContext(), R.color.top_site_default);
|
||||
|
||||
|
@ -47,16 +36,11 @@ public class TopSitesThumbnailView extends ImageView {
|
|||
// Paint for drawing the border.
|
||||
private final Paint mBorderPaint;
|
||||
|
||||
private boolean mResize = false;
|
||||
private int mWidth;
|
||||
private int mHeight;
|
||||
|
||||
public TopSitesThumbnailView(Context context) {
|
||||
this(context, null);
|
||||
|
||||
// A border will be drawn if needed.
|
||||
setWillNotDraw(false);
|
||||
|
||||
}
|
||||
|
||||
public TopSitesThumbnailView(Context context, AttributeSet attrs) {
|
||||
|
@ -73,69 +57,9 @@ public class TopSitesThumbnailView extends ImageView {
|
|||
mBorderPaint.setStyle(Paint.Style.STROKE);
|
||||
}
|
||||
|
||||
public void setImageBitmap(Bitmap bm, boolean resize) {
|
||||
super.setImageBitmap(bm);
|
||||
mResize = resize;
|
||||
clearLayoutVars();
|
||||
|
||||
updateImageMatrix();
|
||||
}
|
||||
|
||||
private void clearLayoutVars() {
|
||||
mLayoutRect.setEmpty();
|
||||
}
|
||||
|
||||
private void updateImageMatrix() {
|
||||
if (!HardwareUtils.isTablet() || !mResize) {
|
||||
return;
|
||||
}
|
||||
|
||||
// No work to be done here - assumes the rect gets reset when a new bitmap is set.
|
||||
if (mLayoutRect.right == mWidth && mLayoutRect.bottom == mHeight) {
|
||||
return;
|
||||
}
|
||||
|
||||
setScaleType(ScaleType.MATRIX);
|
||||
|
||||
mLayoutRect.set(0, 0, mWidth, mHeight);
|
||||
mLayoutNextMatrix.setRectToRect(mLayoutRect, mLayoutRect, Matrix.ScaleToFit.CENTER);
|
||||
setImageMatrix(mLayoutNextMatrix);
|
||||
|
||||
final Matrix swapReferenceMatrix = mLayoutCurrentMatrix;
|
||||
mLayoutCurrentMatrix = mLayoutNextMatrix;
|
||||
mLayoutNextMatrix = swapReferenceMatrix;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageResource(int resId) {
|
||||
super.setImageResource(resId);
|
||||
mResize = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(Drawable drawable) {
|
||||
super.setImageDrawable(drawable);
|
||||
mResize = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure the view to determine the measured width and height.
|
||||
* The height is constrained by the measured width.
|
||||
*
|
||||
* @param widthMeasureSpec horizontal space requirements as imposed by the parent.
|
||||
* @param heightMeasureSpec vertical space requirements as imposed by the parent, but ignored.
|
||||
*/
|
||||
@Override
|
||||
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
|
||||
// Default measuring.
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
// Force the height based on the aspect ratio.
|
||||
mWidth = getMeasuredWidth();
|
||||
mHeight = (int) (mWidth * ThumbnailHelper.THUMBNAIL_ASPECT_RATIO);
|
||||
setMeasuredDimension(mWidth, mHeight);
|
||||
|
||||
updateImageMatrix();
|
||||
protected float getAspectRatio() {
|
||||
return ThumbnailHelper.TOP_SITES_THUMBNAIL_ASPECT_RATIO;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -469,6 +469,7 @@ gbjar.sources += [
|
|||
'tabs/TabsLayoutItemView.java',
|
||||
'tabs/TabsListLayout.java',
|
||||
'tabs/TabsPanel.java',
|
||||
'tabs/TabsPanelThumbnailView.java',
|
||||
'Telemetry.java',
|
||||
'TelemetryContract.java',
|
||||
'TextSelection.java',
|
||||
|
@ -521,6 +522,7 @@ gbjar.sources += [
|
|||
'widget/CheckableLinearLayout.java',
|
||||
'widget/ClickableWhenDisabledEditText.java',
|
||||
'widget/ContentSecurityDoorHanger.java',
|
||||
'widget/CropImageView.java',
|
||||
'widget/DateTimePicker.java',
|
||||
'widget/DefaultDoorHanger.java',
|
||||
'widget/Divider.java',
|
||||
|
|
|
@ -66,9 +66,9 @@
|
|||
android:background="@drawable/tab_thumbnail"
|
||||
android:duplicateParentState="true">
|
||||
|
||||
<org.mozilla.gecko.widget.ThumbnailView android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/tablet_tab_thumbnail_width"
|
||||
android:layout_height="@dimen/tablet_tab_thumbnail_height"
|
||||
<org.mozilla.gecko.tabs.TabsPanelThumbnailView android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/tablet_tab_thumbnail_width"
|
||||
android:layout_height="@dimen/tablet_tab_thumbnail_height"
|
||||
/>
|
||||
|
||||
</org.mozilla.gecko.widget.TabThumbnailWrapper>
|
||||
|
|
|
@ -25,9 +25,9 @@
|
|||
android:background="@drawable/tab_thumbnail"
|
||||
android:duplicateParentState="true">
|
||||
|
||||
<org.mozilla.gecko.widget.ThumbnailView android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/tab_thumbnail_width"
|
||||
android:layout_height="@dimen/tab_thumbnail_height"/>
|
||||
<org.mozilla.gecko.tabs.TabsPanelThumbnailView android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/tab_thumbnail_width"
|
||||
android:layout_height="@dimen/tab_thumbnail_height"/>
|
||||
|
||||
<LinearLayout android:layout_width="@dimen/tab_thumbnail_width"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
android:background="@drawable/tab_thumbnail"
|
||||
android:duplicateParentState="true">
|
||||
|
||||
<org.mozilla.gecko.widget.ThumbnailView android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/tab_thumbnail_width"
|
||||
android:layout_height="@dimen/tab_thumbnail_height"/>
|
||||
<org.mozilla.gecko.tabs.TabsPanelThumbnailView android:id="@+id/thumbnail"
|
||||
android:layout_width="@dimen/tab_thumbnail_width"
|
||||
android:layout_height="@dimen/tab_thumbnail_height"/>
|
||||
|
||||
</org.mozilla.gecko.widget.TabThumbnailWrapper>
|
||||
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
|
||||
<dimen name="overlay_prompt_container_width">360dp</dimen>
|
||||
|
||||
<!-- Should be closer to 0.83 (140/168) but various roundings mean that 0.9 works better -->
|
||||
<item name="thumbnail_aspect_ratio" format="float" type="dimen">0.9</item>
|
||||
|
||||
<item name="tab_strip_content_start" type="dimen">72dp</item>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -213,9 +213,6 @@
|
|||
|
||||
<dimen name="progress_bar_scroll_offset">1.5dp</dimen>
|
||||
|
||||
<!-- This is a 4:7 ratio (as per UX decision). -->
|
||||
<item name="thumbnail_aspect_ratio" format="float" type="dimen">0.571</item>
|
||||
|
||||
<!-- http://blog.danlew.net/2015/01/06/handling-android-resources-with-non-standard-formats/ -->
|
||||
<item name="match_parent" type="dimen">-1</item>
|
||||
<item name="wrap_content" type="dimen">-2</item>
|
||||
|
|
|
@ -10,7 +10,6 @@ import org.mozilla.gecko.R;
|
|||
import org.mozilla.gecko.Tab;
|
||||
import org.mozilla.gecko.util.HardwareUtils;
|
||||
import org.mozilla.gecko.widget.TabThumbnailWrapper;
|
||||
import org.mozilla.gecko.widget.ThumbnailView;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -37,7 +36,7 @@ public class TabsLayoutItemView extends LinearLayout
|
|||
|
||||
private int mTabId;
|
||||
private TextView mTitle;
|
||||
private ThumbnailView mThumbnail;
|
||||
private TabsPanelThumbnailView mThumbnail;
|
||||
private ImageView mCloseButton;
|
||||
private ImageView mAudioPlayingButton;
|
||||
private TabThumbnailWrapper mThumbnailWrapper;
|
||||
|
@ -98,7 +97,7 @@ public class TabsLayoutItemView extends LinearLayout
|
|||
protected void onFinishInflate() {
|
||||
super.onFinishInflate();
|
||||
mTitle = (TextView) findViewById(R.id.title);
|
||||
mThumbnail = (ThumbnailView) findViewById(R.id.thumbnail);
|
||||
mThumbnail = (TabsPanelThumbnailView) findViewById(R.id.thumbnail);
|
||||
mCloseButton = (ImageView) findViewById(R.id.close);
|
||||
mAudioPlayingButton = (ImageView) findViewById(R.id.audio_playing);
|
||||
mThumbnailWrapper = (TabThumbnailWrapper) findViewById(R.id.wrapper);
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- 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.tabs;
|
||||
|
||||
import org.mozilla.gecko.R;
|
||||
import org.mozilla.gecko.ThumbnailHelper;
|
||||
import org.mozilla.gecko.widget.CropImageView;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
/**
|
||||
* A width constrained ImageView to show thumbnails of open tabs in the tabs panel.
|
||||
*/
|
||||
public class TabsPanelThumbnailView extends CropImageView {
|
||||
public static final String LOGTAG = "Gecko" + TabsPanelThumbnailView.class.getSimpleName();
|
||||
|
||||
|
||||
public TabsPanelThumbnailView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public TabsPanelThumbnailView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public TabsPanelThumbnailView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getAspectRatio() {
|
||||
return ThumbnailHelper.TABS_PANEL_THUMBNAIL_ASPECT_RATIO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(Drawable drawable) {
|
||||
boolean resize = true;
|
||||
|
||||
if (drawable == null) {
|
||||
drawable = getResources().getDrawable(R.drawable.tab_panel_tab_background);
|
||||
resize = false;
|
||||
setScaleType(ScaleType.FIT_XY);
|
||||
}
|
||||
|
||||
super.setImageDrawable(drawable, resize);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
/* -*- 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.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Matrix;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.nineoldandroids.view.ViewHelper;
|
||||
|
||||
/**
|
||||
* An ImageView which will always display at the given width and calculated height (based on the width and
|
||||
* the supplied aspect ratio), drawn starting from the top left hand corner. A supplied drawable will be resized to fit
|
||||
* the width of the view; if the resized drawable is too tall for the view then the drawable will be cropped at the
|
||||
* bottom, however if the resized drawable is too short for the view to display whilst honouring it's given width and
|
||||
* height then the drawable will be displayed at full height with the right hand side cropped.
|
||||
*/
|
||||
public abstract class CropImageView extends ThemedImageView {
|
||||
public static final String LOGTAG = "Gecko" + CropImageView.class.getSimpleName();
|
||||
|
||||
private int viewWidth;
|
||||
private int viewHeight;
|
||||
private int drawableWidth;
|
||||
private int drawableHeight;
|
||||
|
||||
private boolean resize = true;
|
||||
private Matrix layoutCurrentMatrix = new Matrix();
|
||||
private Matrix layoutNextMatrix = new Matrix();
|
||||
|
||||
|
||||
public CropImageView(final Context context) {
|
||||
this(context, null);
|
||||
}
|
||||
|
||||
public CropImageView(final Context context, final AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
}
|
||||
|
||||
public CropImageView(final Context context, final AttributeSet attrs, final int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
init();
|
||||
}
|
||||
|
||||
protected abstract float getAspectRatio();
|
||||
|
||||
protected void init() {
|
||||
// Setting the pivots means that the image will be drawn from the top left hand corner. There are
|
||||
// issues in Android 4.1 (16) which mean setting these values to 0 may not work.
|
||||
// http://stackoverflow.com/questions/26658124/setpivotx-doesnt-work-on-android-4-1-1-nineoldandroids
|
||||
ViewHelper.setPivotX(this, 1);
|
||||
ViewHelper.setPivotY(this, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Measure the view to determine the measured width and height.
|
||||
* The height is constrained by the measured width.
|
||||
*
|
||||
* @param widthMeasureSpec horizontal space requirements as imposed by the parent.
|
||||
* @param heightMeasureSpec vertical space requirements as imposed by the parent, but ignored.
|
||||
*/
|
||||
@Override
|
||||
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||
// Default measuring.
|
||||
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||
|
||||
// Force the height based on the aspect ratio.
|
||||
viewWidth = getMeasuredWidth();
|
||||
viewHeight = (int) (viewWidth * getAspectRatio());
|
||||
|
||||
setMeasuredDimension(viewWidth, viewHeight);
|
||||
|
||||
updateImageMatrix();
|
||||
}
|
||||
|
||||
protected void updateImageMatrix() {
|
||||
if (!resize || getDrawable() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
setScaleType(ImageView.ScaleType.MATRIX);
|
||||
|
||||
getDrawable().setBounds(0, 0, viewWidth, viewHeight);
|
||||
|
||||
final float horizontalScaleValue = (float) viewWidth / (float) drawableWidth;
|
||||
final float verticalScaleValue = (float) viewHeight / (float) drawableHeight;
|
||||
|
||||
final float scale = Math.max(verticalScaleValue, horizontalScaleValue);
|
||||
|
||||
layoutNextMatrix.setScale(scale, scale);
|
||||
setImageMatrix(layoutNextMatrix);
|
||||
|
||||
// You can't modify the matrix in place and we want to avoid allocation, so let's keep two references to two
|
||||
// different matrix objects that we can swap when the values need to change
|
||||
final Matrix swapReferenceMatrix = layoutCurrentMatrix;
|
||||
layoutCurrentMatrix = layoutNextMatrix;
|
||||
layoutNextMatrix = swapReferenceMatrix;
|
||||
}
|
||||
|
||||
public void setImageBitmap(final Bitmap bm, final boolean resize) {
|
||||
super.setImageBitmap(bm);
|
||||
|
||||
this.resize = resize;
|
||||
updateImageMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageResource(final int resId) {
|
||||
super.setImageResource(resId);
|
||||
setImageMatrix(null);
|
||||
resize = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setImageDrawable(final Drawable drawable) {
|
||||
this.setImageDrawable(drawable, false);
|
||||
}
|
||||
|
||||
public void setImageDrawable(final Drawable drawable, final boolean resize) {
|
||||
super.setImageDrawable(drawable);
|
||||
|
||||
if (drawable != null) {
|
||||
// Reset the matrix to ensure that any previous changes aren't carried through.
|
||||
setImageMatrix(null);
|
||||
|
||||
drawableWidth = drawable.getIntrinsicWidth();
|
||||
drawableHeight = drawable.getIntrinsicHeight();
|
||||
} else {
|
||||
drawableWidth = -1;
|
||||
drawableHeight = -1;
|
||||
}
|
||||
|
||||
this.resize = resize;
|
||||
|
||||
updateImageMatrix();
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче