Android:FullImageView 自定义等比缩放的铺满控件显示的ImageView

  • 何谓铺满控件的显示:也就是说,一个ImageView控件里面,全部是图片,没有空白部分。
  • 适用范围:加载晓得ImageView,比如,作为AbsListView的一个Item的图标。
  • 如我们所知:Android 系统提供的ImageView控件,通过设置属性:android:scaleType="fitXY"就可以让图片铺满控件显示了。但是,在我们实际开发中,应该很少有人会去使用这个属性,因为这样做就让图片变形了。
  • OK,既然Android系统没有给我提供这样方便的显示方式,那么,我们就去自定义一个ImageView以满足我们的需求。
  • 代码不是很多,里面注释也是比较详细的,就不先解释了。
  • 自定义ImageView的代码:

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Matrix;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.ImageView;

/**
 * 自动让图片铺满控件显示的ImageView<br/>
 * 何谓铺满控件:就是图片等比缩放。然后占满控件。多余的部分会加载在控件之外,也就是看不见的地方
 */
public class FullImage extends ImageView implements OnGlobalLayoutListener {

    private static final boolean DEBUG = true;
    private boolean once;
    private Matrix matrix;

    public FullImage(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FullImage(Context context) {
        this(context, null);
    }

    public FullImage(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        // init
        init();
    }

    private void init() {
        once = true;
        matrix = new Matrix();
        // setScaleType(ScaleType.MATRIX);// 这一步不加,以上全是白费
    }

    @Override
    protected void onAttachedToWindow() {
        // 注册 OnGlobalLayoutListener 的监听
        ViewTreeObserver observer = getViewTreeObserver();
        observer.addOnGlobalLayoutListener(this);
        super.onAttachedToWindow();
    }

    @SuppressLint("NewApi")
    @Override
    protected void onDetachedFromWindow() {
        // 反注册 OnGlobalLayoutListener 的监听
        getViewTreeObserver().removeOnGlobalLayoutListener(this);
        super.onDetachedFromWindow();
    }

    @Override
    public void onGlobalLayout() {
        if (once) {// 初始化操作,只需要搞一次即可。但是onGlobalLayout 会被多次调用

            // 1. 获取当前控件,加载之后的(this)的宽高
            int width = this.getWidth();
            int height = this.getHeight();

            // 2. 获取显示的图片,以及宽高
            Drawable drawable = this.getDrawable();// 获取显示的图片
            if (drawable == null)
                return;
            if (DEBUG) {
                System.out.println("drawable: " + drawable);
            }
            int dw = drawable.getIntrinsicWidth();// 获取图片的宽高
            int dh = drawable.getIntrinsicHeight();// 获取图片的宽高
            if (DEBUG) {
                System.out.println("dw: " + dw);
                System.out.println("dh: " + dh);
                System.out.println("width: " + width);
                System.out.println("height: " + height);
            }
            // 5.不仅要缩放,还要让图片居中(图片中心点和控件中心点重合),也就是平移
            int dx = Math.round(width * 1.0f / 2 - dw * 1.0f / 2);// x方向:向右移动:控件宽度的一半-图片宽度的一般
            int dy = Math.round(height * 1.0f / 2 - dh * 1.0f / 2);// y方法:向下移动:控件高度的一半-图片高度的一半
            // ___TODO:一定要先平移再进行缩放拆走
            matrix.postTranslate(dx, dy);// 这个OK

            // 3. 根据控件宽高一级图片宽高,设置缩放比例
            float scale = 1.0f;
            // case 1:图片宽度>控件宽度,高度<控件高度
            if (dw > width && dh < height) {// 如果要铺满控件,且等比缩放,则
                /** // scale = width * 1.0f / dw;// <1,缩小的*/
                scale = height * 1.0f / dh;// >1,放大
                System.out.println("case 1:" + scale);
            }
            // case 2:图片宽度<控件宽度,高度>控件高度
            if (dw < width && dh > height) {// 如果要完全显示图片,且等比缩放,则
                /**  // scale = height / dh;// <1,缩小的*/
                scale = width * 1.0f / dw;// >1,放大
                System.out.println("case 2:" + scale);
            }

            // case 3:图片宽度>控件宽度,高度>控件高度
            if (dw > width && dh > height) {// 如果要铺满控件,且等比缩放,则
                scale = Math.max(width * 1.0f / dw, height* 1.0f / dh);// <1,缩小的
                System.out.println("case 3:" + scale);
            }
            // case 4:图片宽度<控件宽度,高度<控件高度
            if (dw < width && dh < height) {// 如果要完全显示图片,且等比缩放,则
                scale = Math.max(width * 1.0f / dw, height* 1.0f / dh);// >1,放大的
                System.out.println("case 4:" + scale);
            }
            // ------图片与控件的尺寸比较,只有以上4种情况
            // 4. 根据缩放比例进行缩放
            if (DEBUG) {
                System.out.println("scale: " + scale);
            }
            matrix.postScale(scale, scale, width / 2, height / 2);

            this.setImageMatrix(matrix);
            once = false;
        }
    }
}
  • 需要注意的是:我在代码中是先进行平移,再进行缩放的。是因为,如果先缩放,再平移,可能会出现一些不正常的效果。

  • 使用该控件的代码:

 <com.xxx.yyyy.FullImage
        android:id="@+id/imageView1"
        android:layout_width="240dp"
        android:layout_height="240dp"
        android:background="@android:color/darker_gray"
        android:padding="2dp"
        android:src="@drawable/install" />

只要,在我们需要使用这种显示方式的地方,将xnl中ImageView改成我们自定义的FullImage即可。不需要做任何的自定义属性,自定义命名空间等等。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,以下是一个自定义Preference布局的示例代码,包含一个Button按钮并实现了点击事件: 首先,在res/layout目录下创建一个名为custom_preference.xml的布局文件,代码如下: ```xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="?android:attr/listPreferredItemHeight" android:gravity="center_vertical" android:paddingEnd="?android:attr/scrollbarSize"> <!-- Preference icon --> <ImageView android:id="@+android:id/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="16dp" android:layout_marginEnd="10dp" android:layout_gravity="center_vertical" android:contentDescription="@null" /> <!-- Preference title and summary --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+android:id/title" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceLargeInverse" android:textColor="?android:attr/textColorPrimaryInverse" android:singleLine="true" android:ellipsize="end" android:textStyle="bold" android:paddingTop="5dp" /> <TextView android:id="@+android:id/summary" android:layout_width="match_parent" android:layout_height="wrap_content" android:textAppearance="?android:attr/textAppearanceSmall" android:textColor="?android:attr/textColorSecondaryInverse" android:maxLines="3" android:ellipsize="end" android:paddingBottom="5dp" /> </LinearLayout> <!-- Custom button --> <Button android:id="@+id/custom_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Custom Button" android:layout_marginEnd="10dp" android:onClick="onButtonClicked" /> </LinearLayout> ``` 其中,我们添加了一个Button按钮,设置了其ID为custom_button,并在其中添加了一个onClick属性,指向一个名为onButtonClicked的方法。 接着,在我们的Preference类中,重写onBindViewHolder方法,以及实现onButtonClicked方法,完整代码如下: ```java public class CustomPreference extends Preference { public CustomPreference(Context context, AttributeSet attrs) { super(context, attrs); setLayoutResource(R.layout.custom_preference); } @Override public void onBindViewHolder(PreferenceViewHolder holder) { super.onBindViewHolder(holder); // Get the custom button view Button button = (Button) holder.findViewById(R.id.custom_button); // Set the click listener for the button button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // Do something when the button is clicked Toast.makeText(getContext(), "Custom button clicked", Toast.LENGTH_SHORT).show(); } }); } // Custom button click handler public void onButtonClicked(View view) { // Do something when the button is clicked Toast.makeText(getContext(), "Custom button clicked", Toast.LENGTH_SHORT).show(); } } ``` 在该类中,我们重写了onBindViewHolder方法,通过ViewHolder获取了我们自定义布局中的Button,并设置了其点击事件。同时,我们还实现了一个名为onButtonClicked的方法,用于处理Button的点击事件。 最后,在我们的PreferenceActivity或PreferenceFragment中,添加我们自定义的Preference: ```xml <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceCategory android:title="Custom Preference Category"> <com.example.myapplication.CustomPreference android:key="custom_preference" android:title="Custom Preference" android:summary="This is a custom preference with a button" /> </PreferenceCategory> </PreferenceScreen> ``` 这样就完成了一个自定义Preference布局,并添加了一个Button按钮并实现了点击事件的示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值