• 自定义控件的方式适配图片,以及里面的一些技巧


    转载本专栏每一篇博客请注明转载出处地址,尊重原创。此博客转载链接地址:小杨的博客  http://blog.csdn.net/qq_32059827/article/details/52718489


    开题前先给出一种几乎所有人都经常见的问题,如下:

    布局代码

    <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content""
            android:orientation="vertical" >
    
            <ImageView
                android:src="@drawable/recommend_56"
                android:id="@+id/iv_list_item_subject_icon"
                android:layout_width="match_parent"
                android:layout_height="150dp"/>
    
        </LinearLayout>

    IDE渲染效果图(无需运行程序也可以看出):


    问题:图片没办法填充布局,看蓝色渲染效果就能看出。

    到这里,相信很多人都遇到此类事情,我想让图片整个填充我的布局,他却偏偏无法填充,是那么的难看。那么大多人,都是这么解决问题的——

    在imageView里面加一行代码:android:scaleType="fitXY"。运行效果:

    正好填充完毕,而且看起来感觉还不错。

    但是,这样其实是有问题的,如果我把图片的高度设置的高一些,问题就很明显了。例如,我修改为高度修改为200dp。运行效果:

    可以看到,都教授和女神身子都被拉长了相信把这个放到一款APP里,用户对于二位的粉丝而言,开发者要遭骂名了。

    如果非要在布局文件中做这种适配,建议用android:scaleType="centerCrop",这个属性不会对图片做拉伸,他原来是对图片中心开始,按照一定的比例裁剪,保留裁剪的部分。

    因为不去做拉伸,效果肯定比上边拉伸效果好很多。运行看看效果:


    看!图片没被拉伸!!但是,但是这个时候估计都教授粉丝火气比上边还大,这尼玛连人都看不到了!呵呵,你把图片高度设置小一点就好了,比如设置150dp,效果肯定很好。

    android:layout_height="150dp"运行:

    虽然说,女神的耳朵被剪走了,但是图片应该是上边情况最好的情景了。


    那么,我们肯定会想,到底有没有好的办法,让图片既可以不被拉伸,也不所示图片的内容吗?回答是肯定的!那就是今天的主题——使用自定义控件方式,解决图片适配。

    思路:自定义一个控件,控件按照图片的比例来确定自己的宽高,控件确定了宽高,让Imageview匹配这个自定义控件。这样按照比例来放置的图片就可以解决上边的问题。

    按照比例来确定布局高度的自定义控件。

    首先,自定义一个RatioLayout继承自FrameLayout。那么到底是多大的比例?通过自定属性的方式把这个比例值传递给我们自定义的控件里面。

    然后配置针对这个控件的自定义属性文件,里面的代码如下:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
        <declare-styleable name="RatioLayout">
            <attr name="ratio" format="float" />
        </declare-styleable>
    
    </resources>

    然后计算图片的比例。宽/高。这个图片的比例结果等于2.43

    那么布局中就这么写:

    <com.itydl.googlepaly.ui.view.RatioLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content" 
                itydl:ratio="2.43">
    
                <ImageView
                    android:id="@+id/iv_list_item_subject_icon"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:scaleType="centerCrop"
                    android:src="@drawable/recommend_15" />
            </com.itydl.googlepaly.ui.view.RatioLayout>

    (提示:记得在根布局加入自定义的命名空间)

    这个歌时候,就能在自定义控件的代码中拿到这个自定义的属性值了。接下来,具体的自定义控件时测量方法,以及一些详细的diamante解释如下:

    public class RatioLayout extends FrameLayout {
    	private float ratio;
    	public RatioLayout(Context context, AttributeSet attrs, int defStyle) {
    		super(context, attrs, defStyle);
    	}
    
    	public RatioLayout(Context context, AttributeSet attrs) {
    		super(context, attrs);
    		// “高端”手法获取属性:
    		// 获取自定义控件下的属性集合。如果你的属性很多的话,返回的这个集合就对应有多大
    		TypedArray typedArray = context.obtainStyledAttributes(attrs,
    				R.styleable.RatioLayout);//表示我从attrs属性集合里面,拿到了名字叫RatioLayout的属性
    		// 根据属性id获取属性值, 方式:
    		// R.styleable.名称_属性。参数一:系统生成的id=自定义控件名_属性名;第二个参数:在属性文件中的位置是第几个
    		ratio = typedArray.getFloat(R.styleabut_ratio, 0);
    		// 使用此方式拿属性必须回收TypedArray, 以释放内存le.RatioLayo
    		typedArray.recycle();
    	}
    
    	public RatioLayout(Context context) {
    		super(context);
    	}
    	
    	/**
    	 * 当前控件测量自己的宽高时,调用此方法
    	 */
    	// 要不要绘制控件的大小?
    	@Override
    	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    		
    		int widthMode = MeasureSpec.getMode(widthMeasureSpec);//获取宽度模式
    		int heightMode = MeasureSpec.getMode(heightMeasureSpec);//获取高度模式
    
    		//控件的宽高,并非图片的宽高
    		int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    		int heightSize = MeasureSpec.getSize(heightMeasureSpec);
    
    		// MeasureSpec.EXACTLY 确定值, 比如把宽高值写死dp,类似match_parent
    		// MeasureSpec.AT_MOST 至多, 能撑多大就多大, 类似wrap_content
    		// MeasureSpec.UNSPECIFIED 未指定大小
    
    		//按比例计算图片高度的前提是,宽度模式是确定的,即是MeasureSpec.AT_MOST,高度是不确定的。这两个条件少一个,都没有下面重新按照比例计算的必要了。
    		if (widthMode == MeasureSpec.EXACTLY//ratio要大于零、宽度确定、高度不确定才有必要计算高度值
    				&& heightMode != MeasureSpec.EXACTLY && ratio > 0) {
    			// 1. 根据布局宽度推算图片宽度
    			int imageWidth = widthSize - getPaddingLeft() - getPaddingRight();//【在布局文件中如果控件设置了padding的话图片小于控件宽度,不设置则图片宽与控件一样】
    			// 2. 根据图片宽度和宽高比,推算图片高度
    			int imageHeight = (int) (imageWidth / ratio+ 0.5f);//ratio是通过宽/高计算出来的
    			// 3. 根据图片高度, 推算控件(布局)最新高度
    			heightSize = imageHeight + getPaddingTop() + getPaddingBottom();//如果设置了padding就大于图片高度,如果没加,则相等
    			// 4. 重新定义高度模式。根据布局高度以及高度模式, 推算heightMeasureSpec
    			heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize,
    					MeasureSpec.EXACTLY);
    		}
    
    		//根据最新的高度宽度去测量
    		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    	}
    
    
    }
    


    这个时候,通过渲染是看不出来,可以直接运行一下看看是否达到了惊人的效果:


    可以看到,这是最好的展示效果。都教授还是那个都教授,女神也都展示了出来。

    到此,通过自定义控件适配图片就完毕了。再说一下里面的“小技巧”,就是另一种“高端”方式获取属性值。过程如下:

    // “高端”手法获取属性:
    		// 获取自定义控件下的属性集合。如果你的属性很多的话,返回的这个集合就对应有多大
    		TypedArray typedArray = context.obtainStyledAttributes(attrs,
    				R.styleable.RatioLayout);
    		// 根据属性id获取属性值, 方式:
    		// R.styleable.名称_属性。参数一:系统生成的id=自定义控件名_属性名;第二个参数:在属性文件中的位置是第几个
    		ratio = typedArray.getFloat(R.styleable.RatioLayout_ratio, 0);
    		// 使用此方式拿属性必须回收TypedArray, 以释放内存
    		typedArray.recycle();

    当自定义控件的属性很多的时候,这种方式就比较前卫一点了。

    所有知识都介绍完了,欢迎关注本博客,不定期推送文章哦~~


  • 相关阅读:
    css3 让一个图片翻转示例代码
    万能清除法
    str_replace 字符串匹配替换 explode 拆分字符串成数组 implode 数组 为字符串 list($month, $day, $year) = split ('[/.-]', $date);
    历年沪深A股、香港H股票数据导入和实时数据更新展示 ---转载
    CSS3生成音频波纹效果加载中动画
    jQuery中Ajax快捷方法之$.getScript()
    jQuery中Ajax快捷方法之$.get()
    ajax 关于IP地址查询的API
    php 拒绝用户输入非法字符
    PHP 字符串函数是 PHP 核心的组成部分。
  • 原文地址:https://www.cnblogs.com/wanghang/p/6299574.html
Copyright © 2020-2023  润新知