Android 實現自定義寬高比的ImageView
阿新 • • 發佈:2019-02-03
前言
我們為什麼要用到寬高比固定的ImageView呢?因為Android螢幕大小不一樣,同樣一張圖片可能會在不同的裝置上顯示效果不同,會發生拉伸等情況。今天就來說一種解決方案,讓圖片的寬高比固定,保證不變形。為了實現這個效果,我們需要自定義一個ImageView。
思路
根據這個ImageView的寬度或者高度去設定,分以下幾種情況:
1.寬度確定,高度不確定,通過寬度設定高度
2.高度確定,寬度不確定,通過高度設定寬度
3.寬高都確定,無需設定,因為設定沒效果
4.寬高都不確定,無法設定寬高比
程式碼
我們先在styles.xml中自定義屬性
<declare-styleable name="MyImageView">
<attr name="ratio" format="float"/>
</declare-styleable>
- 1
- 2
- 3
然後我們在自定義View中去獲取這個屬性:
public class MyImageView extends ImageView {
//寬高比,由我們自己設定
private float ratio;
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
//獲得屬性名稱和對應的值
// for (int i = 0; i < attrs.getAttributeCount() ; i++) {
// String name = attrs.getAttributeName(i);
// String value = attrs.getAttributeValue(i);
// System.out.println("====name: "+name+"value:"+value);
// }
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.MyImageView);
//根據屬性名稱獲取對應的值,屬性名稱的格式為類名_屬性名
ratio = typedArray.getFloat(R.styleable.MyImageView_ratio, 0.0f);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
//獲取寬度的模式和尺寸
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
//獲取高度的模式和尺寸
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
//寬確定,高不確定
if(widthMode == MeasureSpec.EXACTLY&&heightMode!=MeasureSpec.EXACTLY&&ratio!=0){
heightSize = (int) (widthSize*ratio+0.5f);//根據寬度和比例計算高度
heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
}else if(widthMode!=MeasureSpec.EXACTLY&&heightMode==MeasureSpec.EXACTLY&ratio!=0){
widthSize = (int) (heightSize/ratio+0.5f);
widthMeasureSpec = MeasureSpec.makeMeasureSpec(widthSize,MeasureSpec.EXACTLY);
}else{
throw new RuntimeException("無法設定寬高比");
}
//必須呼叫下面的兩個方法之一完成onMeasure方法的重寫,否則會報錯
// super.onMeasure(widthMeasureSpec,heightMeasureSpec);
setMeasuredDimension(widthMeasureSpec,heightMeasureSpec);
}
/**
* 設定寬高比
* @param ratio
*/
public void setRatio(float ratio){
this.ratio = ratio;
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
最後我們在佈局檔案中使用這個自定義的ImageView
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
android:gravity="center"
tools:context="com.example.hecun.testone.MainActivity">
<com.example.hecun.testone.MyImageView
android:id="@+id/imageview"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:src="@drawable/ym1"
custom:ratio="1"
android:scaleType="fitXY"
/>
</LinearLayout>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
我們在這裡設定了寬高比為1,我們來看看效果:
順便給出ratio為2和3時的效果圖