1,ImageView(图片视图)
1)概念
ImageView继承自View组件,它的主要功能是用于显示图片,且任何Drawable对象都可使用ImageView来显示。
Android中不仅可以将扩展名为.png,.jpg,.gif的普通图片作为图片资源,而且可以将扩展名为.9.png的9-Patch图片作为图片资源。扩展名为.png,.jpg,.gif的普通图片较为常见,他们通常是通过绘图软件完成的。而9-Patch图片是通过使用Android SDK中的提供的工具Draw 9-patch生成的。那为什么要使用9-Patch这种图片呢?原因是:与普通图片不同,使用9-Patch图片作为屏幕或按钮的背景时,当屏幕的尺寸或按钮的大小改变时,图片可自动缩放,达到不失真的效果。
2)属性
①
--scaleType
设置图片的填充方式,相关方法setScaleType(ImageView.ScaleType)
ImageView.ScaleType / android:scaleType值:
CENTER /center 按图片的原来size居中显示,当图片长/宽超过View的长/宽,则截取图片的居中部分显示
CENTER_CROP / centerCrop 按比例扩大图片的size居中显示,使得图片长(宽)等于或大于View的长(宽)
CENTER_INSIDE / centerInside 将图片的内容完整居中显示,通过按比例缩小或原来的size使得图片长/宽等于或小于View的长/宽
FIT_CENTER / fitCenter 把图片按比例扩大/缩小到View的宽度,居中显示
FIT_END / fitEnd 把图片按比例扩大/缩小到View的宽度,显示在View的下部分位置
FIT_START / fitStart 把图片按比例扩大/缩小到View的宽度,显示在View的上部分位置
FIT_XY / fitXY 把图片不按比例扩大/缩小到View的大小显示
MATRIX / matrix 用矩阵来绘制,动态缩小放大图片来显示。
ImageView
②
--adjustViewBounds
调整边框时是否保持可绘制对象的宽高比,相关方法setAdjustViewBounds(boolean)
--src
设置要显示的Drawable对象的ID
,相关方法setImageResource(int)
--android:maxHeight
设置ImageView的最大高度,相关方法setMaxHeight(int)
2,图片加载
1)大量图片加载慢
按需加载,不需要的释放。
必要时做一个存放图片地址的映射数组,这样图片删掉了也可以从数组里面取对应的路径。
2)加载大图片
android系统给图片分配的内存只有8M,当加载大量图片时往往会出现OOM。
①尽量不要使用setImageBitmap或setImageResource或BitmapFactory.decodeResource来设置一张大图
这些函数在完成decode后,最终都是通过java层的createBitmap来完成的,需要消耗更多内存,可以通过BitmapFactory.decodeStream方法,创建出一个bitmap,再将其设为ImageView的 source
②使用BitmapFactory.Options对图片进行压缩
InputStream is = this.getResources().openRawResource(R.drawable.pic1);
BitmapFactory.Options options=new BitmapFactory.Options();
options.inJustDecodeBounds = false;
options.inSampleSize = 10; //width,hight设为原来的十分一
Bitmap btp =BitmapFactory.decodeStream(is,null,options);
③运用Java软引用,进行图片缓存,将需要经常加载的图片放进缓存里,避免反复加载
及时销毁不再使用的Bitmap对象
if(!bmp.isRecycle() ){
bmp.recycle() //回收图片所占的内存
system.gc() //提醒系统及时回收
}
3)图片选择器
GitHub:ImagePicker
使用步骤:
①引入依赖。
public static final int REQUEST_CODE_SELECT = 100;
public static final int REQUEST_CODE_PREVIEW = 101;
private ArrayList<ImageItem> selImageList = new ArrayList<>(); //当前选择的所有图片
②初始化ImagePicker。
private void initImagePicker() {
ImagePicker imagePicker = ImagePicker.getInstance();
imagePicker.setImageLoader(new GlideImageLoader()); //设置图片加载器
imagePicker.setShowCamera(true); //显示拍照按钮
imagePicker.setCrop(true); //允许裁剪(单选才有效)
imagePicker.setSaveRectangle(true); //是否按矩形区域保存
imagePicker.setSelectLimit(maxImgCount); //选中数量限制
imagePicker.setStyle(CropImageView.Style.RECTANGLE); //裁剪框的形状
imagePicker.setFocusWidth(800); //裁剪框的宽度。单位像素(圆形自动取宽高最小值)
imagePicker.setFocusHeight(800); //裁剪框的高度。单位像素(圆形自动取宽高最小值)
imagePicker.setOutPutX(1000); //保存文件的宽度。单位像素
imagePicker.setOutPutY(1000); //保存文件的高度。单位像素
}
③跳转。
//打开选择,本次允许选择的数量(通过maxImgCount控制一次选择照片的数量)
ImagePicker.getInstance().setSelectLimit(maxImgCount);
Intent intent1 = new Intent(this, ImageGridActivity.class);
/* 如果需要进入选择的时候显示已经选中的图片,
* 详情请查看ImagePickerActivity
* */
startActivityForResult(intent1, REQUEST_CODE_SELECT);
④onActivityResult方法回调
if (resultCode == ImagePicker.RESULT_CODE_ITEMS) {//添加图片返回
if (data != null && requestCode == REQUEST_CODE_SELECT) {
images = (ArrayList<ImageItem>) data.getSerializableExtra(ImagePicker.EXTRA_RESULT_ITEMS);
if (images != null) {
selImageList.clear();
selImageList.addAll(images);
ImageItem imageItem = selImageList.get(0);//imageItem.path为地址
Glide.with(this)//context
.load(userImage)//uri
.placeholder(R.mipmap.icon_cover_default)//占位图(不可用于CircleImageView图片的加载)
.error(R.drawable.nmtittle)//错误图
.into(myTitleImage);//ImageView控件
}
}
} else if (resultCode == ImagePicker.RESULT_CODE_BACK) {//预览图片返回
if (data != null && requestCode == REQUEST_CODE_PREVIEW) {
images = (ArrayList<ImageItem>) data.getSerializableExtra(ImagePicker.EXTRA_IMAGE_ITEMS);
if (images != null) {
selImageList.clear();
selImageList.addAll(images);
ImageItem imageItem = selImageList.get(0); ImagePicker.getInstance().getImageLoader().displayImage(this, imageItem.path, IV_photo, 0, 0);//IV_photo为要显示图片的控件
}
}
}
4)background
①background属性
对于src,图片不会拉伸。
如果以background,图片会根据View的宽度进行拉伸,解决方案是:
如下xml文件:tv_background.xml,放于drawable文件夹中。
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/toolbar_bg"
android:tileMode="disabled" android:gravity="top" >
</bitmap>
可以之间被 android:background使用,且图片不会出现拉伸。
注意:此方案可以把大图片放小,但无法把小图片放大。笔者暂时没有找到可以把bitmap适配于大屏手机的办法。来个大大指教下!
②setBackgroundResource、setBackground比较
功能相同,区别在于效率。
对于使用频率比较高的,从xm读取资源相当于一次IO,可提前通过getResources()
存储,然后每次直接使用即可。
playBtn.setBackgroundResource(R.drawable.pause_selecor);
playBtn.setBackgroundDrawable(myContext.getResources().getDrawable(R.drawable.pause_selecor););
5)在不压缩的情况下加载高清大图
使用BitmapRegionDecoder
进行布局加载。
3,Bitmap的加载和Cache
4,Drawable
5,drawableLeft、drawableRight、drawableTop、drawableBottom
1)xml设置
android:drawablePadding="5dp"
android:drawableRight="@drawable/icon_new"
2)java设置
//void android.widget.TextView.setCompoundDrawables(Drawable left, Drawable top, Drawable right, Drawable bottom)
Drawable mDrawable = getResources().getDrawable(drawable);
mDrawable.setBounds(0, 0, mDrawable.getMinimumWidth(), mDrawable.getMinimumHeight());
btn_Left.setCompoundDrawables(mDrawable, null, null, null);
3)图片点击
①点击图片切换决定et_password显示的密码是明文还是密文。
@Override
public boolean onTouch(View v, MotionEvent event) {
switch (v.getId()) {
case R.id.act_login_et_password:
// et.getCompoundDrawables()得到一个长度为4的数组,分别表示左右上下四张图片
Drawable drawable = et_password.getCompoundDrawables()[2];
//如果右边没有图片,不再处理
if (drawable == null)
return false;
//如果不是按下事件,不再处理
if (event.getAction() != MotionEvent.ACTION_UP)
return false;
if (event.getX() > et_password.getWidth()
- et_password.getPaddingRight()
- drawable.getIntrinsicWidth()){
isChecked = !isChecked;
if(isChecked){
et_password.setInputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD);
}else{
et_password.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
}
}
break;
default:
break;
}
return false;
}
6,实践
1)图片分辨率
H 分辨率480*800
XH 分辨率1280*720
XXH 分辨率1920*1080
在Android studio 中,自定义图片放在drawable中,切图根据分辨率不同,放在mipmap文件夹中(可以自适应屏幕)。
2)屏幕分辨率自适应
①组件大小:权重(layout_weight)、具体像素(dip)
②图片:drawable-hdpi、.9.png图片
③AndroidManifest.xml
<supports-screens
android:largeScreens="true"
android:normalScreens="true"
android:anyDensity = "true"/>
android:anyDensity
值为true
,系统会依据屏幕密度,自动去找对应的文件夹。
如果drawable-hpdi中有高密度图片,其它两个文件夹中没有对应图片资源,那么系统会去加载drawable-hdpi中的资源。
3)Tab
①tab切换底部线条动画
方案:
TextView设置切换2种背景。
shape写的只有底部有横线的图形:
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="-2dp"
android:right="-2dp"
android:left="-2dp">
<shape>
<solid android:color="@android:color/transparent"/>
<stroke
android:width="1dp"
android:color="@color/red"/>
</shape>
</item>
</layer-list>