很多同行在开发中可能会遇到这样的问题,就是在加载图片的时候会出现图片变形的问题.其实这很可能就是你的图片宽高比和图片所在容器的宽高比不匹配造成的.比如说图片的宽为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. 注意ArrayAdapter的Add()方法

    ArrayAdapter类可以作为ListView等的适配器资源,并且可以动态向适配器中添加新的数据,这就是ArrayAdapter.Add()方法的作用.但是在使用该方法时如果出错,那就需要检查Ar ...

  2. Eclipse创建Android模拟器创建选项解释

  3. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

  4. Java多线程理解

    首先说一下进程和线程的区别 进程:是计算机运用程序实例,拥有独立的内存空间和数据(猜测内存堆应该是作用的进程上),一个进程包含多个子线程,不同进程相互独立: 线程:cpu执行的基本单位,拥有独立的寄存 ...

  5. Spring笔记--0907

    包含ioc和aop两大核心概念 aop----事务管理 spring框架运用的设计模式(查一下) ---------------------------------------Ioc(控制反转)和Di ...

  6. PHP, LDAPS and Apache

    要PHP可以连接到用self-signed certificate的ldaps服务器,需要在/etc/ldap.conf中添加一行: TLS_REQCERT     never 要PHP在Apache ...

  7. Oozie命令行常用命令汇总[转]

    Oozie命令行常用命令汇总 有时候脚本跑多了就不愿意在OozieWeb端去看脚本的运行情况了.还好Oozie提供了很多命令行命令.能通过命令行直接检索自己想看到的脚本信息.在这里简单进行一下总结.一 ...

  8. Software Testing hw2

    Fault的定义:可能导致系统或功能失效的异常条件(Abnormal condition that can cause an element or an item tofail.),可译为“故障”. ...

  9. rabbitmq集群安装

        在配置文件中配置集群没有成功,但是使用命令行成功了,以下是过程请参考.     场景:两台机器,一台是10.1.3.95 hostname为mq1,一台是10.1.3.96 hostname为 ...

  10. 为什么学习webdriver

    http://www.boobooke.com/goods-37.html