Android 相对于宽度的图像视图高度

Android 相对于宽度的图像视图高度,android,android-layout,imageview,android-imageview,Android,Android Layout,Imageview,Android Imageview,我有这样的布局: <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" style="@style/AppTheme.Widgets.Box" android:orientation="vertical" android:layout_width="match_parent" android:layout_height="wrap_content">

我有这样的布局:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    style="@style/AppTheme.Widgets.Box"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="2dp"
        android:scaleType="centerCrop"
        android:background="#eee"/>

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="7dp"
        android:gravity="center"/>

</LinearLayout>


所以,我正在从web将远程图像加载到ImageView中。我知道图像的尺寸,所以我知道宽高比。现在,当我初始化布局时,我需要以某种方式应用此比例,这样它就不会在应用程序的后面疯狂地跳跃。

如果使用“中间”作为缩放类型,则图像将被缩放,以便保留纵横比,并且图像适合使用布局宽度和布局高度定义的图像视图的“框架”。但是你确定你想让你的图像达到最大2dp高吗?

因为你知道图像的尺寸。可以通过编程将像素转换为dp来设置图像视图的维度


请参阅此

对于这种情况,我创建了一个自定义的ImageView,它保持了相对于宽度的高度。它具有自定义属性“height_ratio”,该属性乘以宽度可获得高度:

DynamicHeightImageView.java:

/**
 * An {@link android.widget.ImageView} layout that maintains a consistent width to height aspect ratio.
 */
public class DynamicHeightImageView extends ImageView {

    private float mHeightRatio;

    public DynamicHeightImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DynamicHeightImageView, 0, 0);
        try {
            mHeightRatio = ta.getFloat(R.styleable.DynamicHeightImageView_height_ratio, 0.0f);
        } finally {
            ta.recycle();
        }
    }

    public DynamicHeightImageView(Context context) {
        super(context);
    }

    public void setHeightRatio(float ratio) {
        if (ratio != mHeightRatio) {
            mHeightRatio = ratio;
            requestLayout();
        }
    }

    public double getHeightRatio() {
        return mHeightRatio;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mHeightRatio > 0.0f) {
            // set the image views size
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = (int) (width * mHeightRatio);
            setMeasuredDimension(width, height);
        }
        else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DynamicHeightImageView">
        <attr name="height_ratio" format="float"/>
    </declare-styleable>
</resources>
<com.melnykov.android.views.DynamicHeightImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    custom:height_ratio="0.6"/>
attrs.xml:

/**
 * An {@link android.widget.ImageView} layout that maintains a consistent width to height aspect ratio.
 */
public class DynamicHeightImageView extends ImageView {

    private float mHeightRatio;

    public DynamicHeightImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DynamicHeightImageView, 0, 0);
        try {
            mHeightRatio = ta.getFloat(R.styleable.DynamicHeightImageView_height_ratio, 0.0f);
        } finally {
            ta.recycle();
        }
    }

    public DynamicHeightImageView(Context context) {
        super(context);
    }

    public void setHeightRatio(float ratio) {
        if (ratio != mHeightRatio) {
            mHeightRatio = ratio;
            requestLayout();
        }
    }

    public double getHeightRatio() {
        return mHeightRatio;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mHeightRatio > 0.0f) {
            // set the image views size
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = (int) (width * mHeightRatio);
            setMeasuredDimension(width, height);
        }
        else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DynamicHeightImageView">
        <attr name="height_ratio" format="float"/>
    </declare-styleable>
</resources>
<com.melnykov.android.views.DynamicHeightImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    custom:height_ratio="0.6"/>

用法:

/**
 * An {@link android.widget.ImageView} layout that maintains a consistent width to height aspect ratio.
 */
public class DynamicHeightImageView extends ImageView {

    private float mHeightRatio;

    public DynamicHeightImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DynamicHeightImageView, 0, 0);
        try {
            mHeightRatio = ta.getFloat(R.styleable.DynamicHeightImageView_height_ratio, 0.0f);
        } finally {
            ta.recycle();
        }
    }

    public DynamicHeightImageView(Context context) {
        super(context);
    }

    public void setHeightRatio(float ratio) {
        if (ratio != mHeightRatio) {
            mHeightRatio = ratio;
            requestLayout();
        }
    }

    public double getHeightRatio() {
        return mHeightRatio;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        if (mHeightRatio > 0.0f) {
            // set the image views size
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int height = (int) (width * mHeightRatio);
            setMeasuredDimension(width, height);
        }
        else {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    }
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="DynamicHeightImageView">
        <attr name="height_ratio" format="float"/>
    </declare-styleable>
</resources>
<com.melnykov.android.views.DynamicHeightImageView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:scaleType="centerCrop"
    custom:height_ratio="0.6"/>

在我看来,这是一种改进:

我试着让整个过程更简单一点,用Kotlin编写,并将高度和宽度方面设置为整数,以便更精确地使用分数而不是浮点数:

/**
 * An [android.widget.ImageView] layout that maintains a consistent width to height aspect ratio.
 */
class DynamicHeightImageView @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : ImageView(context, attrs, defStyleAttr) {

private var heightFactor : Int
private var widthFactor : Int

init {
    context.theme.obtainStyledAttributes(attrs, R.styleable.DynamicHeightImageView, 0, 0).apply {
        heightFactor = getInt(R.styleable.DynamicHeightImageView_heightFactor, 1)
        widthFactor = getInt(R.styleable.DynamicHeightImageView_widthFactor, 1)
    }
}

/**
 * Adjusts the [getHeight] relative to the [getWidth], according to [heightFactor] and [widthFactor].
 */
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
    super.onLayout(changed, left, top, right, bottom)
    layoutParams.height = (width.toFloat() * heightFactor / widthFactor).toInt()
}


但是imageview有一些宽度。我有2列布局,取决于屏幕大小是列的宽度。用这个宽度,我需要计算高度。