前言

  这篇博客聊一聊在Android下ImageView的使用,在此篇博客中,会讲解到ImageView的一些属性的使用,以及ImageView展示图片的放大、缩小、旋转等操作。最后再讲解一下Android4.0项目中最常用的一个功能,从网络获取图片的示例。本文所有讲解均会附上示例代码,并在最后提供源码下载。

ImageView

  ImageView,图像视图,直接继承自View类,它的主要功能是用于显示图片,实际上它不仅仅可以用来显示图片,任何Drawable对象都可以使用ImageView来显示。ImageView可以适用于任何布局中,并且Android为其提供了缩放和着色的一些操作。

  ImageView的一些常用属性,并且这些属性都有与之对应的getter、setter方法:

  • android:adjustViewBounds:设置ImageView是否调整自己的边界来保持所显示图片的长宽比。
  • android:maxHeight:设置ImageView的最大高度。
  • android:maxWidth:设置ImageView的最大宽度。
  • android:scaleType:设置所显示的图片如何缩放或移动以适应ImageView的大小。
  • android:src:设置ImageView所显示的Drawable对象的ID。

  对于android:scaleType属性,因为关于图像在ImageView中的显示效果,所以有如下属性值可以选择:

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

图片基本显示

  下面通过一个示例效果,来说明一下ImageView是如何显示图片的,再此示例中,需要使用到一个green.png的图片,需要放到Drawable文件夹下,关于Android的资源文件,以后再进行详解。

  布局代码:

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7 <TextView
8 android:layout_width="match_parent"
9 android:layout_height="wrap_content"
10 android:text="scaleType:center,未缩放,在ImageView的中心" />
11
12 <ImageView
13 android:id="@+id/imageview1"
14 android:layout_width="200dp"
15 android:layout_height="100dp"
16 android:background="#F00"
17 android:scaleType="center"
18 android:src="@drawable/green" />
19
20 <TextView
21 android:layout_width="match_parent"
22 android:layout_height="wrap_content"
23 android:text="scaleType:fitCenter,按比例缩放" />
24
25 <ImageView
26 android:id="@+id/imageview2"
27 android:layout_width="300dp"
28 android:layout_height="200dp"
29 android:background="#FFF"
30 android:padding="10dp"
31 android:scaleType="fitCenter"
32 android:src="@drawable/green" />
33
34 </LinearLayout>

  效果展示:

  

缩放与旋转图片

  因为ImageView继承自View,所以在代码中设置其大小,可以使用View.setLayoutParams(new LinearLayout.LayoutParams(newWidth,newHeight))方法,这个方法可以直接设定View下的所有控件的外观大小,所以这里也适用于ImageView。

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

  下面通过一个示例来说明一下图片的放大缩小与旋转的示例,在示例中会提供两个SeekBar,对于SeekBar如果不了解的话,可以参见我的另外一篇博客,Android—UI之Progress。这两个SeekBar一个设置ImageView显示图片的大小,另一个设置旋转的角度。对于图片大小,通过DisplayMetrics设置屏幕的宽度为图像的最大宽度,具体操作在注释中已经写明,这里不在累述。

  布局代码:

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7 <ImageView
8 android:id="@+id/imageview3"
9 android:layout_width="200dp"
10 android:layout_height="150dp"
11 android:scaleType="fitCenter"
12 android:src="@drawable/green" />
13
14 <TextView
15 android:id="@+id/tv1"
16 android:layout_width="match_parent"
17 android:layout_height="wrap_content"
18 android:layout_marginTop="10dp"
19 android:text="图像宽度:240 图像高度:150" />
20
21 <SeekBar
22 android:id="@+id/sbSize"
23 android:layout_width="200dp"
24 android:layout_height="wrap_content"
25 android:layout_marginTop="10dp"
26 android:max="240"
27 android:progress="120" />
28
29 <TextView
30 android:id="@+id/tv2"
31 android:layout_width="match_parent"
32 android:layout_height="wrap_content"
33 android:layout_marginTop="10dp"
34 android:text="0°" />
35
36 <SeekBar
37 android:id="@+id/sbRotate"
38 android:layout_width="200dp"
39 android:layout_height="wrap_content"
40 android:layout_marginTop="10dp"
41 android:max="360" />
42
43 </LinearLayout>

  实现代码:

 1 package com.bgxt.imageviewdemo;
2
3 import android.annotation.SuppressLint;
4 import android.app.Activity;
5 import android.graphics.Bitmap;
6 import android.graphics.BitmapFactory;
7 import android.graphics.Matrix;
8 import android.graphics.drawable.BitmapDrawable;
9 import android.os.Bundle;
10 import android.util.DisplayMetrics;
11
12 import android.widget.ImageView;
13 import android.widget.LinearLayout;
14 import android.widget.SeekBar;
15 import android.widget.SeekBar.OnSeekBarChangeListener;
16 import android.widget.TextView;
17
18 @SuppressLint("NewApi")
19 public class ChangeImageActivity extends Activity implements
20 OnSeekBarChangeListener {
21 private int minWidth = 80;
22 private ImageView imageView;
23 private TextView textview1, textview2;
24 Matrix matrix=new Matrix();
25
26 @Override
27 protected void onCreate(Bundle savedInstanceState) {
28 // TODO Auto-generated method stub
29 super.onCreate(savedInstanceState);
30 setContentView(R.layout.layout_changeimage);
31
32 imageView = (ImageView) findViewById(R.id.imageview3);
33 SeekBar seekbar1 = (SeekBar) findViewById(R.id.sbSize);
34 SeekBar seekbar2 = (SeekBar) findViewById(R.id.sbRotate);
35 textview1 = (TextView) findViewById(R.id.tv1);
36 textview2 = (TextView) findViewById(R.id.tv2);
37
38 //获取当前屏幕的尺寸,并设置图片放大的最大尺寸,不能超过屏幕尺寸
39 DisplayMetrics dm = new DisplayMetrics();
40 getWindowManager().getDefaultDisplay().getMetrics(dm);
41 seekbar1.setMax(dm.widthPixels - minWidth);
42
43 seekbar1.setOnSeekBarChangeListener(this);
44 seekbar2.setOnSeekBarChangeListener(this);
45 }
46
47 @Override
48 public void onProgressChanged(SeekBar seekBar, int progress,
49 boolean fromUser) {
50 if (seekBar.getId() == R.id.sbSize) {
51 //设置图片的大小
52 int newWidth=progress+minWidth;
53 int newHeight=(int)(newWidth*3/4);
54 imageView.setLayoutParams(new LinearLayout.LayoutParams(newWidth, newHeight));
55 textview1.setText("图像宽度:"+newWidth+"图像高度:"+newHeight);
56 } else if (seekBar.getId() == R.id.sbRotate){
57 //获取当前待旋转的图片
58 Bitmap bitmap=BitmapFactory.decodeResource(getResources(), R.drawable.green);
59 //设置旋转角度
60 matrix.setRotate(progress,30,60);
61 //通过待旋转的图片和角度生成新的图片
62 bitmap=Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
63 //绑定图片到控件上
64 imageView.setImageBitmap(bitmap);
65 textview2.setText(progress+"°");
66 }
67 }
68
69 @Override
70 public void onStartTrackingTouch(SeekBar seekBar) {
71 // TODO Auto-generated method stub
72
73 }
74
75 @Override
76 public void onStopTrackingTouch(SeekBar seekBar) {
77 // TODO Auto-generated method stub
78
79 }
80
81 }

  效果展示:

  

从互联网获取图片

  一个移动的平台开发,很多资源是不可能一直保存在本地的,更多实时性的东西,是需要直接通过网络及时获取的。这里通过一个从网上获取图片展示到ImageView的例子,来讲解一下这个功能的实现。

  在Android4.0之后,增加了一些新特性,也增加了一些限制。其中有一个限制就是不能在主线程中访问网络,必须另开一条线程访问。但是这里又存在另外一个问题,在子线程中,无法直接操作UI控件的属性。如果你们使用的开发平台是Android4.0之下,就不存在这个问题,直接在主线程中访问网络操作UI控件即可。

  我的解决方案就是,通过Thread类,进行多线程访问网络,再通过Handler类,进行消息传递。对于Thread类,是Java的知识,不再详细讲解,对于Handler类,这里简要说明一下。

  在Android平台下,不允许Activity新启动的线程访问该Activity里的界面UI控件,这样就会导致新启动的线程无法动态改变界面UI控件的属性值。所以就需要借助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:定义的消息码,一般用于确定消息的来源。

  下面这个示例,使用了两种方式获取传递消息,以一个随机数确定。在这个示例中,访问网络的代码会附上但是不会详解,如果对于Android中访问网络不熟悉的朋友,可以参见我另外一篇博客,Android--Http协议

  布局代码:

 1 <?xml version="1.0" encoding="utf-8"?>
2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 android:layout_width="match_parent"
4 android:layout_height="match_parent"
5 android:orientation="vertical" >
6
7
8 <Button android:id="@+id/btnInternet" android:layout_width="wrap_content"
9 android:layout_height="wrap_content" android:text="下载网络图片"/>
10 <TextView android:id="@+id/tbMsgType" android:layout_width="match_parent"
11 android:layout_height="wrap_content"/>
12 <ImageView android:id="@+id/ivInternet" android:layout_width="wrap_content"
13 android:layout_height="wrap_content"/>
14 </LinearLayout>

  实现代码:

 1 package com.bgxt.imageviewdemo;
2
3 import java.io.InputStream;
4 import java.net.HttpURLConnection;
5 import java.util.Random;
6
7 import com.bgxt.httputils.HttpUtils;
8
9 import android.app.Activity;
10 import android.graphics.Bitmap;
11 import android.graphics.BitmapFactory;
12 import android.os.Bundle;
13 import android.os.Handler;
14 import android.os.Message;
15 import android.view.View;
16 import android.widget.Button;
17 import android.widget.ImageView;
18 import android.widget.TextView;
19 import android.widget.Toast;
20
21 public class InternetImageActivity extends Activity {
22 private Button btnInternet;
23 private ImageView ivInternet;
24 private TextView tvMsgType;
25 private Handler handler;
26
27 @Override
28 protected void onCreate(Bundle savedInstanceState) {
29 // TODO Auto-generated method stub
30 super.onCreate(savedInstanceState);
31 setContentView(R.layout.activity_internetimage);
32
33 btnInternet = (Button) findViewById(R.id.btnInternet);
34 ivInternet = (ImageView) findViewById(R.id.ivInternet);
35 tvMsgType = (TextView) findViewById(R.id.tbMsgType);
36
37 // 定义一个handler,用于接收消息
38 handler = new Handler() {
39 @Override
40 public void handleMessage(Message msg) {
41 Bitmap bmp = null;
42 // 通过消息码确定使用什么方式传递图片信息
43 if (msg.what == 0) {
44 bmp = (Bitmap) msg.obj;
45 tvMsgType.setText("使用obj传递数据");
46 } else {
47 Bundle ble = msg.getData();
48 bmp = (Bitmap) ble.get("bmp");
49 tvMsgType.setText("使用Bundle传递数据");
50 }
51 // 设置图片到ImageView中
52 ivInternet.setImageBitmap(bmp);
53 }
54 };
55
56 btnInternet.setOnClickListener(new View.OnClickListener() {
57 @Override
58 public void onClick(View v) {
59 //清空之前获取的数据
60 tvMsgType.setText("");
61 ivInternet.setImageBitmap(null);
62 //定义一个线程类
63 new Thread() {
64 @Override
65 public void run() {
66 try {
67 //获取网络图片
68 InputStream inputStream = HttpUtils
69 .getImageViewInputStream();
70 Bitmap bitmap = BitmapFactory
71 .decodeStream(inputStream);
72 Message msg = new Message();
73 Random rd = new Random();
74 int ird = rd.nextInt(10);
75 //通过一个随机数,随机选择通过什么方式传递图片信息到消息中
76 if (ird / 2 == 0) {
77 msg.what = 0;
78 msg.obj = bitmap;
79 } else {
80 Bundle bun = new Bundle();
81 bun.putParcelable("bmp", bitmap);
82 msg.what = 1;
83 msg.setData(bun);
84 }
85 //发送消息
86 handler.sendMessage(msg);
87 } catch (Exception e) {
88
89 }
90 }
91 }.start();
92 }
93 });
94 }
95 }

  访问网络类,代码:

 1 package com.bgxt.httputils;
2
3 import java.io.IOException;
4 import java.io.InputStream;
5 import java.net.HttpURLConnection;
6 import java.net.URL;
7
8 public class HttpUtils {
9 private final static String URL_PATH = "http://ww4.sinaimg.cn/bmiddle/9e58dccejw1e6xow22oc6j20c80gyaav.jpg";
10
11 public HttpUtils() {
12 }
13
14 public static InputStream getImageViewInputStream() throws IOException {
15 InputStream inputStream = null;
16 URL url = new URL(URL_PATH);
17 if (url != null) {
18 HttpURLConnection httpURLConnection = (HttpURLConnection) url
19 .openConnection();
20 httpURLConnection.setConnectTimeout(3000);
21 httpURLConnection.setRequestMethod("GET");
22 httpURLConnection.setDoInput(true);
23 int response_code = httpURLConnection.getResponseCode();
24 if (response_code == 200) {
25 inputStream = httpURLConnection.getInputStream();
26 }
27 }
28 return inputStream;
29 }
30 }

  效果展示:

总结

  以上就讲解了ImageView的一些基本使用,对于Android项目而言,一般的用到更多的就是从网络获取图片的功能,所以这里着重讲解了一下。

  请支持原创,尊重原创,转载请注明出处。谢谢。

作者:承香墨影
更多内容,请阅读本人新书:《Android深入浅出》
欢迎转载,但还请尊重劳动果实,保留此段声明并注明原文链接。

(转)Android--UI之ImageView的更多相关文章

  1. Android UI系列-----ImageView的scaleType属性

    这篇随笔将会简单的记录下ImageView这个控件的一些使用方法,以及其最重要的一个属性: scaleType ImageView这个控件是用来显示图片用的,例如我们可以通过下面这段xml配置来声明显 ...

  2. Android UI 绘制过程浅析(五)自定义View

    前言 这已经是Android UI 绘制过程浅析系列文章的第五篇了,不出意外的话也是最后一篇.再次声明一下,这一系列文章,是我在拜读了csdn大牛郭霖的博客文章<带你一步步深入了解View> ...

  3. Android UI线程和非UI线程

    Android UI线程和非UI线程 UI线程及Android的单线程模型原则 当应用启动,系统会创建一个主线程(main thread). 这个主线程负责向UI组件分发事件(包括绘制事件),也是在这 ...

  4. Android UI组件----ListView列表控件详解

    [声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/3 ...

  5. 十二、Android UI开发专题(转)

    http://dev.10086.cn/cmdn/bbs/viewthread.php?tid=18736&page=1#pid89255Android UI开发专题(一) 之界面设计 近期很 ...

  6. Android UI基础教程 目录

    从csdn下载了这本英文版的书之后,又去京东搞了一个中文目录下来.对照着看. 话说,这本书绝对超值.有money的童鞋看完英文版记得去买中文版的~~ Android UI基础教程完整英文版 pdf+源 ...

  7. [转]Android UI:看看Google官方自定义带旋转动画的ImageView-----RotateImageView怎么写(附 图片淡入淡出效果)

    http://blog.csdn.net/yanzi1225627/article/details/22439119 众所周知,想要让ImageView旋转的话,可以用setRotation()让其围 ...

  8. shape和selector是Android UI设计中经常用到的

    shape和selector是Android UI设计中经常用到的,比如我们要自定义一个圆角Button,点击Button有些效果的变化,就要用到shape和selector.可以这样说,shape和 ...

  9. Android UI - 实现广告Banner旋转木马效果

    Android UI - 实现广告Banner旋转木马效果 前言 本篇博客要分享的一个效果是实现广告Banner轮播效果,这个效果也比較常见,一些视频类应用就常常有,就拿360影视大全来举例吧: 用红 ...

  10. 【转】【Android UI设计与开发】第07期:底部菜单栏(二)Fragment的详细介绍和使用方法

    原始地址:http://blog.csdn.net/yangyu20121224/article/category/1431917/1 由于TabActivity在Android4.0以后已经被完全弃 ...

随机推荐

  1. LeetCode OJ-- Spiral Matrix II

    https://oj.leetcode.com/problems/spiral-matrix-ii/ 螺旋矩阵,和题目一一样的思路,这个是产生n*n 矩阵. #include <iostream ...

  2. 如何获取MAC的进程数

    参考链接: https://www.cnblogs.com/watchdatalearn2012620/p/3182477.html https://segmentfault.com/q/101000 ...

  3. react状态

    组件的生命周期分成三个状态: Mounting:已插入真实 DOM Updating:正在被重新渲染 Unmounting:已移出真实 DOM React 为每个状态都提供了两种处理函数,will 函 ...

  4. JVM 常量池

    最近正好在研究这个问题,题主问题本身是有问题的,在JDK7中HotSpot的常量池是放在Java Heap中,并非题目中的native memory中.在JDK6中是放在Perm Space.题主可以 ...

  5. linux下kill某个应用

    linux命令行与桌面切换快捷键Ctr+Alt+F1,Ctr+Alt+F7 ps -e | grep abc sudo kill xyz

  6. HtmlEmail实现简单发送邮件

    一般发送邮件的话系统项目中可能会用到,像一些通知信息自动发送等,会用到发送邮件的情况,发送邮件有好多种,包括设置各种格式,添加图片附件等,当然今天我们先看一下怎么实现发送成功. 工欲善其事必先利其器, ...

  7. C# 根据生日获取年龄

    C# 根据生日获取年龄 根据生日计算出准确的年龄,不等于0时,返回的是岁,等于0时,返回的是天(以‘-’来区分) public static string GetAgeByBirth(string B ...

  8. Java中泛型的Class<Object>与Class<?>的区别(转)

    Object是一个具体的类名,而?是一个占位符号,表示任何类型,只要是SomeClass类或者子类就可以. List<Object>可以放任何类对象. List<? extends ...

  9. Oracle8i Internal Services

    http://d.hatena.ne.jp/yohei-a/20091017/1255791152 第1回 Oracle8i Internal Services 1人読書会 Oracle 読んだところ ...

  10. Lightoj 1088 - Points in Segments 【二分】

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1088 题意: 有一维的n个点和q条线段.询问每条线段上的点有多少个. 思路:寻 ...