Android的图形处理:图片读存,缩转移,Shape图形,Selector多状态图,9patch图,自定义图形
简介
何为Graphics
手机上显示的任何界面, 无论是文字,按钮或图片, 都是系统内置的一些API绘制的Graphics(图形,图像)Graphics分为2D和3D两种在我们应用中操作最多的Graphics就是图片
用它我们要会: 如何操作图片 如何利用系统的相关API绘制一个自定义的Graphics
API
Bitmap: 位图,图片在内存中数据对象 .bmp .jpg .png
Drawable: 就是一个可画的对象,其可能是一张位图(BitmapDrawable), 也可能是一个图形(ShapeDrawable),有可能是一个图层(LayerDrawable)
我们根据画图的需求,创建相应的可画对象
Canvas: 画布,手机屏幕上用于绘图的目标区域
Paint: 我们可以把它看做一个画图工具,比如画笔、画刷。 他管理了每个画图工具的字体、颜色、样式。
Matrix: 矩阵,高等数学里有介绍,在图像处理方面,主要是用于平面的缩放、平移、旋转等操作
实践
图片的读取保存
用到的API
加载图片得到bitmap对象BitmapFactory.decodeResource(Resources res, int id)BitmapFactory.decodeFile(String pathName)
将bitmap对象保存到SD卡 compress(CompressFormat format, int quality, OutputStream stream)
package com.jane.graphics;
import java.io.FileNotFoundException;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;
import android.widget.Toast;
/*
Bitmap: 加载一张图片数据到内存中, 都可以封装成一个Bitmap对象
需求1: 加载资源文件中的图片资源并显示
需求2: 加载存储空间中的图片资源并显示
需求3: 将一个bitmap对象保存到存储空间中
*/
public class BitmapTestActivity extends Activity
{
private ImageView iv_bitmap1;
private ImageView iv_bitmap2;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmap);
iv_bitmap1 = (ImageView) findViewById(R.id.iv_bitmap1);
iv_bitmap2 = (ImageView) findViewById(R.id.iv_bitmap2);
// 需求1: 加载资源文件中的图片资源并显示
iv_bitmap1.setImageResource(R.drawable.ic_launcher);
// 需求2: 加载存储空间中的图片资源并显示
Bitmap bitmap = BitmapFactory.decodeFile("/storage/sdcard/ic_launcher.png");
iv_bitmap2.setImageBitmap(bitmap);
}
public void saveImage(View v) throws FileNotFoundException
{
// 需求3: 将一个bitmap对象保存到存储空间中
Bitmap bitmap = BitmapFactory.decodeFile("/storage/sdcard/ic_launcher.png");
bitmap.compress(CompressFormat.PNG, 100,openFileOutput("ic_launcher.png", Context.MODE_PRIVATE));
Toast.makeText(this, "保存完成", 0).show();
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="保存图片"
android:onClick="saveImage"/>
<ImageView
android:id="@+id/iv_bitmap1"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
<ImageView
android:id="@+id/iv_bitmap2"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
图片的缩放/旋转/平移处理
用的的API
在Android中, 可以通过Matrix来对图片进行缩放,旋转和平移的操作
Matrix: 矩阵(高数), 在图像处理方面,主要是用于平面的缩放、平移、旋转等操作
相关API:
Matrix.postScale(float sx, float sy) : 缩放
Matrix.postRotate(float degrees) : 旋转
Matrix.postTranslate(float dx, float dy) : 平移
Matrix.reset() : 清空重置
ImageView.setImageMatrix(Matrix matrix) 设置图片的Matrix
package com.jane.graphics;
import android.app.Activity;
import android.graphics.Matrix;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;
import android.widget.ImageView;
public class MatrixTestActivity extends Activity
{
private EditText et_matrix_scale;
private EditText et_matrix_rotate;
private EditText et_matrix_translateX;// 偏移量X
private EditText et_matrix_translateY;// 偏移量Y
private ImageView iv_matrix_icon;
private Matrix matrix;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_matrix);
et_matrix_scale = (EditText) findViewById(R.id.et_matrix_scale);
et_matrix_rotate = (EditText) findViewById(R.id.et_matrix_rotate);
et_matrix_translateX = (EditText) findViewById(R.id.et_matrix_translateX);
et_matrix_translateY = (EditText) findViewById(R.id.et_matrix_translateY);
iv_matrix_icon = (ImageView) findViewById(R.id.iv_matrix_icon);
matrix = new Matrix();
}
public void scaleBitmap(View view)
{
float scale = Float.parseFloat(et_matrix_scale.getText().toString());
// 保存缩放比例
matrix.postScale(scale, scale);
// 将matrix设置到imageView
iv_matrix_icon.setImageMatrix(matrix);
/*
* 要想上面的Matrix起效果,就得在布局文件里面的图片视图里面进行设置:
* android:scaleType="matrix"
*/
}
public void rotateBitmap(View view)
{
float degree = Float.parseFloat(et_matrix_rotate.getText().toString());
// 保存旋转角度
matrix.postRotate(degree);
// 将matrix设置到imageView
iv_matrix_icon.setImageMatrix(matrix);
}
public void translateBitmap(View view)
{
float dx = Float.parseFloat(et_matrix_translateX.getText().toString());
float dy = Float.parseFloat(et_matrix_translateY.getText().toString());
// 保存平移数据
matrix.postTranslate(dx, dy);
// 将matrix设置到imageView
iv_matrix_icon.setImageMatrix(matrix);
}
public void clearMatrix(View view)
{
matrix.reset();
// 将matrix设置到imageView
iv_matrix_icon.setImageMatrix(matrix);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:padding="10dp" >
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="50dip"
android:layout_marginTop="10dip"
android:orientation="horizontal" >
<EditText
android:id="@+id/et_matrix_scale"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:hint="缩放比例"
android:text="0.25" />
<EditText
android:id="@+id/et_matrix_rotate"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:hint="旋转角度"
android:onClick="rotateBitmap"
android:text="30" />
<EditText
android:id="@+id/et_matrix_translateX"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:hint="X偏移"
android:text="10" />
<EditText
android:id="@+id/et_matrix_translateY"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:hint="y偏移"
android:text="10" />
</LinearLayout>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="50dip"
android:layout_marginTop="10dip"
android:orientation="horizontal" >
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:onClick="scaleBitmap"
android:text="缩放" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:onClick="rotateBitmap"
android:text="旋转" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:onClick="translateBitmap"
android:text="移动" />
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1.0"
android:onClick="clearMatrix"
android:text="还原" />
</LinearLayout>
<ImageView
android:id="@+id/iv_matrix_icon"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="matrix"
android:src="@drawable/ic_launcher" />
</LinearLayout>
Shape图形图片
在Android中, 可以通过<shap>来配置自定义图形
这个先在布局文件里面定义好相应的视图文件,
然后将它的背景设置成Shape图形图片就可以了
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/shape_test"
android:text="使用Shape做的按钮" />
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<!-- 圆角
android:radius指定的是半径
-->
<corners android:radius="8dp" >
</corners>
<!-- 描边(边框)
android:dashGap 一个虚线的长度
android:dashWidth 虚线之间的间距
android:width 边框的宽度
android:color 边框颜色
-->
<stroke
android:dashGap="2dp"
android:dashWidth="10dp"
android:width="4dp"
android:color="#00ff00" />
<!-- 尺寸:就是这个视图对象的宽高 -->
<size
android:height="40dp"
android:width="100dp" />
<!-- 内部单色填充 -->
<solid android:color="#ff0000" />
<!-- 内部渐变色填充:
android:centerColor 中间颜色
android:endColor 结束颜色
android:startColor 开始颜色
android:angle 色变的方向
-->
<gradient
android:centerColor="#ffffff"
android:endColor="#ffff00"
android:startColor="#0000ff"
android:angle="90">
</gradient>
</shape>
Selector多状态图片
Selector+图片
selector多状态图形在可以在正常,按下,选中等状态下显示不同的图形, 在应用中十分常用
在使用时可以把它的xml文件看作一个图片
它可以与图片或<shap>一起使用
这个和上面也差不多,先在布局文件里面定义好相应的视图,
然后将它的背景设置成drawable文件就可以了
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="@drawable/select_drawble"
android:onClick="clickIV" />
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 这两个必须按照顺序来写,如果反过来
就不能生效了,比如没有按下去的时候选择正常的图片,
按下去后,因为正常的图片在前面,符合约束,所以也显示正常情况下的图片了
-->
<!-- 按下的图片 (必须写在前面) -->
<item android:drawable="@drawable/main_index_search_pressed" android:state_pressed="true"></item>
<!-- 正常情况下的图片 -->
<item android:drawable="@drawable/main_index_search_normal"></item>
</selector>
Selector+shape
<Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="@drawable/selector_shape"
android:text="使用Selector+Shape做的按钮" />
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:state_pressed="true">
<shape>
<corners android:radius="5dp"/>
<solid android:color="#ff0000"/>
<padding android:top="5dp" android:bottom="5dp"/>
</shape>
</item>
<item>
<shape>
<corners android:radius="10dp"/>
<solid android:color="#00ff00"/>
<padding android:top="5dp" android:bottom="5dp"/>
</shape>
</item>
</selector>
9patch图片(以.9.png结尾)
.9.png图片是一种特别的png图片, 它在放大显示时不会失真
.9.png图片可以分为三种类型区域
正中间区域: 可向水平和垂直方向复制扩展
中上, 中下, 中左与中右区域: 只能向一个方向扩展
四个角区域: 大小不会变化
如何制作?
准备一张png图片
然后在sdk的tools里面启动draw9patch.bat程序
然后用这个程序来打开png图片
然后将这张图片设置成背景就行了
绘制自定义图形
package com.jane.graphics;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Bundle;
import android.view.View;
public class DrawTestActivity extends Activity
{
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(new MyView(this));
}
class MyView extends View
{
private ShapeDrawable shapeDrawable;
private Paint paint;
public MyView(Context context)
{
super(context);
shapeDrawable = new ShapeDrawable(new OvalShape());
shapeDrawable.getPaint().setColor(Color.RED);// 指定颜色
shapeDrawable.setBounds(10, 10, 200, 100);// 指定位置
paint = new Paint();
paint.setColor(Color.BLUE); // 颜色
paint.setTextSize(20);// 字体大小
paint.setTypeface(Typeface.DEFAULT_BOLD);// 粗体字
paint.setAntiAlias(true);// 消除锯齿
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
// 画绿色背景
canvas.drawColor(Color.GREEN);
// 画椭圆
shapeDrawable.draw(canvas);// 将自己画到画布上
// 画文本,这里指定的坐标是左下角的坐标
canvas.drawText("画文字", 10, 120, paint);
}
}
}