1. Bitmap位图
<!-- 对应于代码中的对象时BitmapDrawable -->
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/ic_launcher"
android:antialias="true" //抗锯齿
android:tileMode="mirror"
//repeat:使图片平铺显示,mirror:使用图片又有镜像又有平铺显示,clamp:复制边缘的颜色,disabled:为默认选项
android:filter="true" //位图过滤
android:dither="true" //启用或禁用抖动的位图
android:gravity="center" //设置图片的绘制位置 >
</bitmap>
2.selector背景选择器
使用:1.在ListView中配置android:listSelector="@drawable/list_item_bg"
2.在listview的item中添加属性android:background=“@drawable/list_item_bg"
3.代码中使用 Drawable drawable = getResources().getDrawable(R.drawable.list_item_bg);
ListView.setSelector(drawable);android:cacheColorHint="@android:color/transparent"
<?xml version="1.0" encoding="utf-8" ?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 默认时的背景图片 -->
<item android:drawable="@drawable/pic1" />
<!-- 没有焦点时的背景图片 -->
<item android:state_window_focused="false" android:drawable="@drawable/pic1" />
<!-- 非触摸模式下获得焦点并单击时的背景图片 -->
<item android:state_focused="true" android:state_pressed="true" android:drawable= "@drawable/pic2" />
<!-- 触摸模式下单击时的背景图片 -->
<item android:state_focused="false" android:state_pressed="true" android:drawable="@drawable/pic3" />
<!--选中时的图片背景 -->
<item android:state_selected="true" android:drawable="@drawable/pic4" />
<!--获得焦点时的图片背景 -->
<item android:state_focused="true" android:drawable="@drawable/pic5" />
</selector>
3.shape控件显示属性
<shape android:shape="rectangle"
xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 实心,就是填充的意思 -->
<solid
android:color="#ffeaeaea"/>
<!-- 渐变,android:angle是渐变角度,渐变默认的模式为android:type="linear",即线性渐变,
可以指定渐变为径向渐变,android:type="radial",径向渐变需要指定半径android:gradientRadius="50"-->
<gradient
android:startColor="#ffeaeaea"
android:endColor="#ffeaeaea"
android:angle="270.0"
android:type="linear"
android:centerY="0.5" />
<padding
android:left="7.0dip"
android:top="7.0dip"
android:right="7.0dip"
android:bottom="7.0dip" />
<!-- 圆角,android:radius为角的弧度,值越大角越圆 -->
<corners
android:radius="6.0dip" />
<!-- 描边,把描边弄成虚线的形式,设置方式为:android:dashWidth="5dp" 横线宽度 android:dashGap="3dp" 隔开的距离 -->
<stroke
android:color="#ffeaeaea"/>
</shape>
4.读取本地图片转为Bitmap
public class FileToBitmap {
public static Bitmap getBitmapFromFile(File dst, int width, int height) {
if (null != dst && dst.exists()) {
BitmapFactory.Options opts = null;
if (width > 0 && height > 0) {
opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(dst.getPath(), opts);
final int minSideLength = Math.min(width, height);
opts.inSampleSize = computeSampleSize(opts, minSideLength,
width * height);
opts.inJustDecodeBounds = false;
opts.inInputShareable = true;
opts.inPurgeable = true;
}
try {
return BitmapFactory.decodeFile(dst.getPath(), opts);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}
return null;
}
public static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);
int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}
private static int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(
Math.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}
}
参考文章:http://www.tuicool.com/articles/63emAv
http://blog.csdn.net/haozipi/article/details/47183543?ref=myread
http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=498&fromuid=6 Bitmap 究竟占多大内存
5.图片上传
@Override
public void run() {
// TODO Auto-generated method stub
super.run();
new Runnable() {
public void run() {
int res = 0;
String BOUNDARY = UUID.randomUUID().toString(); // 边界标识 随机生成
String PREFIX = "--", LINE_END = "\r\n";
String CONTENT_TYPE = "multipart/form-data"; // 内容类型
try {
URL url = new URL(Content.SERVICE_URL + urlString);
L.i(TAG, "url:" + url);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
conn.setReadTimeout(Content.CONNECT_TIMEOUT);
conn.setConnectTimeout(Content.CONNECT_TIMEOUT);
conn.setDoInput(true); // 允许输入流
conn.setDoOutput(true); // 允许输出流
conn.setUseCaches(false); // 不允许使用缓存
conn.setRequestMethod("POST"); // 请求方式
conn.setRequestProperty("Charset", "UTF-8"); // 设置编码
conn.setRequestProperty("connection", "keep-alive");
conn.setRequestProperty("Content-Type", CONTENT_TYPE
+ ";boundary=" + BOUNDARY);
if (file != null) {
DataOutputStream dos = new DataOutputStream(
conn.getOutputStream());
StringBuffer sb = new StringBuffer();
sb.append(PREFIX);
sb.append(BOUNDARY);
sb.append(LINE_END);
sb.append("Content-Disposition: form-data; name=\"file\"; filename=\""
+ file.getName() + "\"" + LINE_END);
sb.append("Content-Type: application/octet-stream; charset="
+ "UTF-8" + LINE_END);
sb.append(LINE_END);
dos.write(sb.toString().getBytes());
InputStream is = new FileInputStream(file);
byte[] bytes = new byte[1024];
int len = 0;
while ((len = is.read(bytes)) != -1) {
dos.write(bytes, 0, len);
}
is.close();
dos.write(LINE_END.getBytes());
byte[] end_data = (PREFIX + BOUNDARY + PREFIX + LINE_END)
.getBytes();
dos.write(end_data);
dos.flush();
res = conn.getResponseCode();
L.i(TAG, "response code:" + res);
if (res == 200) {
L.i(TAG, "request success");
InputStream input = conn.getInputStream();
StringBuffer sb1 = new StringBuffer();
int ss;
while ((ss = input.read()) != -1) {
sb1.append((char) ss);
}
result = sb1.toString();
L.i(TAG, "result : " + result);
Message msg = new Message();
msg.what = 1;
msg.obj = sb1.toString();
handler2.sendMessage(msg);
} else {
L.i(TAG, "request error");
}
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}.run();
}
6.图片下载
public class InternetTest {
// 读取的方法
public byte[] readStream(InputStream inStream) throws Exception {
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
byte[] buffer = new byte[1024]; // 用数据装
int len = -1;
while ((len = inStream.read(buffer)) != -1) {
outstream.write(buffer, 0, len);
}
outstream.close();
inStream.close();
// 关闭流一定要记得。
return outstream.toByteArray();
}
@Test
public void getImage() throws Exception {
//要下载的图片的地址,
String urlPath = "http://t2.gstatic.com/images?q=tbn:9g03SOE7gW2gEM:http://dev.10086.cn/cmdn/supesite";
URL url = new URL(urlPath);//获取到路径
// http协议连接对象
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");// 这里是不能乱写的,详看API方法
conn.setConnectTimeout(6 * 1000);
// 别超过10秒。
System.out.println(conn.getResponseCode());
if (conn.getResponseCode() == 200) {
InputStream inputStream = conn.getInputStream();
byte[] data = readStream(inputStream);
File file = new File("smart.jpg");// 给图片起名子
FileOutputStream outStream = new FileOutputStream(file);//写出对象
outStream.write(data);// 写入
outStream.close(); // 关闭流
}
}
}
7.图片压缩
第一:我们先看下质量压缩方法:
private Bitmap compressImage(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);//质量压缩方法,这里100表示不压缩,把压缩后的数据存放到baos中
int options = 100;
while ( baos.toByteArray().length / 1024>100) { //循环判断如果压缩后图片是否大于100kb,大于继续压缩
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, options, baos);//这里压缩options%,把压缩后的数据存放到baos中
options -= 10;//每次都减少10
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());//把压缩后的数据baos存放到ByteArrayInputStream中
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);//把ByteArrayInputStream数据生成图片
return bitmap;
}
第二:图片按比例大小压缩方法(根据路径获取图片并压缩):
private Bitmap getimage(String srcPath) {
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeFile(srcPath,newOpts);//此时返回bm为空
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
//现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
float hh = 800f;//这里设置高度为800f
float ww = 480f;//这里设置宽度为480f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be;//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
}
第三:图片按比例大小压缩方法(根据Bitmap图片压缩):
private Bitmap comp(Bitmap image) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG, 100, baos);
if( baos.toByteArray().length / 1024>1024) {//判断如果图片大于1M,进行压缩避免在生成图片(BitmapFactory.decodeStream)时溢出
baos.reset();//重置baos即清空baos
image.compress(Bitmap.CompressFormat.JPEG, 50, baos);//这里压缩50%,把压缩后的数据存放到baos中
}
ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());
BitmapFactory.Options newOpts = new BitmapFactory.Options();
//开始读入图片,此时把options.inJustDecodeBounds 设回true了
newOpts.inJustDecodeBounds = true;
Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
newOpts.inJustDecodeBounds = false;
int w = newOpts.outWidth;
int h = newOpts.outHeight;
//现在主流手机比较多是800*480分辨率,所以高和宽我们设置为
float hh = 800f;//这里设置高度为800f
float ww = 480f;//这里设置宽度为480f
//缩放比。由于是固定比例缩放,只用高或者宽其中一个数据进行计算即可
int be = 1;//be=1表示不缩放
if (w > h && w > ww) {//如果宽度大的话根据宽度固定大小缩放
be = (int) (newOpts.outWidth / ww);
} else if (w < h && h > hh) {//如果高度高的话根据宽度固定大小缩放
be = (int) (newOpts.outHeight / hh);
}
if (be <= 0)
be = 1;
newOpts.inSampleSize = be;//设置缩放比例
//重新读入图片,注意此时已经把options.inJustDecodeBounds 设回false了
isBm = new ByteArrayInputStream(baos.toByteArray());
bitmap = BitmapFactory.decodeStream(isBm, null, newOpts);
return compressImage(bitmap);//压缩好比例大小后再进行质量压缩
}
8.图片分辨率减少方法,防止OOM
public Bitmap getBitmapFromFile(File dst, int width, int height) {
if (null != dst && dst.exists()) {
BitmapFactory.Options opts = null;
if (width > 0 && height > 0) {
opts = new BitmapFactory.Options();
opts.inJustDecodeBounds = true;
BitmapFactory.decodeFile(dst.getPath(), opts);
// 计算图片缩放比例
final int minSideLength = Math.min(width, height);
opts.inSampleSize = computeSampleSize(opts, minSideLength,
width * height);
opts.inJustDecodeBounds = false;
opts.inInputShareable = true;
opts.inPurgeable = true;
}
try {
return BitmapFactory.decodeFile(dst.getPath(), opts);
} catch (OutOfMemoryError e) {
e.printStackTrace();
}
}
return null;
}
public static int computeSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
int initialSize = computeInitialSampleSize(options, minSideLength,
maxNumOfPixels);
int roundedSize;
if (initialSize <= 8) {
roundedSize = 1;
while (roundedSize < initialSize) {
roundedSize <<= 1;
}
} else {
roundedSize = (initialSize + 7) / 8 * 8;
}
return roundedSize;
}
private static int computeInitialSampleSize(BitmapFactory.Options options,
int minSideLength, int maxNumOfPixels) {
double w = options.outWidth;
double h = options.outHeight;
int lowerBound = (maxNumOfPixels == -1) ? 1 : (int) Math.ceil(Math
.sqrt(w * h / maxNumOfPixels));
int upperBound = (minSideLength == -1) ? 128 : (int) Math.min(Math
.floor(w / minSideLength), Math.floor(h / minSideLength));
if (upperBound < lowerBound) {
// return the larger one when there is no overlapping zone.
return lowerBound;
}
if ((maxNumOfPixels == -1) && (minSideLength == -1)) {
return 1;
} else if (minSideLength == -1) {
return lowerBound;
} else {
return upperBound;
}
}
9.打开相机照片和本机相册选择图片
1、PopActivity
File file = new File(Content.CACHE_PATH + "/"+System.currentTimeMillis()+".png");
if(!file.exists())
try {
file.createNewFile();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
uri = Uri.fromFile(file);
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, TAKE_PHOTO);
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) return;
switch (requestCode) {
case TAKE_PHOTO:
intent.setData(uri);
cropBitmap(uri);
break;
public void cropBitmap(Uri mUri) {
Intent intent = new Intent("com.android.camera.action.CROP");
intent.setDataAndType(mUri, "image/*");
intent.putExtra("crop", "true");
intent.putExtra("aspectX", 1);
intent.putExtra("aspectY", 1);
intent.putExtra("outputX", 200);
intent.putExtra("outputY", 200);
intent.putExtra("outputFormat", "png");
intent.putExtra("noFaceDetection", true);
intent.putExtra("return-data", true);
startActivityForResult(intent, CROP_PICTURE);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode != RESULT_OK) return;
switch (requestCode) {
case CROP_PICTURE:
if(mark==2){
if(data.getData()!=null){
intent.setData(data.getData());
}else{
intent.putExtras(data.getExtras());
}
}else{
intent.putExtras(data.getExtras());
}
setResult(RESULT_OK, intent);
finish();
break;
2、Activity
@Override
protected void onActivityResult(int arg0, int arg1, Intent arg2) {
// TODO Auto-generated method stub
super.onActivityResult(arg0, arg1, arg2);
case TAKE_PHOTO:
if (arg2 != null) {
Bitmap one = null;
Uri photoUri = arg2.getData();
L.i(TAG, "photoUri#" + arg2);
if (photoUri.toString().contains("content://media")) {
Cursor cursor = getContentResolver().query(photoUri, null,
null, null, null);
cursor.moveToFirst();
String picturePath = cursor
.getString(cursor
.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
one = Util.getDiskBitmap(picturePath);
cursor.close();
iv3.setImageBitmap(one);
String picPath = Util.saveBitmap(
"" + System.currentTimeMillis(), Util.comp(one));
String semd = Util.bitmaptoString(one);
L.i(TAG, "p#" + picPath);
new ImageUpLoader("postImg/picture?uid=" + uid, picPath,
handler2).start();
} else {
Bundle extra = arg2.getExtras();
if (extra != null) {
one = (Bitmap)extra.get("data");
}
iv3.setImageBitmap(ImageToRound.toRoundBitmap(one));
String picPath = Util.saveBitmap(
"" + System.currentTimeMillis(), Util.comp(one));
L.i(TAG, "p:"+picPath);
new ImageUpLoader("postImg/picture?uid=" + uid, picPath,
handler2).start();
}
}
break;
12.Android-Universal-Image-Loader 图片异步加载类库的使用
http://blog.csdn.net/vipzjyno1/article/details/23206387
1、
private ImageLoader imageLoader;
private DisplayImageOptions options;
imageLoader = ImageLoader.getInstance();
imageLoader.init(ImageLoaderConfiguration.createDefault(context));
options = new DisplayImageOptions.Builder()
.showStubImage(Content.NO_PHOTO)
.showImageForEmptyUri(Content.NO_PHOTO)
.showImageOnFail(Content.NO_PHOTO).cacheInMemory(true)
.cacheOnDisc(true).bitmapConfig(Bitmap.Config.ARGB_8888)
.build();
imageLoader.displayImage(url2, vh.touImageView, options);
2、
public static void initImageLoader(Context context) {
ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(
context).threadPriority(Thread.NORM_PRIORITY - 2)
.denyCacheImageMultipleSizesInMemory()
.discCacheFileNameGenerator(new Md5FileNameGenerator())
.tasksProcessingOrder(QueueProcessingType.LIFO)
.writeDebugLogs().build();
ImageLoader.getInstance().init(config);
}
3、Configuration所有配置简介
.memoryCacheExtraOptions(480, 800) //即保存的每个缓存文件的最大长宽
.threadPriority(Thread.NORM_PRIORITY - 2) //设置图片加载线程的优先级,默认为Thread.NORM_PRIORITY-1 线程池中线程的个数 注:如果设置了taskExecutor或者taskExecutorForCachedImages 此设置无效
.threadPoolSize(3) // 设置显示图片线程池大小,默认为3 注:如果设置了taskExecutor或者taskExecutorForCachedImages 此设置无效
.denyCacheImageMultipleSizesInMemory() // 设置拒绝缓存在内存中一个图片多个大小 默认为允许,(同一个图片URL)根据不同大小的imageview保存不同大小图片
.memoryCache(new LRULimitedMemoryCache(40*1024*1024)) //缓存策略
.memoryCacheSize(50 * 1024 * 1024) //设置内存缓存的大小
.diskCacheFileNameGenerator(new Md5FileNameGenerator()) // 设置硬盘缓存文件名生成规范 默认为new HashCodeFileNameGenerator()
.diskCacheSize(200 * 1024 * 1024) //磁盘缓存大小
.tasksProcessingOrder(QueueProcessingType.LIFO) //工作队列 设置图片加载和显示队列处理的类型 默认为QueueProcessingType.FIFO 注:如果设置了taskExecutor或者taskExecutorForCachedImages 此设置无效
.diskCacheFileCount(200) //缓存的文件数量
.diskCache(new UnlimitedDiskCache(cacheDir)) //自定义缓存路径
.taskExecutor(DefaultConfigurationFactory.createExecutor(3,Thread.NORM_PRIORITY - 1, QueueProcessingType.FIFO)) // 设置自定义加载和显示图片的线程池
.taskExecutorForCachedImages(DefaultConfigurationFactory.createExecutor(3,Thread.NORM_PRIORITY - 1, QueueProcessingType.FIFO)) // 设置自定义加载和显示内存缓存或者硬盘缓存图片的线程池
.memoryCache(new LruMemoryCache(2 * 1024 * 1024)) // 设置内存缓存 默认为一个当前应用可用内存的1/8大小的LruMemoryCache
.memoryCacheSize(2 * 1024 * 1024) // 设置内存缓存的最大大小 默认为一个当前应用可用内存的1/8
.memoryCacheSizePercentage(13) // 设置内存缓存最大大小占当前应用可用内存的百分比 默认为一个当前应用可用内存的1/8
.discCache(new UnlimitedDiscCache(StorageUtils.getCacheDirectory(getApplicationContext()))) // 设置硬盘缓存默认为StorageUtils.getCacheDirectory(getApplicationContext())即/mnt/sdcard/android/data/包名/cache/
.discCacheSize(50 * 1024 * 1024) // 设置硬盘缓存的最大大小
.discCacheFileCount(100) // 设置硬盘缓存的文件的最多个数
.imageDownloader(new HttpClientImageDownloader(getApplicationContext(),new DefaultHttpClient())) // 设置图片下载器 默认为 DefaultConfigurationFactory.createBitmapDisplayer()
.imageDecoder(DefaultConfigurationFactory.createImageDecoder(false)) // 设置图片解码器 ,默认为DefaultConfigurationFactory.createImageDecoder(false)
.defaultDisplayImageOptions(DisplayImageOptions.createSimple()) // 设置默认的图片显示选项 ,默认为DisplayImageOptions.createSimple()
.writeDebugLogs() // 打印DebugLogs
.build(); // 建立
4、DisplayImageOptions所有配置简介
.showImageOnLoading(R.drawable.ic_chat_def_pic) // 设置图片加载时的默认图片
.showImageOnFail(R.drawable.ic_chat_def_pic_failure) // 设置图片加载失败的默认图片
.showImageForEmptyUri(R.drawable.ic_chat_def_pic) // 设置图片URI为空时默认图片
.resetViewBeforeLoading(false) // 设置是否将View在加载前复位
.delayBeforeLoading(100) // 设置延迟部分时间才开始加载 默认为0
.cacheInMemory(true) // 设置添加到内存缓存 默认为false
.cacheOnDisc(true) // 设置添加到硬盘缓存 默认为false
.imageScaleType(ImageScaleType.IN_SAMPLE_POWER_OF_2) // 设置规模类型的解码图像 默认为ImageScaleType.IN_SAMPLE_POWER_OF_2
.bitmapConfig(Bitmap.Config.ARGB_8888) // 设置位图图像解码配置 默认为Bitmap.Config.ARGB_8888
.decodingOptions(new Options()) // 设置选项的图像解码
.displayer(new FadeInBitmapDisplayer(300)) // 设置自定义显示器 默认为DefaultConfigurationFactory.createBitmapDisplayer()
.handler(new Handler()) // 设置自定义的handler 默认为new Handler()
.build(); // 建立
13、基于LruCache的图片缓存
http://blog.csdn.net/u013064109/article/details/51756551
14、openCV4android
http://blog.csdn.net/hbl_for_android/article/details/51941106 openCV4android常用变换(一)
http://blog.csdn.net/hbl_for_android/article/details/51989105 opencv4android常用变换(二)