参考资料: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;
android:adjustViewBounds:设置ImageView是否调整自己的边界来保持所显示图片的长宽比。 要与下面两个属性一起用才有效果。 android:maxHeight:设置ImageView的最大高度。 android:maxWidth:设置ImageView的最大宽度。 android:layout_width与android:layout_height都为wrap_content
android:cropToPadding,是否裁剪, 用来保留ImageView的padding。 与android:scrollY 属性一起使用的时候才有用,单独使用没有效果; 即在滚动的时候, 滚动到边界, 边界的padding空白是否显示;
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能完全显示该图片。
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);
// 获取当前待旋转的图片 Bitmap bitmap = BitmapFactory.decodeResource(getResources(), images[currentImage]); // 设置旋转角度 matrix.setRotate(rotate); // 生成旋转后的图片 bitmap = Bitmap.createBitmap(bitmap, 0, 0 , bitmap.getWidth(), bitmap.getHeight(), matrix, true);
currentImage = (currentImage + 1) % images.length; imageView.setImageResource(images[currentImage]);
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) { } }
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毫秒之后发送消息。
putParcelable(String key,Parcelable value):需要传递的对象类实现Parcelable接口。 pubSerializable(String key,Serializable value):需要传递的对象类实现Serializable接口。
int arg1:参数一,用于传递不复杂的数据,复杂数据使用setData()传递。 int arg2:参数二,用于传递不复杂的数据,复杂数据使用setData()传递。 Object obj:传递一个任意的对象。 int what:定义的消息码,一般用于确定消息的来源。
<uses-permission android:name="android.permission.INTERNET"/>
<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>
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); } }