Android自定View——可以设置宽高比例的ImageView

如果对android自定义view还不太属性,可以查看我之前写的文章《 Android自定义View——基础知识篇

在App中展示最多的除了文字外,应该就是图片了。为了适配屏幕,有些情况下在布局时图片大小是不固定的,如下图:


中间是三张图片(ImageView),图片左右两边的间距都已经确定,但图片大小不确定。可以看出三张图片占用剩下的空间,这里可以用LinearLayout布局,设置中间三个ImageView的layout_weight=1。但这里还有一个需求,图片不能被变形,必须按比例缩放。因为不确定ImageView的大小,所以无法事先根据比例设置宽高。

我们可以自定义一个ImageView,根据图片的比例自动确定ImageView的大小,或者指定宽高的比例。效果图如下:



我们可以看出,ImageView根据屏幕的大小不同自动适配。下面是关键代码:

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. public class RatioImageView extends ImageView {  
  2.   
  3.     /* 优先级从大到小: 
  4.      mIsWidthFitDrawableSizeRatio mIsHeightFitDrawableSizeRatio 
  5.      mWidthRatio mHeightRatio 
  6.      即如果设置了mIsWidthFitDrawableSizeRatio为true,则优先级较低的三个值不生效 */  
  7.   
  8.     private float mDrawableSizeRatio = -1f; // src图片(前景图)的宽高比例  
  9.     // 根据前景图宽高比例测量View,防止图片缩放变形  
  10.     private boolean mIsWidthFitDrawableSizeRatio; // 宽度是否根据src图片(前景图)的比例来测量(高度已知)  
  11.     private boolean mIsHeightFitDrawableSizeRatio; // 高度是否根据src图片(前景图)的比例来测量(宽度已知)  
  12.     // 宽高比例  
  13.     private float mWidthRatio = -1// 宽度 = 高度*mWidthRatio  
  14.     private float mHeightRatio = -1// 高度 = 宽度*mHeightRatio  
  15.   
  16.     public RatioImageView(Context context) {  
  17.         this(context, null);  
  18.     }  
  19.   
  20.     public RatioImageView(Context context, AttributeSet attrs) {  
  21.         this(context, attrs, 0);  
  22.     }  
  23.   
  24.     public RatioImageView(Context context, AttributeSet attrs, int defStyleAttr) {  
  25.         super(context, attrs, defStyleAttr); // 虽然此处会调用setImageDrawable,但此时成员变量还未被正确初始化  
  26.         init(attrs);  
  27.         // 一定要有此代码  
  28.         if (getDrawable() != null) {  
  29.             mDrawableSizeRatio = 1f * getDrawable().getIntrinsicWidth()  
  30.                     / getDrawable().getIntrinsicHeight();  
  31.         }  
  32.     }  
  33.   
  34.     /** 
  35.      * 初始化变量 
  36.      */  
  37.     private void init(AttributeSet attrs) {  
  38.   
  39.         TypedArray a = getContext().obtainStyledAttributes(attrs,  
  40.                 R.styleable.RatioImageView);  
  41.         mIsWidthFitDrawableSizeRatio = a.getBoolean(R.styleable.RatioImageView_is_width_fix_drawable_size_ratio,  
  42.                 mIsWidthFitDrawableSizeRatio);  
  43.         mIsHeightFitDrawableSizeRatio = a.getBoolean(R.styleable.RatioImageView_is_height_fix_drawable_size_ratio,  
  44.                 mIsHeightFitDrawableSizeRatio);  
  45.         mHeightRatio = a.getFloat(  
  46.                 R.styleable.RatioImageView_height_to_width_ratio, mHeightRatio);  
  47.         mWidthRatio = a.getFloat(  
  48.                 R.styleable.RatioImageView_width_to_height_ratio, mWidthRatio);  
  49.         a.recycle();  
  50.     }  
  51.   
  52.     @Override  
  53.     public void setImageResource(int resId) {  
  54.         super.setImageResource(resId);  
  55.         if (getDrawable() != null) {  
  56.             mDrawableSizeRatio = 1f * getDrawable().getIntrinsicWidth()  
  57.                     / getDrawable().getIntrinsicHeight();  
  58.             if (mDrawableSizeRatio > 0  
  59.                     && (mIsWidthFitDrawableSizeRatio || mIsHeightFitDrawableSizeRatio)) {  
  60.                 requestLayout();  
  61.             }  
  62.         }  
  63.     }  
  64.   
  65.     @Override  
  66.     public void setImageDrawable(Drawable drawable) {  
  67.         super.setImageDrawable(drawable);  
  68.         if (getDrawable() != null) {  
  69.             mDrawableSizeRatio = 1f * getDrawable().getIntrinsicWidth()  
  70.                     / getDrawable().getIntrinsicHeight();  
  71.             if (mDrawableSizeRatio > 0  
  72.                     && (mIsWidthFitDrawableSizeRatio || mIsHeightFitDrawableSizeRatio)) {  
  73.                 requestLayout();  
  74.             }  
  75.         }  
  76.     }  
  77.   
  78.     @Override  
  79.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  80.         // 优先级从大到小:  
  81.         // mIsWidthFitDrawableSizeRatio mIsHeightFitDrawableSizeRatio  
  82.         // mWidthRatio mHeightRatio  
  83.         if (mDrawableSizeRatio > 0) {  
  84.             // 根据前景图宽高比例来测量view的大小  
  85.             if (mIsWidthFitDrawableSizeRatio) {  
  86.                 mWidthRatio = mDrawableSizeRatio;  
  87.             } else if (mIsHeightFitDrawableSizeRatio) {  
  88.                 mHeightRatio = 1 / mDrawableSizeRatio;  
  89.             }  
  90.         }  
  91.   
  92.         if (mHeightRatio > 0 && mWidthRatio > 0) {  
  93.             throw new RuntimeException("高度和宽度不能同时设置百分比!!");  
  94.         }  
  95.   
  96.         if (mWidthRatio > 0) { // 高度已知,根据比例,设置宽度  
  97.             int height = MeasureSpec.getSize(heightMeasureSpec);  
  98.             super.onMeasure(MeasureSpec.makeMeasureSpec(  
  99.                             (int) (height * mWidthRatio), MeasureSpec.EXACTLY),  
  100.                     MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));  
  101.         } else if (mHeightRatio > 0) { // 宽度已知,根据比例,设置高度  
  102.             int width = MeasureSpec.getSize(widthMeasureSpec);  
  103.             super.onMeasure(MeasureSpec.makeMeasureSpec(width,  
  104.                     MeasureSpec.EXACTLY), MeasureSpec.makeMeasureSpec(  
  105.                     (int) (width * mHeightRatio), MeasureSpec.EXACTLY));  
  106.         } else { // 系统默认测量  
  107.             super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  108.         }  
  109.     }  
  110.   
  111. }  


res/values/attrs.xml
[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources>  
  3.     <declare-styleable name="RatioImageView">  
  4.   
  5.         <!--宽度是否根据src图片的比例来测量(高度已知)-->  
  6.         <attr name="is_width_fix_drawable_size_ratio" format="boolean"/>  
  7.         <!--高度是否根据src图片的比例来测量(宽度已知)-->  
  8.         <attr name="is_height_fix_drawable_size_ratio" format="boolean"/>  
  9.   
  10.         <!-- 高度设置,参考宽度,如0.5 , 表示 高度=宽度×0.5 -->  
  11.         <attr name="height_to_width_ratio" format="float"/>  
  12.         <!-- 宽度设置,参考高度,如0.5 , 表示 宽度=高度×0.5 -->  
  13.         <attr name="width_to_height_ratio" format="float"/>  
  14.   
  15.     </declare-styleable>  
  16. </resources>  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值