自定义控件:等比例显示控件RatioLayout
生活随笔
收集整理的這篇文章主要介紹了
自定义控件:等比例显示控件RatioLayout
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
我們經(jīng)常碰到服務器返回的圖片比例大小是一樣的,但是分辨力卻是不一樣的。這時候,就會遇到顯示效果的問題。例如,圖1和圖2都是寬高比例相等,但是分辨率大小不一樣的圖片,應該按照比例顯示,使用等比例顯示控件后,圖2的顯示效果如圖3所示,和圖1的顯示效果是一致的,解決了寬高比相等或接近但分辨率大小不一樣而造成的顯示效果不一致的問題
解決方法一
自定義控件,自定義ViewGroup繼承FrameLayout ,重寫onMeasure()方法,根據(jù)圖片寬高比例和獲取到圖片的寬度(圖片的寬度是具體值或者match_parent,match_parent寬度就是屏幕寬度)計算出圖片的高度,然后喚醒重新測量ImageView。沒有繼承ImageView而是FrameLayout ,是因為自定義ViewGroup更加通用,不僅可以用于ImageView的等比例顯示,還可以用于其他的控件(如Button)的等比例顯示
package com.google.widget.view;import android.content.Context; import android.content.res.TypedArray; import android.util.AttributeSet; import android.widget.FrameLayout;import com.google.widget.R;public class RatioLayout extends FrameLayout {private float mPicRatio;//圖片的寬高比public static final int RELATIVE_WIDTH = 0;//控件的寬度固定,根據(jù)比例求出高度public static final int RELATIVE_HEIGHT = 1;//控件的高度固定,根據(jù)比例求出寬度private int mRelative = RELATIVE_WIDTH;public RatioLayout(Context context) {this(context, null);}public RatioLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public RatioLayout(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);initView(context, attrs);}private void initView(Context context, AttributeSet attrs) {TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.RatioLayout);for (int i = 0; i < array.getIndexCount(); i++) {switch (i) {case R.styleable.RatioLayout_ratio:mPicRatio = array.getFloat(i, 2.43f);break;case R.styleable.RatioLayout_relative:mRelative = array.getInt(i, 0);break;}}array.recycle();}public void setPicRatio(float picRatio) {mPicRatio = picRatio;}public void setRelative(int relative) {mRelative = relative;}@Overrideprotected 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);int childWidth = widthSize - getPaddingLeft() - getPaddingRight();int childHeight = heightSize - getPaddingBottom() - getPaddingTop();if (widthMode == MeasureSpec.EXACTLY && mPicRatio != 0 && mRelative == RELATIVE_WIDTH) {//修正高度的值childHeight = (int) (childWidth / mPicRatio + 0.5f);} else if (heightMode == MeasureSpec.EXACTLY && mPicRatio != 0 && mRelative ==RELATIVE_HEIGHT) {//修正寬度的值childWidth = (int) (childHeight * mPicRatio + 0.5f);}int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth, MeasureSpec.EXACTLY);int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight, MeasureSpec.EXACTLY);measureChildren(childWidthMeasureSpec, childHeightMeasureSpec);setMeasuredDimension(childWidth + getPaddingLeft() + getPaddingRight(), childHeight +getPaddingBottom() + getPaddingTop());/* widthMeasureSpec = MeasureSpec.makeMeasureSpec(childWidth + getPaddingLeft() +getPaddingRight(), MeasureSpec.EXACTLY);heightMeasureSpec = MeasureSpec.makeMeasureSpec(childHeight + getPaddingBottom() +getPaddingTop(), MeasureSpec.EXACTLY);super.measure(widthMeasureSpec, heightMeasureSpec);*/} } <?xml version="1.0" encoding="utf-8"?> <ScrollView xmlns:android="http://schemas.android.com/apk/res/android"xmlns:google="http://schemas.android.com/apk/res-auto"android:layout_width="match_parent"android:layout_height="match_parent"><LinearLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_margin="10dp"android:orientation="vertical"><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:text="分辨率:444x183,寬高比2.426"android:textSize="20sp"/><ImageView android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginBottom="15dp"android:background="#4887EE"android:scaleType="fitXY"android:src="@mipmap/recommend_05"/><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:text="分辨率:828x341,寬高比2.428"android:textSize="20sp"/><ImageView android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#4887EE"android:scaleType="fitXY"android:src="@mipmap/recommend_32"/><TextView android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_marginTop="15dp"android:text="按比例顯示"android:textSize="20sp"/><com.google.widget.view.RatioLayout android:layout_width="match_parent"android:layout_height="wrap_content"android:background="#4887EE"google:ratio="2.43"><ImageView android:layout_width="match_parent"android:layout_height="match_parent"android:src="@mipmap/recommend_32"/></com.google.widget.view.RatioLayout></LinearLayout> </ScrollView>解決方法二
設置圖片請求監(jiān)聽,拿到圖片的實際寬度后,根據(jù)寬高比計算出ImageView的高度,然后通過setLayoutParams()重新設置ImageView的參數(shù)
public class ImageUtils {/*** 自適應寬度加載圖片。保持圖片的長寬比例不變,通過修改imageView的高度來完全顯示圖片。* Note: ImageView android:layout_width="match_parent"*/public static void loadIntoUseFitWidth(Context context, final String imageUrl, int errorImageId, final ImageView imageView) {Glide.with(context).load(imageUrl).diskCacheStrategy(DiskCacheStrategy.SOURCE).listener(new RequestListener<String, GlideDrawable>() {@Overridepublic boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {return false;}@Overridepublic boolean onResourceReady(final GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {if (imageView == null) {return false;}imageView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {@Overridepublic void onGlobalLayout() {setLayoutParams(resource, imageView);imageView.getViewTreeObserver().removeGlobalOnLayoutListener(this);}});return false;}}).placeholder(errorImageId).error(errorImageId).into(imageView);}private static void setLayoutParams(GlideDrawable resource, ImageView imageView) {if (imageView.getScaleType() != ImageView.ScaleType.FIT_XY) {imageView.setScaleType(ImageView.ScaleType.FIT_XY);}ViewGroup.LayoutParams params = imageView.getLayoutParams();// 獲取容器實際存放圖片的寬度int vw = imageView.getWidth() - imageView.getPaddingLeft() - imageView.getPaddingRight();// 計算出容器實際存放圖片寬度與圖片資源寬度的比例float scale = (float) vw / (float) resource.getIntrinsicWidth();// 依據(jù)比例算出容器實際存放圖片高度值int vh = Math.round(resource.getIntrinsicHeight() * scale);// 計算容器的高度params.height = vh + imageView.getPaddingTop() + imageView.getPaddingBottom();imageView.setLayoutParams(params);}}總結(jié)
以上是生活随笔為你收集整理的自定义控件:等比例显示控件RatioLayout的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 自定义View:测量measure,布局
- 下一篇: 一个程序员的血泪史