use*_*777 8 android bitmap aspect-ratio android-imageview
我需要将Bitmap设置为ImageView以保持16:9的比例.你有什么建议吗?主要解决方案可能是在自定义ImageView上的覆盖方法onMeasure,但是如何?
Eug*_*sov 24
由于PercentFrameLayout并且PercentRelativeLayout在API级别26.0.0中被弃用,我建议您考虑使用ConstraintLayout以保持16:9的比例ImageView.ConstraintLayout是构建Android平台响应式UI的强大工具,您可以在此处找到更多详细信息使用ConstraintLayout构建响应式UI.
下面是如何将ImageView构建到ConstraintLayout以保持16:9比率的示例:
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="@+id/imageView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
android:layout_marginTop="0dp"
app:srcCompat="@mipmap/ic_launcher"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)
不要忘记将constraint-layout依赖项添加到模块的build.gradle文件中
implementation "com.android.support.constraint:constraint-layout:1.0.2"
Run Code Online (Sandbox Code Playgroud)
或者不是编辑XML文件,而是直接在布局编辑器中编辑布局:
编辑01/03/2019:在所有这些时间之后,我强烈建议使用ConstraintLayout下面介绍的@Eugene Brusov。我个人永远不会使用通过覆盖onMeasure进行数学运算的图像视图。
编辑03/29/2018:我下面的回答可能很简单,但可能太多了。如果您想利用Google提供的功能ConstraintLayout,请遵循此答案或向下滚动并查看@Eugene Brusov的答案。
旧答案:
public class CustomImageView extends ImageView {
// some other necessary things
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
int width = getMeasuredWidth();
//force a 16:9 aspect ratio
int height = Math.round(width * .5625f);
setMeasuredDimension(width, height);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在您的xml中
<path.to.package.CustomImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/img"/>
Run Code Online (Sandbox Code Playgroud)
编辑:Google已经正式弃用了从API 26开始的Percent支持库,您应该尽快离开它。
将尺寸设置为比例如果将至少一个视图尺寸设置为“匹配约束”(0dp),则可以将视图尺寸设置为16:9之类的比例。要启用该比率,请单击“切换纵横比约束”(图10中的标注1),然后在出现的输入中输入width:height比率。
如果宽度和高度都设置为匹配约束,则可以单击“切换纵横比约束”以选择哪个尺寸基于另一个比例。视图检查器通过用实线连接相应的边来指示将其设置为比率。
例如,如果将双方都设置为“匹配约束”,请单击两次“切换纵横比约束”以将宽度设置为高度的比率。现在,整个大小取决于视图的高度(可以通过任何方式定义),如下图所示:
此处的更多信息:https : //developer.android.com/training/constraint-layout/index.html#adjust-the-view-size
有一种叫做PercentFrameLayout并且PercentRelativeLayout在支持库。
<android.support.percent.PercentFrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
app:layout_widthPercent="100%"
app:layout_aspectRatio="178%"
android:scaleType="centerCrop"
android:src="@drawable/header_background"/>
<!-- The rest of your layout -->
</android.support.percent.PercentRelativeLayout>
Run Code Online (Sandbox Code Playgroud)
如果仔细看一下上面的布局,您会发现有ImageView问题的(需要固定在16:9处)被包裹在a周围,PercentFrameLayout并且在上设置了两个属性ImageView,您可能以前从未看到过:
app:layout_widthPercent="100%"
app:layout_aspectRatio="178%"
Run Code Online (Sandbox Code Playgroud)
因此,(1)你需要定义一个维度(宽度或高度)是领先于我们的尺寸ImageView问题。在这种情况下,ImageView它将垂直扩展到最大宽度(例如android:layout_width="match_parent")。(2)您需要以百分比设置宽高比(因此,库的名称)为178%(16/9 = 1.77777777778或更简单地讲1.78:1或178%)。
在此处阅读有关百分比支持库的更多信息。
上面的答案对我不起作用,我找到了这个并工作:
public class AspectRatioImageView extends ImageView {
// NOTE: These must be kept in sync with the AspectRatioImageView attributes in attrs.xml.
public static final int MEASUREMENT_WIDTH = 0;
public static final int MEASUREMENT_HEIGHT = 1;
private static final float DEFAULT_ASPECT_RATIO = 1f;
private static final boolean DEFAULT_ASPECT_RATIO_ENABLED = false;
private static final int DEFAULT_DOMINANT_MEASUREMENT = MEASUREMENT_WIDTH;
private float aspectRatio;
private boolean aspectRatioEnabled;
private int dominantMeasurement;
public AspectRatioImageView(Context context) {
this(context, null);
}
public AspectRatioImageView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.AspectRatioImageView);
aspectRatio = a.getFloat(R.styleable.AspectRatioImageView_aspectRatio, DEFAULT_ASPECT_RATIO);
aspectRatioEnabled = a.getBoolean(R.styleable.AspectRatioImageView_aspectRatioEnabled,
DEFAULT_ASPECT_RATIO_ENABLED);
dominantMeasurement = a.getInt(R.styleable.AspectRatioImageView_dominantMeasurement,
DEFAULT_DOMINANT_MEASUREMENT);
a.recycle();
}
@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!aspectRatioEnabled) return;
int newWidth;
int newHeight;
switch (dominantMeasurement) {
case MEASUREMENT_WIDTH:
newWidth = getMeasuredWidth();
newHeight = (int) (newWidth / aspectRatio);
break;
case MEASUREMENT_HEIGHT:
newHeight = getMeasuredHeight();
newWidth = (int) (newHeight * aspectRatio);
break;
default:
throw new IllegalStateException("Unknown measurement with ID " + dominantMeasurement);
}
setMeasuredDimension(newWidth, newHeight);
}
/** Get the aspect ratio for this image view. */
public float getAspectRatio() {
return aspectRatio;
}
/** Set the aspect ratio for this image view. This will update the view instantly. */
public void setAspectRatio(float aspectRatio) {
this.aspectRatio = aspectRatio;
if (aspectRatioEnabled) {
requestLayout();
}
}
/** Get whether or not forcing the aspect ratio is enabled. */
public boolean getAspectRatioEnabled() {
return aspectRatioEnabled;
}
/** set whether or not forcing the aspect ratio is enabled. This will re-layout the view. */
public void setAspectRatioEnabled(boolean aspectRatioEnabled) {
this.aspectRatioEnabled = aspectRatioEnabled;
requestLayout();
}
/** Get the dominant measurement for the aspect ratio. */
public int getDominantMeasurement() {
return dominantMeasurement;
}
/**
* Set the dominant measurement for the aspect ratio.
*
* @see #MEASUREMENT_WIDTH
* @see #MEASUREMENT_HEIGHT
*/
public void setDominantMeasurement(int dominantMeasurement) {
if (dominantMeasurement != MEASUREMENT_HEIGHT && dominantMeasurement != MEASUREMENT_WIDTH) {
throw new IllegalArgumentException("Invalid measurement type.");
}
this.dominantMeasurement = dominantMeasurement;
requestLayout();
}
}
Run Code Online (Sandbox Code Playgroud)
注意:一个符号*更改为/(阅读源代码中的注释)而这在您的/values/attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="AspectRatioImageView">
<attr name="aspectRatio" format="float" />
<attr name="aspectRatioEnabled" format="boolean" />
<attr name="dominantMeasurement">
<enum name="width" value="0" />
<enum name="height" value="1" />
</attr>
</declare-styleable>
</resources>
Run Code Online (Sandbox Code Playgroud)
然后你可以在你的布局中使用这种方式(aspectRatio = width/height):
<com.yourpackage.ui.classes.AspectRatioImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
app:aspectRatio="1.78"
app:aspectRatioEnabled="true"
app:dominantMeasurement="width" />
Run Code Online (Sandbox Code Playgroud)