1. 程式人生 > >Android 實現自定義寬高比的ImageView

Android 實現自定義寬高比的ImageView

前言

我們為什麼要用到寬高比固定的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時的效果圖 
這裡寫圖片描述 
這裡寫圖片描述