Android ImageView组件

参考资料:http://blog.csdn.net/shulianghan/article/details/18555131

http://www.cnblogs.com/plokmju/p/android__imageview.html


ImageView,直接继承自View类,用于显示任何Drawable对象。ImageView有两个子类 ImageButton 和 QuickContactBadge, ImageButton还有一个子类是 ZoomButton;


一、常用属性

1.调整边界,保持长宽比

同时满足下面三个条件:
android:adjustViewBounds:设置ImageView是否调整自己的边界来保持所显示图片的长宽比。
要与下面两个属性一起用才有效果。

android:maxHeight:设置ImageView的最大高度。
android:maxWidth:设置ImageView的最大宽度。

android:layout_width与android:layout_height都为wrap_content

2.裁剪保留空白:

android:cropToPadding,是否裁剪, 用来保留ImageView的padding。
与android:scrollY 属性一起使用的时候才有用,单独使用没有效果; 
即在滚动的时候, 滚动到边界, 边界的padding空白是否显示;

3.其他属性

android:scaleType:设置所显示的图片如何缩放或移动以适应ImageView的大小。
android:src:设置ImageView所显示的Drawable对象的ID。


android:scaleType的可选属性值:

matrix:使用矩阵进行缩放。
fitXY:横向、纵向独立缩放,以适应该ImageView。
fitStart:保持纵横比缩放图片,并且将图片放在ImageView的左上角。
fitCenter:保持纵横比缩放图片,缩放完成后将图片放在ImageView的中央。
fitEnd:保持纵横比缩放图片,缩放完成后将图片放在ImageView的右下角。
center:把图片放在ImageView的中央,但是不进行任何缩放。
centerCrop:保持纵横比缩放图片,以使图片能完全覆盖ImageView。
centerInside:保持纵横比缩放图片,以使得ImageView能完全显示该图片。

二、常用方法

1.缩放图片

View.setLayoutParams(new LinearLayout.LayoutParams(newWidth,newHeight))方法可以直接设定View下的所有控件的外观大小。同样适用于ImageView。

LayoutParmas params = new LinearLayout.LayoutParams(newWidth, newHeight);
params.gravity = Gravity.CENTER;
mImageView.setLayoutParams(params);

更好的方法是这样:
mImageView.getLayoutParmas().width = newWidth;
mImageView.getLayoutParmas().height = newHeight;
mImageView.requestLayout();

也可以用矩阵完成
// 计算缩放比例
float scaleWidth = ((float) newWidth) / width;
float scaleHeight = ((float) newHeight) / height;
// 缩放矩阵
Matrix matrix = new Matrix();
matrix.postScale(scaleWidth, scaleHeight);
// 生成新的图片
bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);

2.旋转图片

// 获取当前待旋转的图片
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), images[currentImage]);
// 设置旋转角度
matrix.setRotate(rotate);
// 生成旋转后的图片
bitmap = Bitmap.createBitmap(bitmap, 0, 0
         , bitmap.getWidth(), bitmap.getHeight(), matrix, true);

3.设置图片

currentImage = (currentImage + 1) % images.length;
imageView.setImageResource(images[currentImage]);

4.设置透明度

imageView.setAlpha(alpha);  



三、缩放与旋转图片


ImageView的旋转涉及Matrix类,它表示一个3x3的坐标变换矩阵,在这个矩阵内,进行变换、旋转操作,需要通过构造函数显式的初始化之后才可以使用。

Demo布局:

<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"> 
    
    <LinearLayout 
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center"
        >
        <Button 
            android:id="@+id/button_last"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="上一张"            
            />
        <Button 
            android:id="@+id/button_next"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="下一张"
            />
    </LinearLayout>
    
    <TextView 
        android:id="@+id/text_view_alpha"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="透明度:255"
        android:paddingTop="5dp"
        />

    <SeekBar
        android:id="@+id/seek_bar_alpha"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="255"
        android:progress="255"
         />
    
    <TextView 
        android:id="@+id/text_view_zoom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="缩放"
        android:paddingTop="5dp"
        />    
    <SeekBar 
        android:id="@+id/seek_bar_zoom"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="800"
        />
    
    <TextView 
        android:id="@+id/text_view_rotate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="旋转"
        />
    <SeekBar 
        android:id="@+id/seek_bar_rotate"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="360"
        />

     <ImageView 
         android:id="@+id/image_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_gravity="center"
         android:gravity="center"
         android:scaleType="fitCenter"
         android:src="@drawable/pic_1"
         />        

  
</LinearLayout>


MainActivity.java:

public class MainActivity extends Activity implements OnClickListener, OnSeekBarChangeListener{

    // 组件
    private Button btnLast, btnNext;
    private TextView tvAlpha, tvZoom, tvRotate;
    private SeekBar sbAlpha, sbZoom, sbRotate;
    private ImageView imageView;
    
    // 图片数组
    private int[] images;
    
    // 旋转矩阵
    private Matrix matrix;
    
    // 当前图片
    private int currentImage;

    // 初始图片大小
    // ImageView未绘制时getWidth()为0,此时用这个
    private int initWidth, initHeight;
    
    // 最小宽度
    private int minWidth = 50;
    
    // 图片长宽比
    private double currentImageRatio;
    
    // 图片缩放比例标记
    private boolean hasGetRatio = false;
    
    // 标示是否已经在ImageView的观察者中获取控件大小
    private boolean hasMeasured = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        // 初始化
        init();
    }
    
    /**
     * 在onCreate()中获取ImageView的初始宽度和高度
     */
    private void getImageViewSizeInit(){
        ViewTreeObserver vto = imageView.getViewTreeObserver();
        vto.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
            @Override
            public boolean onPreDraw() {
                if (!hasMeasured) {
                    // 获得初始宽高
                    initWidth = imageView.getMeasuredWidth();
                    initHeight = imageView.getMeasuredHeight();
                    // 将滑动条设置为对应位置
                    adjustZoomTvSb(initWidth, initHeight);
                    hasMeasured = true;
                }
                return true;
            }
        });
    }
    
    /*
     * 初始化
     */
    private void init(){
        btnLast = (Button) findViewById(R.id.button_last);
        btnNext = (Button) findViewById(R.id.button_next);
        tvAlpha = (TextView) findViewById(R.id.text_view_alpha);
        tvZoom = (TextView) findViewById(R.id.text_view_zoom);
        tvRotate = (TextView) findViewById(R.id.text_view_rotate);
        sbAlpha = (SeekBar) findViewById(R.id.seek_bar_alpha);
        sbZoom = (SeekBar) findViewById(R.id.seek_bar_zoom);
        sbRotate = (SeekBar) findViewById(R.id.seek_bar_rotate);
        imageView = (ImageView) findViewById(R.id.image_view);
        
        //添加事件监听器
        btnLast.setOnClickListener(this);
        btnNext.setOnClickListener(this);
        sbAlpha.setOnSeekBarChangeListener(this);
        sbZoom.setOnSeekBarChangeListener(this);
        sbRotate.setOnSeekBarChangeListener(this);
        
        // 给控制图片大小的SeekBar设置最大值为屏幕宽度
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        sbZoom.setMax(metrics.widthPixels - minWidth);
        
        // 用观察者在onCreate中获取组件属性
        getImageViewSizeInit();
        
        // 初始化旋转矩阵
        matrix = new Matrix();
        
        // 添加图片
        images = new int[]{R.drawable.pic_1, R.drawable.pic_2, R.drawable.pic_3};
        currentImage = 0;       
        
    }
    
    /**
     * 调整缩放滑动条的位置和TextView显示
     * TextView SeekBar
     */
    private void adjustZoomTvSb(int width, int height){
        sbZoom.setProgress(width);
        tvZoom.setText("缩放:宽度 " + width + " px,高度 " + height + " px");
    }
    
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.button_last: // 上一张 按钮
            currentImage--;
            if (currentImage < 0) {
                currentImage = currentImage + images.length;
            }
            break;
        case R.id.button_next: // 下一张 按钮
            currentImage = (currentImage + 1) % images.length;
            break;
        default:
            break;
        }
        // 设置图片
        imageView.setImageResource(images[currentImage]);
//        adjustZoomTvSb(imageView.getWidth(), imageView.getHeight());
        // 每张图片比例不一样,要重新测定
        hasGetRatio = false;
    }

    @Override
    public void onProgressChanged(SeekBar seekBar, int progress,
            boolean fromUser) {
        switch (seekBar.getId()) {
        // 透明度滑块
        case R.id.seek_bar_alpha:
            int alpha = progress;
            // 设置透明度
            imageView.setAlpha(alpha);        
            tvAlpha.setText("透明度:" + alpha);
            break;
        // 图片大小滑块
        case R.id.seek_bar_zoom:
            // 如果还没绘制图片,则不用计算和改变大小
            if (hasMeasured) {
                if (!hasGetRatio) {
                    currentImageRatio = 1.0 *imageView.getHeight() / imageView.getWidth();
                    Log.v("调试", "缩放比例为:" + currentImageRatio);
                    hasGetRatio = true;
                }
                int newWidth = progress + minWidth;
                int newHeight = (int) (newWidth * currentImageRatio);
                // 改变ImageView的大小
                imageView.getLayoutParams().width = newWidth;
                imageView.getLayoutParams().height = newHeight;
                imageView.requestLayout();
//                // 也可以用如下方法
//                LayoutParams params = new LinearLayout.LayoutParams(newWidth, newHeight);
//                params.gravity = Gravity.CENTER;
                tvZoom.setText("缩放:宽度 " + newWidth + " px,高度 " + newHeight + " px");
            }
            break;
        // 图片旋转滑块
        case R.id.seek_bar_rotate:
            // 获取当前待旋转的图片
            Bitmap bitmap = BitmapFactory.decodeResource(getResources(), images[currentImage]);
            // 设置旋转角度
            matrix.setRotate(progress);
            // 生成旋转后的图片
            bitmap = Bitmap.createBitmap(bitmap, 0, 0
                    , bitmap.getWidth(), bitmap.getHeight(), matrix, true);
            // 绑定到图片控件上
            imageView.setImageBitmap(bitmap);
            tvRotate.setText("旋转:" + progress + "°");
        default:
            break;
        }
    }

    @Override
    public void onStartTrackingTouch(SeekBar seekBar) {
    }

    @Override
    public void onStopTrackingTouch(SeekBar seekBar) {
    }

}

效果图:



四、从互联网获取图片

Android4.0之后不能在主线程中访问网络,必须另开一条线程访问。在子线程中,无法直接操作UI控件的属性。解决方案就是,通过Thread类,进行多线程访问网络,再通过Handler类,进行消息传递。

Handler类的主要作用有两个:
在新启动的线程中发送消息。
在主线程中获取、处理消息。

为了让主线程能接受并处理新启动的线程发送的消息,Android通过回调的方式来实现,开发人员只需要重写Handler类中处理消息的方法,handleMessage(Message)即可,其中Message封装了发送过来的消息。

Handler包含如下方法,用于实现发送和处理消息:
void handleMessage(Message msg):处理消息的方法,用于被重写。
final boolean hasMessage(int what):检查消息队列中是否包含what属性为指定值的消息。
sendEmptyMessage(int what):立即发送空消息。
final boolean sendEmptyMessageDelayed(int what,long delayMillis):指定delayMillis毫秒之后发送空消息。
final boolean sendMessage(Message msg):立即发送消息。
final boolean sendMessageDelayed(Message msg,long delayMillis):指定delayMillis毫秒之后发送消息。

Message封装了线程中传递的消息,对于一般的数据,Message提供了getData()和setData()方法来获取与设置数据,其中操作的数据是一个Bundle对象,这个Bundle对象提供一系列的getXxx()和setXxx()方法用于传递基本数据类型。
在Bundle中提供了两个方法,专门用来传递对象的,但是这两个方法也有相应的限制,需要实现特定的接口,当然,一些Android自带的类,其实已经实现了这两个接口中的某一个,可以直接使用。方法如下:
putParcelable(String key,Parcelable value):需要传递的对象类实现Parcelable接口。
pubSerializable(String key,Serializable value):需要传递的对象类实现Serializable接口。

还有另外一种方式在Message中传递对象,那就是使用Message自带的obj属性传值,它是一个Object类型,所以可以传递任意类型的对象,Message自带的有如下几个属性:
int arg1:参数一,用于传递不复杂的数据,复杂数据使用setData()传递。
int arg2:参数二,用于传递不复杂的数据,复杂数据使用setData()传递。
Object obj:传递一个任意的对象。
int what:定义的消息码,一般用于确定消息的来源。

Demo:
必须声明联网权限:
<uses-permission android:name="android.permission.INTERNET"/>

activity_main.xml:
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"> 
    
    <Button 
        android:id="@+id/button_download"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="下载网络图片"
        />
    
    <TextView 
        android:id="@+id/textview_prompt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        />
    
    <ImageView 
        android:id="@+id/imageview_show"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:scaleType="fitCenter"
        />
  
</LinearLayout>

MainActivity.java:
package com.example.test;

import java.io.InputStream;
import java.util.Random;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

public class MainActivity extends Activity implements OnClickListener{

    private Button btnDownload;
    private TextView tvPrompt;
    private ImageView ivShow;
    private Handler handler;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(R.layout.activity_main);
        
        btnDownload = (Button) findViewById(R.id.button_download);
        tvPrompt = (TextView) findViewById(R.id.textview_prompt);
        ivShow = (ImageView) findViewById(R.id.imageview_show);
        
        // 定义一个handler,用于接收消息
        handler = new Handler() {
            @Override
            public void handleMessage(Message msg) {
                Bitmap bitmap = null;
                // 通过消息码确定使用什么方式传递图片信息
                if (msg.what == 0) {
                    bitmap = (Bitmap) msg.obj;
                    tvPrompt.setText("使用obj传递数据");
                } else {
                    Bundle bundle = msg.getData();
                    bitmap = (Bitmap) bundle.get("bitmap");
                    tvPrompt.setText("使用Bundle传递数据");
                }
                // 设置图片到ImageView中
                ivShow.setImageBitmap(bitmap);
            }
        };
        
        btnDownload.setOnClickListener(this);
    }
    
        
    // 事件监听器
    @Override
    public void onClick(View v) {
        // 清空之前获取的数据
        tvPrompt.setText("");
        ivShow.setImageBitmap(null);
        // 定义一个线程类
        new Thread() {
            @Override
            public void run() {
                try{
                    // 获取网络图片
                    InputStream input = HttpUtils.getImageViewInputStream();
                    Bitmap bitmap = BitmapFactory.decodeStream(input);
                    // 调整宽度为屏幕宽度
                    bitmap = zoomBitmap(bitmap);
                    Message msg = new Message();
                    Random rand = new Random();
                    int randNum = rand.nextInt(10);
                    // 通过随机数选择传递图片的方式
                    if (randNum / 2 == 0) {
                        msg.what = 0;
                        msg.obj = bitmap;
                    } else {
                        Bundle bundle = new Bundle();
                        bundle.putParcelable("bitmap", bitmap);
                        msg.what = 1;
                        msg.setData(bundle);
                    }
                    // 发送消息
                    handler.sendMessage(msg);
                } catch (Exception e) {
                    
                }
            }
        }.start();
    }
    
 // 调整图片大小
    private Bitmap zoomBitmap(Bitmap bitmap){
        int width = bitmap.getWidth();
        int height = bitmap.getHeight();
        // 设置想要的大小,已知自己手机宽度为1080
        int newWidth = 1080;
        int newHeight = newWidth * height / width;
        // 计算缩放比例
        float scaleWidth = ((float) newWidth) / width;
        float scaleHeight = ((float) newHeight) / height;
        // 缩放矩阵
        Matrix matrix = new Matrix();
        matrix.postScale(scaleWidth, scaleHeight);
        // 返回新的图片
        return Bitmap.createBitmap(bitmap, 0, 0, width, height, matrix, true);
        
    }

}


效果如图:

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值