Reputation: 780
I have this layout:
<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>
So, I am loading remote images into ImageView from web. I know the dimensions of the image so i know width:height ratio. Now I need to somehow apply this ration when I am initializing my layout so it doesnt jump like crazy later in the app.
Upvotes: 2
Views: 2304
Reputation: 2557
As an improvement (as I see it) to makovkastar's answer:
I've tried to make the whole thing a little more simple, wrote it in Kotlin and made it so that the height and width aspects are set as integers as to be more precise by using fractions instead of floating point numbers:
/**
* 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()
}
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DynamicHeightImageView">
<attr name="heightFactor" format="integer"/>
<attr name="widthFactor" format="integer"/>
</declare-styleable>
</resources>
Upvotes: 0
Reputation: 5020
For such case I've created a custom ImageView that maintains it's height relative to width. It has the custom attribute 'height_ratio' that's multiplied by width to get height:
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);
}
}
}
attrs.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="DynamicHeightImageView">
<attr name="height_ratio" format="float"/>
</declare-styleable>
</resources>
Usage:
<com.melnykov.android.views.DynamicHeightImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
custom:height_ratio="0.6"/>
Upvotes: 8
Reputation: 11999
Since you know the dimensions of your image. You can set the image view's dimension programmatically converting pixels into dp
Refer this Convert Pixels to DP
Upvotes: 0
Reputation: 4243
If you use CENTER_INSIDE as scale type, the image will be scaled so that the aspect ratio is preserved and the image fits into the "frame" of the image view that you have defined with layout_width and layout_height. But are you sure that you want your image 2dp high at maximum?
Upvotes: 0