Android自定义属性实现图片屏幕的适配

屏幕适配是个经常遇到的问题,下面,我以如何将一张图片不拉伸,不裁剪的方式来完整的展示一张图片;
一、首先来看一下最初的状态:
我首先在主界面放了一张图片:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.fuyunwang.myapplication8.MainActivity">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:src="@mipmap/pic"
        />
</RelativeLayout>

效果如下:
这里写图片描述
可以看到,这是原图的大小,当我把图片直接塞给ImageView的时候,ImageView会自己做一个屏幕的适配,保证原图展示,所以这里会出现留白。
然而当我们设置ImageView的缩放模式为:android:scaleType="centerCrop" 的时候,图片不会出现留白但会出现明显的拉伸,导致效果变差:
这里写图片描述
地球变成了椭圆这肯定是不合理的
当然,还有保证图片不拉伸能以较好的效果展示,也就是模式为:

android:scaleType="centerCrop"

这个时候图片就会裁剪一部分然后显示,这时就丢失了一部分像素,具体的我就不贴图了,用过这个模式的大家都知道
好,那么现在我们如果想既要图片不拉伸,不留白,又不能出现裁剪的情况,保证图片完整的展示我们应该怎么做呢?
这里我以自定义属性的方式来实现上述要求
二、自定义MyImageLayout实现:
我们的思路很简单,就是实现图片的完美展示。这里用到的原理就是控件的宽高比例要与图片的宽高比例相一致,保证图片的完整展示.
首先得到原始图片的宽高比例,这里图片是1024*1024的,所以比例就是1:1(我找的这张图比较特殊,如果是一张长方形的图片效果更明显);
我们得到的长/宽的比率就是1

1.好,首先,我先在工程下创建一个类,MyImageLayout继承自FrameLayout,实现三个构造方法,
2.在values目录下创建attrs.xml文件,我这里自定义属性,因为只是实现适配,所以很简单:

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

3.在布局文件中使用属性:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:fuyunwang="http://schemas.android.com/apk/res-auto"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.fuyunwang.myapplication8.MainActivity">

    <com.fuyunwang.myapplication8.view.MyImageLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        fuyunwang:ratio="1.0"
        >
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:src="@mipmap/pic"
            />
    </com.fuyunwang.myapplication8.view.MyImageLayout>
</RelativeLayout>

4.在代码中得到宽高:

package com.fuyunwang.myapplication8.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.text.LoginFilter;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.FrameLayout;

import com.fuyunwang.myapplication8.R;

/**
 * Created by BeautifulSoup on 2016/12/18.
 */

public class MyImageLayout extends FrameLayout {
    float ratio=-1;
    public MyImageLayout(Context context) {
        super(context);
    }

    public MyImageLayout(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray typedArray=context.obtainStyledAttributes(attrs,R.styleable.MyImageLayout);
        ratio=typedArray.getFloat(R.styleable.MyImageLayout_ratio,-1);
        typedArray.recycle();
        Log.i("MyImageLayout: ", String.valueOf(ratio));
    }

    public MyImageLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

    }

    /**
     * OnMeasure方法实现重绘
     * @param widthMeasureSpec
     * @param heightMeasureSpec
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.i("MyImageLayout: ", String.valueOf(ratio));
        int width=MeasureSpec.getSize(widthMeasureSpec);
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);
        int height=MeasureSpec.getSize(heightMeasureSpec);
        int heightMode=MeasureSpec.getMode(heightMeasureSpec);
        //高度已经指定,宽度不确定,这个时候需要指定控件的绝对大小
        if(widthMode==MeasureSpec.EXACTLY&&heightMode!=MeasureSpec.EXACTLY&&ratio>0){
            //得到真实的宽度值
            int realWidth=width-getPaddingLeft()-getPaddingRight();
            int realHeight= (int) (realWidth/ratio+0.5f);
            //动态计算控件的宽高
            height=realHeight+getPaddingTop()+getPaddingBottom();

            heightMeasureSpec=MeasureSpec.makeMeasureSpec(height,MeasureSpec.EXACTLY);
        }

        super.onMeasure(widthMeasureSpec,heightMeasureSpec);
    }
}

此时的效果就完成了

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值