很多同行在开发中可能会遇到这样的问题,就是在加载图片的时候会出现图片变形的问题.其实这很可能就是你的图片宽高比和图片所在容器的宽高比不匹配造成的.比如说图片的宽为200,高为100.宽高比就是2,那么这时候把它放在宽高比为1或者3的控件上就会分别出现变窄和变宽的问题.只有在容器宽高比为2的时候图片才会和原始显示效果一样.怎样解决这个问题呢?这个时候就可以创建一个能够自适应图片宽高比的父容器来包裹ImageView就可以了.在使用RatioLayout的时候要注意以下几点:

1)ImageView的宽高属性都要改成match_parent

2)要指定RatioLayout以宽还是高来进行适配

3)在attrs.xml中添加控件的两个属性:一个是宽高比,一个是适配标准.前者为float,后者为enum类型,分别制定width=0和height=1

4)创建一个类RatioLayout继承FrameLayout,重写两个构造方法以及onMeasure方法

具体代码如下:

I.RatioLayout.java

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.widget.FrameLayout; import com.yangtao.googleplay.R;
/**
* Created by 杨涛 on 2016/11/18.
* 版权所有 翻版必究
* 自定义的容器控件
* 可以实现的功能如下:
* 1.可以根据指定的宽高比和模式来让子控件动态适应屏幕
*/
public class RatioLayout extends FrameLayout { private float mRatio; private static final int RATIOMODE_WIDTH = 0; private static final int RATIOMODE_HEIGHT = 1; private int ratioMode = RATIOMODE_WIDTH; public RatioLayout(Context context) { this(context, null); } public RatioLayout(Context context, AttributeSet attrs) { super(context, attrs); TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RatioLayout); mRatio = typedArray.getFloat(R.styleable.RatioLayout_ratio, 1); ratioMode = typedArray.getInt(R.styleable.RatioLayout_ratioMode, RATIOMODE_WIDTH); typedArray.recycle(); } public void setRatio(float ratio) { mRatio = ratio; } public void setRatioMode(int ratioMode) { this.ratioMode = ratioMode; } /* 根据固定的宽计算高 宽是已经确定的 高需要根据ratio来确定 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); if (widthMode == MeasureSpec.EXACTLY && ratioMode == RATIOMODE_WIDTH) { int width = MeasureSpec.getSize(widthMeasureSpec); //拿到了控件的宽 int height = (int) ((width / mRatio) + .5f); setMeasuredDimension(width, height); setAndMeasureChilds(width, height); } else if (heightMode == MeasureSpec.EXACTLY && ratioMode == RATIOMODE_HEIGHT) { //如果高度已经确定的话 int height = MeasureSpec.getSize(heightMeasureSpec); //拿到了控件的宽 int width = (int) ((height * mRatio) + .5f); setMeasuredDimension(width, height); setAndMeasureChilds(width, height); } else { super.setMeasuredDimension(widthMeasureSpec, heightMeasureSpec); } } /** * 得到子控件应有的宽和高,然后调用方法测量子控件的宽和高 * @param width * @param height */ private void setAndMeasureChilds(int width, int height) { int childWidth = width - getPaddingLeft() - getPaddingRight(); int childHeight = height - getPaddingTop() - getPaddingBottom(); int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY); int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY); measureChildren(childWidthMeasureSpec, childHeightMeasureSpec); } }

II.attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="RatioLayout">
<attr name="ratio" format="float"></attr>
<attr name="ratioMode" format="enum">
<enum name="width" value="0"></enum>
<enum name="height" value="1"></enum>
</attr>
</declare-styleable>
</resources>

加载的过程中图片变形了? --教你自定义自动适配图片宽高比的RatioLayout的更多相关文章

  1. 动态加载JS过程中如何判断JS加载完成

    在正常的加载过程中,js文件的加载是同步的,也就是说在js加载的过程中,浏览器会阻塞接下来的内容的解析.这时候,动态加载便显得尤为重要了,由于它是异步加载,因此,它可以在后台自动下载,并不会妨碍其它内 ...

  2. 加载dll过程中assembly失败

    错误现象: 进行插件读取时出现错误:“尝试从一个网络位置加载程序集,在早期版本的 .NET Framework 中,这会导致对该程序集进行沙盒处理.此发行版的 .NET Framework 默认情况下 ...

  3. Sqoop import加载HBase过程中,遇到Permission denied: user=root, access=WRITE, inode="/user":hdfs:supergroup:drwxr-xr-x

    在执行hbase sqoop抽取的时候,遇到了一个错误,如下图: 在执行程序的过程中,遇到权限问题很正常,也容易让人防不胜防,有问题就想办法解决,这个是关键. 解决办法如下: 第一步:su hdfs, ...

  4. openlayers加载天地图过程中遇到跨域问题

    // 采用openlayers加载天地图 var layer = new ol.layer.Tile({ source: new ol.source.XYZ({ // crossOrigin: 'An ...

  5. log4j的学习和log4j在程序中使用的加载作用过程

    昨天进行代码评审的时候,大家都纠结在了日志信息应该如何输出上,其实我想大家应该一直都在使用log4j来对日志信息进行输出,但是未想应该有很大一部分人对log4j是不了解的,我遇到这个问题的时候也到网上 ...

  6. iOS图片加载到内存中占用内存情况

    我的测试结果: 图片占用内存   图片尺寸           .png文件大小 1MB              512*512          316KB 4MB              10 ...

  7. 把图片加载到BufferedImage中

    把图片加载到BufferedImage 中有什么作用呢?它就可以利用 ImageIO.write(image, "JPEG", response.getOutputStream() ...

  8. 利用“反射”动态加载R文件中的资源

    前几天做一个Android下面数据库相关的应用.用ListVIew展示表中数据的时候我希望能给表中每一条记录,加一个展示的图片.但是用数据库保存图片是比较难搞的.于是就把所需图片都保存到res下的dr ...

  9. 创建控制器的方法、控制器加载view过程、控制器view的生命周期、多控制器组合

    在介绍四大对象的那篇博客中,可以基本了解到程序启动的过程: main-->UIApplicationMain-->创建UIApplication的实例和app代理AppDelegate的实 ...

随机推荐

  1. mysql存储图片问题

    1. 借鉴http://blog.chinaunix.net/uid-7374279-id-4255927.html 字段名为blob,有四种类型 TinyBlob(255B).Blob(65k).M ...

  2. IOS的一些小技巧

    1.播放短声音 SystemSoundID shake_sound_male_id = ; NSString *thesoundFilePath = [[NSBundle mainBundle] pa ...

  3. getIdentifier()获取资源Id

    工作需要使用getIdentifier()方法可以方便的获各应用包下的指定资源ID.主要有两种方法:(1)方式一Resources resources = context.getResources() ...

  4. 《Python标准库》 目录

    目录 译者序序前言第1章 文本1.1 string—文本常量和模板1.1.1 函数1.1.2 模板1.1.3 高级模板1.2 textwrap—格式化文本段落1.2.1 示例数据1.2.2 填充段落1 ...

  5. velocity整合servlet

    目录结构点我下载工程代码俩实体类不用说了看CustomerVelocityServlet类 package com.velocity.servlet;import java.util.ArrayLis ...

  6. go json null字段的转换

    最近试了试go中对json null字段进行转换,代码如下: struct 转 json: package main import ( "encoding/json" " ...

  7. java servlet之过滤器1(解决jsp之间POST方式数据传递乱码)

    首先,看看没有解决乱码的效果,新建两个jsp页面(a.jsp跳转到b.jsp). <form action="b.jsp" method="post"&g ...

  8. ORACLE10g数据库字符集设置和客户端字符集设置不一致问题

    在家里自己电脑上又重新安装了Oracle 10g和PLSQL Developer,装完后启动PLSQL Developer,弹出如下错误信息: 解决方案: 在Windows运行命令行中输入regedi ...

  9. 图片下载缓存防止OOM

    一  ImageManager ImageMemoryCache(内存缓存).ImageFileCache(文件缓存)    关于Java中对象的软引用(SoftReference),如果一个对象具有 ...

  10. 【Win10 UWP】后台任务与动态磁贴

    动态磁贴(Live Tile)是WP系统的大亮点之一,一直以来受到广大用户的喜爱.这一讲主要研究如何在UWP应用里通过后台任务添加和使用动态磁贴功能. 从WP7到Win8,再到Win10 UWP,磁贴 ...