AndroidUI设计 之 图片浏览器
图片浏览器效果图 :
源码下载地址 :
-- CSDN : http://download.csdn.net/detail/han1202012/6875083
-- GitHub : https://github.com/han1202012/AndroidPictureViewer.git
一. 图片浏览器显示界面ImageView介绍
1. ImageView的上下继承结构
下面是API中的结构:
java.lang.Object | ||
↳ | android.view.View | |
android.widget.ImageView |
![]() |
![]() |
绘制成UML图 :
通过上面的分析 : ImageView有两个子类 ImageButton 和 QuickContactBadge, ImageButton还有一个子类是 ZoomButton;
2. XML文件属性
调整边界, 保持长宽比 :android:adjustViewBounds, setAdjustViewBounds(boolean), 是否调整自己的边界, 用来保持图片的长宽比例, 该属性与 android:maxHeight 和 android:maxWidth 属性一起使用才有效果, 单独使用没有效果;
设置最大宽度, 高度 :android:maxWidth(android:maxHeight), setMaxWidth(int)[setMaxHeight(int)], 该属性需要与android:adjustViewBounds属性一起使用,单独使用无效果;
-- 设置图片固定大小, 同时保持长宽比 : a. 设置android:adjustViewBounds 为 true; b. 设置最大宽度, 高度; c. 设置android:layout_width 与 android:layout_height 值为 warp_content;
裁剪保留空白 :android:cropToPadding, setCropToPadding(boolean), 是否裁剪, 用来保留ImageView的padding, 该属性与android:scrollY 属性一起使用的时候才有用, 单独使用没有效果; 即 在滚动的时候, 滚动到边界, 边界的padding空白是否显示;
填充方式 :android:scaleType, setScaleType(ImageView.ScaleType), 设置图片缩放类型以适配ImageView大小, 即填充方式;
可能的取值 : matrix, fitXY, fitStart, fitCenter, fitEnd, center, centerCrop, centerInside;
-- matrix : 方法中的常量值为 ImageView.ScaleType.MATRIX, 使用矩阵来进行绘图;
-- fitXY : 方法中的常量值为 ImageView.ScaleType.FIT_XY, 在x y 两个方向上缩放, 使图片完全填充整个ImageView 不按照长宽比例缩放;
-- fitStart : 方法中的常量值为 ImageView.ScaleType.FIT_START, 保持长宽比缩放, 直到该图片完全显示在ImageView中, 缩放完成之后该图片在左上角;
-- fitCenter : 方法中的常量值为 ImageView.ScaleType.FIT_CENTER, 保持长宽比缩放, 直到该图片完全显示在ImageView中, 缩放完成之后该图片位于中央;
-- fitEnd : 方法中的常量值为 ImageView.ScaleType.FIT_END, 保持长宽比缩放, 直到该图片完全显示在ImageView中, 缩放完成之后该图片位于右下角;
-- center : 方法中的常量值为 ImageView.ScaleType.CENTER, 将图片放在ImageView的中央, 不进行缩放;
-- centerCrop : 方法中的常量值为 ImageView.ScaleType.CENTER_CROP, 保持长宽比缩放, 使图片完全覆盖ImageView;
-- centerInside : 方法中的常量值为 ImageView.ScaleType.CENTER_INSIDE, 保持长宽比缩放, 是的ImageView完全显示图片;
实例 :
XML文件 :
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
- <ImageView
- android:id="@+id/im"
- android:background="#00FF00"
- android:layout_height="300dp"
- android:layout_width="300dp"
- android:src="@drawable/pic"
- <strong>android:scaleType</strong>="matrix"/>
- </LinearLayout>
修改其中的 android:scaleType属性值, 查看其中的差异 :
原图 :
android:scaleType 默认情况下 :
android:scaleType = "matrix" : 由下图可以看出, ImageView中的图片宽度与原图一样, 该属性不进行任何缩放,直接将图片放在左上角;
android:scaleType = "fixXY" : 长宽不按比例拉伸, 图片明显变形 :
android:scaleType = "fitStart" , 图片按比例缩放, 宽先达到边界, 图片位于上边; 如果高先达到边界, 图片位于左边;
android:scaleType = "fieCenter" ,长宽按照比例缩放, 宽度先达到边界, 上下有空白; 如果高度先达到边界, 那么左右有空白;
android:scaleType = "fitEnd" , 长宽等比例缩放, 宽度先达到边界, 位于下边; 如果高度先达到边界, 位于右边;
android:scaleType = "center" ,长宽不进行缩放, 图片的中心 与 ImageView 的中心重合;
android:scaleType = "centerCrop" ,长宽等比例缩放, 使图片完全覆盖ImageView, 图片中心与ImageView中心重合, 使图片最短的边能覆盖ImageView边界;
android:scaleType = "centerInside" ,长宽等比例缩放, 如果图片宽高小于等于ImageView宽高, 那么就按照原图大小显示; 如果图片大于ImageView, 那么按照等比例缩小直到能完全显示为止;
3. ImageView常用方法
设置图片 :
-- 设置位图 : setImageBitmap(bitmap), 为ImageView设置Bitmap位图显示;
-- 设置Drawable : setImageDrawable(drawable), 为ImageView设置Drawable显示;
-- 设置资源 : setImageResource(int), 为ImageView设置资源图片;
-- 设置路径 : setImageUri(uri), 为ImageView设置图片路径, 显示该路径的图片;
二. 图片浏览器操作介绍
1. 实现左右循环切换图片
图片数组 : 将图片放在数组中, ImageView显示数组中的图片;
当前显示图片下标索引 : 设置一个int值, 用来表示当前显示图片数组中的图片, 这个值不是int下标, 这个值设置很大设置成Integer.MAXVALUE / 2, 该值与图片数组的长度进行取模运算结果就是当前显示的图片数组下标值;
翻页操作 : 上一页操作就将当前显示索引自减1, 然后模上 图片数组大小; 下一页就将当前索引自增1, 然后模上 图片数组大小;
代码示例 :
- //设置一个很大的值, 保证前后翻页不会出现异常
- currentImage = Integer.MAX_VALUE / 2;
- //为了保证图片能够循环, 这里模运算是关键, 显示图片的下标始终是长度的模
- image_all.setImageResource(images[ ++currentImage % images.length ]);
- image_all.setImageResource(images[ --currentImage % images.length ]);
2. 透明度改变
设置当前透明度 : 设置一个当前透明度值, 初始值为255, 255是不透明, 0为完全透明;
透明度改变 : 当点击透明度增加按钮的时候, 透明度自增20, 如果结果透明度大于255, 那么改透明度强制设置为255; 当点击透明度见效按钮的时候, 透明度自减20, 当透明度小于0的时候, 透明度强制设置为0;
代码示例 :
- //透明度初始值
- alpha = 255;
- //透明度增加
- alpha += 20;
- if(alpha >= 255)
- alpha = 255;
- image_all.setAlpha(alpha);
- //透明度减小
- alpha -= 20;
- if(alpha <= 0)
- alpha = 0;
- image_all.setAlpha(alpha);
3. 图片的放大缩小
获取View组件宽高 : 在Activity普通方法中无法获取到view组件的准确值, 如果想要获取view组件的宽高, 可以在 onWindowFocusChanged()方法中获取;
计算每次自增自减的单位值 : 当按下缩放按钮的时候, 就对ImageView的宽高值进行自增自减单位值操作;
为ImageView设置宽高 : 即设置LayoutParams, 注意是LinearLayout.LayoutParams对象;
代码示例 :
获取宽高 :
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- // TODO Auto-generated method stub
- super.onWindowFocusChanged(hasFocus);
- //获取ImageView组件的宽高
- imageWidth = image_all.getWidth();
- imageHeight = image_all.getHeight();
- //计算每次自增自减的值
- addWidth = imageWidth / 5;
- addHeight = imageHeight / 5;
- }
缩放图片操作 :
- case R.id.big: //放大图片
- imageWidth += addWidth;
- imageHeight += addHeight;
- image_all.setLayoutParams(new LinearLayout.LayoutParams(imageWidth, imageHeight));
- break;
- case R.id.small: //缩小图片
- imageWidth -= addWidth;
- imageHeight -= addHeight;
- if(imageWidth <= 0 || imageHeight <=0){
- imageWidth += addWidth;
- imageHeight += addHeight;
- }
- image_all.setLayoutParams(new LinearLayout.LayoutParams(imageWidth, imageHeight));
- break;
4. 旋转图片操作
设置Matrix对象 : 该对象用来存放图像的旋转角度;
设置旋转角度 : matrix.setRotate(), 即可设置旋转角度;
创建Bitmap : 创建一个位图, 注意将设置了旋转角度的 matrix 设置上去;
源码示例 :
- matrix = new Matrix();
- //向左旋转进行的操作
- anglel += 45;
- matrix.setRotate(anglel);
- Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(images[currentImage % images.length])).getBitmap();
- bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, true);
- image_all.setImageBitmap(bitmap);
- //向右旋转进行的操作
- anglel -= 45;
- matrix.setRotate(anglel);
- Bitmap bitmap1 = ((BitmapDrawable) getResources().getDrawable(images[currentImage % images.length])).getBitmap();
- bitmap1 = Bitmap.createBitmap(bitmap1, 0, 0, bitmap1.getWidth(),bitmap1.getHeight(), matrix, true);
- image_all.setImageBitmap(bitmap1);
三. 图片浏览器源码
XML布局文件 :
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="@drawable/bg_im"
- android:orientation="vertical">
- <LinearLayout
- android:orientation="horizontal"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:padding="5dp"
- android:gravity="center">
- <Button
- android:id="@+id/alpha_plus"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="透明度+"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- <Button
- android:id="@+id/alpha_minus"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="透明度-"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- <Button
- android:id="@+id/prev_page"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="上一张"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- <Button
- android:id="@+id/next_page"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="下一张"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- </LinearLayout>
- <LinearLayout
- android:orientation="horizontal"
- android:layout_height="wrap_content"
- android:layout_width="fill_parent"
- android:padding="5dp"
- android:gravity="center">
- <Button
- android:id="@+id/big"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="放大"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- <Button
- android:id="@+id/small"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="缩小"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- <Button
- android:id="@+id/turn_left"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="左转"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- <Button
- android:id="@+id/turn_right"
- android:layout_height="fill_parent"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:text="右转"
- android:background="@drawable/bg_bt"
- android:onClick="onClick"/>
- </LinearLayout>
- <ImageView
- android:id="@+id/image_all"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:scaleType="fitCenter"
- android:src="@drawable/mary1"/>
- </LinearLayout>
Drawable资源 :
整个界面的背景 : 渐变的颜色
- <?xml version="1.0" encoding="utf-8"?>
- <shape xmlns:android="http://schemas.android.com/apk/res/android" >
- <gradient
- android:startColor="#A9F5A9"
- android:centerColor="#2EFE2E"
- android:endColor="#A9F5A9"
- android:type="linear"/>
- </shape>
按钮的背景 : 两个9patch图片, 按下的时候按钮背景会改变
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:state_pressed="true"
- android:drawable="@drawable/bt_focus"></item>
- <item android:state_pressed="false"
- android:drawable="@drawable/bt_normal"></item>
- </selector>
主Activity核心代码 :
- package shuliang.han.imageview_test;
- import android.app.Activity;
- import android.graphics.Bitmap;
- import android.graphics.Matrix;
- import android.graphics.drawable.BitmapDrawable;
- import android.os.Bundle;
- import android.view.View;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- public class MainActivity extends Activity {
- private int[] images; //图片资源id数组
- private int currentImage; //当前显示图片
- private int alpha; //透明度
- private Matrix matrix;
- private int anglel; //角度
- private int imageWidth;
- private int imageHeight;
- private int addWidth;
- private int addHeight;
- private ImageView image_all;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- init();
- }
- //初始化成员变量
- private void init() {
- images = new int[]{R.drawable.mary1, R.drawable.mary2};
- currentImage = Integer.MAX_VALUE / 2;
- alpha = 255;
- matrix = new Matrix();
- image_all = (ImageView) findViewById(R.id.image_all);
- image_all.setImageResource(images[currentImage % images.length]);
- }
- public void onClick(View view) {
- int id = view.getId();
- switch (id) {
- case R.id.alpha_plus: //增大透明度
- alpha += 20;
- if(alpha >= 255)
- alpha = 255;
- image_all.setAlpha(alpha);
- break;
- case R.id.alpha_minus: //减小透明度
- alpha -= 20;
- if(alpha <= 0)
- alpha = 0;
- image_all.setAlpha(alpha);
- break;
- case R.id.next_page: //显示下一张图片
- //为了保证图片能够循环, 这里模运算是关键, 显示图片的下标始终是长度的模
- image_all.setImageResource(images[ ++currentImage % images.length ]);
- break;
- case R.id.prev_page: //显示上一张图片
- image_all.setImageResource(images[ --currentImage % images.length ]);
- break;
- case R.id.big: //放大图片
- imageWidth += addWidth;
- imageHeight += addHeight;
- image_all.setLayoutParams(new LinearLayout.LayoutParams(imageWidth, imageHeight));
- break;
- case R.id.small: //缩小图片
- imageWidth -= addWidth;
- imageHeight -= addHeight;
- if(imageWidth <= 0 || imageHeight <=0){
- imageWidth += addWidth;
- imageHeight += addHeight;
- }
- image_all.setLayoutParams(new LinearLayout.LayoutParams(imageWidth, imageHeight));
- break;
- case R.id.turn_left: //向左旋转
- anglel += 45;
- matrix.setRotate(anglel);
- Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(images[currentImage % images.length])).getBitmap();
- bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, true);
- image_all.setImageBitmap(bitmap);
- break;
- case R.id.turn_right: //向右旋转
- anglel -= 45;
- matrix.setRotate(anglel);
- Bitmap bitmap1 = ((BitmapDrawable) getResources().getDrawable(images[currentImage % images.length])).getBitmap();
- bitmap1 = Bitmap.createBitmap(bitmap1, 0, 0, bitmap1.getWidth(),bitmap1.getHeight(), matrix, true);
- image_all.setImageBitmap(bitmap1);
- break;
- default:
- break;
- }
- }
- @Override
- public void onWindowFocusChanged(boolean hasFocus) {
- // TODO Auto-generated method stub
- super.onWindowFocusChanged(hasFocus);
- //获取ImageView组件的宽高
- imageWidth = image_all.getWidth();
- imageHeight = image_all.getHeight();
- //计算每次自增自减的值
- addWidth = imageWidth / 5;
- addHeight = imageHeight / 5;
- }
- }
四. ZoomButton 和 QuickContactBadge
示例效果图 :
下载地址 :
GitHub : https://github.com/han1202012/ZoomButton_QuickContactBadge.git
1. ZoomButton
ZoomButton按钮 : ZoomButton按钮提供放大 缩小两个按钮, 两个按钮;
ZoomControls按钮 : 该按钮会自动生成一组两个按钮, 两个按钮分别是放大和缩小;
按钮点击切换背景 : 设置selector资源, 设置两个item, 一个item的状态为按下时, 显示一个图片, 另一个item的状态为普通情况下, 显示另一个图片;
selector源码 :
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android" >
- <item android:state_pressed="true"
- android:drawable="@drawable/app3"></item>
- <item android:state_pressed="false"
- android:drawable="@drawable/app4"></item>
- </selector>
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="match_parent"
- android:orientation="vertical" >
- <ImageButton
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:background="@drawable/app2"/>
- <ImageButton
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"
- android:background="@drawable/bt_bg"/>
- <LinearLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:padding="10dp"
- android:layout_gravity="center_horizontal">
- <ZoomButton
- android:id="@+id/zoom_1"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:src="@android:drawable/btn_minus"/>
- <ZoomButton
- android:id="@+id/zoom_2"
- android:layout_height="wrap_content"
- android:layout_width="wrap_content"
- android:src="@android:drawable/btn_plus"/>
- </LinearLayout>
- <ZoomControls
- android:id="@+id/zoom_ctrl"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center_horizontal"/>
- </LinearLayout>
2. QuickContactBadge
本质 : QuickContactBadge 也是图片, 可以通过android:src 指定图片;
功能 : QuickContactBadge 可以关联手机通讯录中的联系人, 当点击图片的时候, 会弹出该联系人相关的界面;
-- 关联方法 :
--- 使用邮箱关联 : assignContactFromEmail(String address, boolean lazyLookup), 将图片关联到指定email联系人;
--- 使用号码关联 : assignContactFromPhone(String number, boolean lazyLookup), 将图片关联到指定电话联系人;
--- 使用Uri关联 : assignContactUri(Uri uri), 将图片关联到Uri对应的联系人;
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="match_parent"
- android:orientation="vertical" >
- <QuickContactBadge
- android:id="@+id/badge"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:src="@drawable/app5"/>
- </LinearLayout>
Activity代码 :
- package shuliang.han.zoombutton_quickcontactbadge;
- import android.app.Activity;
- import android.os.Bundle;
- import android.widget.QuickContactBadge;
- import shuliang.han.zoombutton_quickcontactbadge.R;
- public class QuickContactBadgeActivity extends Activity {
- private QuickContactBadge badge;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.quick_contact_badge);
- badge = (QuickContactBadge) findViewById(R.id.badge);
- badge.assignContactFromPhone("120", false);
- }
- }