概要:
Camera(相机),但是这里的android.graphics.Camera不同于hardware.Camera。它主要
用于2d图像实现3d效果。
Camera的一系列,旋转,平移方法。实质上改变的是内部的Matrix变量。最后我们可以通过
camera.getMatrix(matrix)方法。获取Matrix的值。之后就可以通过Matrix来改变图像了。
分析:
Camera的主要API有:
rotateX(float degree) 围绕X轴旋转
rotateY(float degree) 围绕Y轴旋转
rotateZ(float degree) 围绕Z轴旋转
rotate(float xDegree, float yDegree, float zDegree)
translate(x, y, z) 平移
save(),restore()与Canvas相同,都是保存原先状态和恢复原先状态。
getMatix(matrix) 将内部的Matrix的值复制到matrix(注意必须在restore之前)。
看到这里也许大家会觉得Camera与Matrix很相像,这里做个比较:
1,Camera的rotate是指定某个维度,旋转指定的角度。
Matrix的rotate是顺时针旋转指定的角度,与Camera的rotateZ效果相同方向相反。
2,Camera的Translate的方法根据某一维度上视点的位移实现图像的缩放,与matrix的Scale方法效果相同。
3,Camera不支持倾斜操作,Matrix可以直接实现倾斜操作。
应用:
代码如下所示:
public class AnimationActivity extends Activity {
Camera mCamera;
private ImageView iv_content;
private SeekBar sb_x, sb_y, sb_z;
private EditText et_x, et_y, et_z;
private TextView tv_rotatex, tv_rotatey, tv_rotatez;
private float rotateX, rotateY, rotateZ;
private float translateX, translateY, translateZ;
private Button btn_set;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_anim);
mCamera = new Camera();
initViews();
registerListeners();
}
private void initViews() {
sb_x = (SeekBar) findViewById(R.id.sb_rotatex);
sb_x.setMax(100);
sb_y = (SeekBar) findViewById(R.id.sb_rotatey);
sb_y.setMax(100);
sb_z = (SeekBar) findViewById(R.id.sb_rotatez);
sb_z.setMax(100);
et_x = (EditText) findViewById(R.id.et_x);
et_y = (EditText) findViewById(R.id.et_y);
et_z = (EditText) findViewById(R.id.et_z);
tv_rotatex = (TextView) findViewById(R.id.tv_rotatex);
tv_rotatey = (TextView) findViewById(R.id.tv_rotatey);
tv_rotatez = (TextView) findViewById(R.id.tv_rotatez);
btn_set = (Button) findViewById(R.id.btn_set);
iv_content = (ImageView) findViewById(R.id.iv_content);
}
private void registerListeners() {
sb_x.setOnSeekBarChangeListener(onSeekBarChangeListener);
sb_y.setOnSeekBarChangeListener(onSeekBarChangeListener);
sb_z.setOnSeekBarChangeListener(onSeekBarChangeListener);
btn_set.setOnClickListener(onClicker);
}
View.OnClickListener onClicker = new View.OnClickListener() {
@Override
public void onClick(View v) {
translateX = getFloat(et_x.getText().toString());
translateY = getFloat(et_y.getText().toString());
translateZ = getFloat(et_z.getText().toString());
refreshImage();
}
};
private float getFloat(String txt) {
try {
if ("".equals(txt) || txt == null) {
return 0;
} else {
return Float.parseFloat(txt);
}
} catch (Exception e) {
return 0;
}
}
SeekBar.OnSeekBarChangeListener onSeekBarChangeListener = new SeekBar.OnSeekBarChangeListener() {
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
if (seekBar == sb_x) {
tv_rotatex.setText("rotateX " + progress + "");
rotateX = progress * 360f / 100f;
} else if (seekBar == sb_y) {
tv_rotatey.setText("rotateY " + progress + "");
rotateY = progress * 360f / 100f;
} else if (seekBar == sb_z) {
tv_rotatez.setText("rotateZ " + progress + "");
rotateZ = progress * 360f / 100f;
}
refreshImage();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
};
private void refreshImage() {
Matrix matrix = new Matrix();
mCamera.save();
mCamera.rotateX(rotateX);
mCamera.rotateY(rotateY);
mCamera.rotateZ(rotateZ);
mCamera.translate(translateX, translateY, translateZ);
mCamera.getMatrix(matrix);
mCamera.restore();
BitmapDrawable bitmapDrawable = (BitmapDrawable) getResources().getDrawable(R.drawable.aa2);
Bitmap temBitmap = bitmapDrawable.getBitmap();
Bitmap bitmap = null;
try {
// 经过矩阵转换后的图像宽高有可能不大于0,此时会抛出IllegalArgumentException
bitmap = Bitmap.createBitmap(temBitmap, 0, 0, temBitmap.getWidth(), temBitmap.getHeight(), matrix, true);
} catch (IllegalArgumentException iae) {
iae.printStackTrace();
}
if (bitmap != null) {
iv_content.setImageBitmap(bitmap);
}
}
}
布局文件:res/layout/activity_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/ll_seek"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/tv_rotatex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="rotateX"/>
<SeekBar
android:id="@+id/sb_rotatex"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_rotatey"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="rotateY"/>
<SeekBar
android:id="@+id/sb_rotatey"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<TextView
android:id="@+id/tv_rotatez"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="rotateZ"/>
<SeekBar
android:id="@+id/sb_rotatez"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:id="@+id/et_x"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="translatex"/>
<EditText
android:id="@+id/et_y"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="translatey"/>
<EditText
android:id="@+id/et_z"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="translatez"/>
<Button
android:id="@+id/btn_set"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="set"/>
</LinearLayout>
</LinearLayout>
<ImageView
android:id="@+id/iv_content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:src="@drawable/aa2"/>
</RelativeLayout>