android图片3d旋转

合集下载

Android Matrix图像变换处理

Android Matrix图像变换处理

Android Matrix图像变换处理Canvas类中drawBitmap(Bitmap bitmap, Matrix matrix, Paint paint)方法中有个参数类型是Matrix,从字面上理解是矩阵的意思,而实际上它也确实是个3x3的矩阵。

Matrix在Android 中的主要作用是图像变换,如平移、旋转、缩放、扭曲等。

Matrix内部通过维护一个float[9]的数组来构成3x3矩阵的形式,而实际上所有的变换方法说到底就是通过更改数组中某个或某几个位置的数值。

Matrix提供了setV alues()和getValues()方法来操作数组。

显然这两个方法使用起来很不方便,如果只有这样,那Matrix估计就不会有人使用了。

Google 轻易不会辜负我们的信任,Matrix提供了若干简单易用的变换方法和映射方法供开发者使用。

Matrix变换方法1、Translate(平移)、Scale(缩放)、Rotate(旋转)、Skew(扭曲)Matrix提供了Translate(平移)、Scale(缩放)、Rotate(旋转)、Skew(扭曲)四中变换操作,这四种操作实质上是调用了setValues()方法来设置矩阵数组来达到变换效果。

除Translate(平移)外,Scale(缩放)、Rotate(旋转)、Skew(扭曲)都可以围绕一个中心点来进行,如果不指定,在默认情况下是围绕(0, 0)来进行相应的变换的。

Translate操作中在x轴上使用正数进行平移将向右移动图像,而使用负数将向左移动图像。

在y轴上使用正数进行平移将向下移动图像,而使用负数将向上移动图像。

Scale操作中,在x轴上使用正数进行缩放将在中心点的右边缩放图像,而使用负数将在中心点的左边缩放图像。

在y轴上使用正数进行缩放将在中心点的下边缩放图像,而使用负数将在中心点的上边缩放图像。

2、pre、set、postMatrix提供的四种操作,每一种都有pre、set、post三种形式。

麦子学院Android开发教程旋转动画效果实现方法

麦子学院Android开发教程旋转动画效果实现方法

最近在网上发现一个很实用的例子,关于旋转动画效果的实现方法,转给大家分享下。

Main.java:Java代码1.public class Main extends Activity {2.3. private com.example.view.RoundSpinView mSelfView;4.5. /** Called when the activity is first created. */6. @Override7. public void onCreate(Bundle savedInstanceState) {8. super.onCreate(savedInstanceState);9. setContentView(yout.main);10. mSelfView = (com.example.view.RoundSpinView)findViewById(R.id.mSelfView);11. mSelfView.setmPointX(160);12. mSelfView.setmPointY(150);13. mSelfView.setmRadius(80);14. mSelfView.fixBoxPosition();15. }16.}17.复制代码自定义View,实现旋转动画:RoundSpinView.java:Java代码1.public class RoundSpinView extends View {2.3. private Paint mPaint = new Paint();4. private static final int STONE_COUNT = 4;5. /** 4张图片分布的角度均值 */6. private int mDegreeDelta;7. private float mDown_x, mDown_y;8.9. private int[] mResourceId = { R.drawable.customer, R.drawable.product,10. R.drawable.order, };11.12. public RoundSpinView(Context context, AttributeSet attrs) {13. super(context, attrs);14. mPaint.setColor(Color.RED);15. mPaint.setStrokeWidth(2);16. setupStones();17. computeCoordinates();18. }19.20. /** 初始化每个旋转图片的坐标位置及图片资源 */21. private void setupStones() {22. mStones = new BigStone[STONE_COUNT];23. BigStone stone;24. int angle = 0;25. mDegreeDelta = 360 / STONE_COUNT;26.27. for (int index = 0; index < STONE_COUNT; index++) {28. stone = new BigStone();29. stone.angle = angle;30. stone.bitmap = BitmapFactory.decodeResource(getResources(),31. mResourceId[index]);32. angle += mDegreeDelta;33. mStones[index] = stone;34. }35. }36.37. /** 计算每个旋转图片坐标 */38. private void computeCoordinates() {39. BigStone stone;40. for (int index = 0; index < STONE_COUNT; index++) {41. stone = mStones[index];42. if (stone.angle >= 360) {43. stone.angle -= 360;44. }45. stone.x = mPointX46. + (float) (mRadius * Math.cos(stone.angle * Math.PI /180));47. stone.y = mPointY48. + (float) (mRadius * Math.sin(stone.angle * Math.PI /180));49. }50. }51.52. public RoundSpinView(Context context) {53. super(context);54. }55.56. private BigStone[] mStones;57.58. /** 旋转的中心点 */59. private int mPointX = 0, mPointY = 0;60. /** 旋转半径 */61. private int mRadius = 0;62.63. private int[] mInts = new int[] { 0, 0, 0, 0 };64. /** 标识那个图片应该位于正中间 */65. private int mIn;66.67. public int getmRadius() {68. return mRadius;69. }70.71. public void setmRadius(int mRadius) {72. this.mRadius = mRadius;73. }74.75. public int getmPointX() {76. return mPointX;77. }78.79. public void setmPointX(int mPointX) {80. this.mPointX = mPointX;81. }82.83. public int getmPointY() {84. return mPointY;85. }86.87. public void setmPointY(int mPointY) {88. this.mPointY = mPointY;89. }90.91. /** Sort the elements in one array. */92. public static void sort(int[] data) {93. int len = data.length;94. for (int i = 0; i < len - 1; i++) {95. int temp = 0;96. boolean isExchanged = false;97. for (int j = len - 1; j > i; j--) {98. if (data[j] < data[j - 1]) {99. temp = data[j];100. data[j] = data[j - 1];101. data[j - 1] = temp;102. /** 发生了交换,故将交换标志置为真 */ 103. isExchanged = true;104. }105. }106. /** 本趟排序未发生交换,提前终止算法,提高效率 */ 107. if (!isExchanged) {108. return;109. }110. }111. }112.113. public void fixBoxPosition() {114. for (int i = 0; i < 4; i++) {115. mInts[i] = Math.abs(mStones[i].angle - 90); 116. }117. RoundSpinView.sort(mInts);118. for (int i = 0; i < 4; i++) {119. if (Math.abs(mStones[i].angle - 90) == mInts[0]) { 120. mIn = i;121. break;122. }123. }124. int mO = 0;125. do {126. mStones[mIn].angle = mO * 90 + 90;127. mIn++;128. if (mIn == 4) {129. mIn = 0;130. }131. mO++;132. } while (mO < 4);133. computeCoordinates();134. invalidate();135. }136.137. public void catchClickEvent(float mX, float mY) {138. System.out.println("mDown_x__________" + mDown_x);139. System.out.println("mDown_y__________" + mDown_y);140. for (int i = 0; i < mStones.length; i++) {141. if (mStones[i].angle == 90) {142. mStones[i].bitmap = BitmapFactory.decodeResource( 143. getResources(), R.drawable.icon);144. }145. }146. invalidate();147. }148.149. @Override150. public boolean dispatchTouchEvent(MotionEvent event) {151. switch (event.getAction()) {152. case MotionEvent.ACTION_DOWN:153. mDown_x = event.getX();154. mDown_y = event.getY();155. // catchClickEvent(mDown_x, mDown_y);156. break;157. case MotionEvent.ACTION_MOVE:158. float mDistance_x = event.getX() - mDown_x;159. float mDistance_y = event.getY() - mDown_y;160. computeAngle(mDistance_x, mDistance_y);161. computeCoordinates();162. invalidate();163. break;164. case MotionEvent.ACTION_UP:165. fixBoxPosition();166. break;167. }168. return true;169. }170.171. public void computeAngle(float mX, float mY) {172. int angle = (int) (mX * 0.1);173. if (mX < 0) {174. for (int index = 0; index < STONE_COUNT; index++) { 175. mStones[index].angle = mStones[index].angle - angle; 176. }177. } else if (mX > 0) {178. for (int index = 0; index < STONE_COUNT; index++) { 179. mStones[index].angle = mStones[index].angle - angle; 180. }181. }182. }183.184. /** 计算一次滑动的角度 */185. public int computeCurrentAngle(float x, float y) {186. float distance = (float) Math187. .sqrt(((x - mPointX) * (x - mPointX) + (y - mPointY) 188. * (y - mPointY)));189. int degree = (int) (Math.acos((x - mPointX) / distance) * 180 / Math.PI);190. return degree;191. }192.193. @Override194. public void onDraw(Canvas canvas) {195. canvas.drawPoint(mPointX, mPointY, mPaint);196.197. for (int index = 0; index < STONE_COUNT; index++) {198. if (!mStones[index].isVisible)199. continue;200. drawInCenter(canvas, mStones[index].bitmap, mStones[index].x,201. mStones[index].y);202. // 不想有红线,就注掉下面这句203. // canvas.drawLine(mPointX, mPointY, mStones[index].x, 204. // mStones[index].y, mPaint);205. }206. }207.208. /**209. * 把中心点放到中心处210. *211. * @param canvas212. * @param bitmap213. * @param left214. * @param top215. */216. void drawInCenter(Canvas canvas, Bitmap bitmap, float left, float top) {217. canvas.drawPoint(left, top, mPaint);218. canvas.drawBitmap(bitmap, left - bitmap.getWidth() / 2,219. top - bitmap.getHeight() / 2, null);220. }221.222. class BigStone {223. Bitmap bitmap;224. int angle;225. float x;226. float y;227. boolean isVisible = true;228. }229.}230.复制代码代码有点长,各位可以建个工程运行看下效果.main.xml:Java代码1.<?xml version="1.0" encoding="utf-8"?>2.<RelativeLayoutxmlns:android="/apk/res/android"3. android:layout_width="fill_parent" android:layout_height="fill_parent"4. android:background="@drawable/bg">5. <TextView android:layout_width="fill_parent"6. android:layout_height="wrap_content" android:text="Theanimation is solved." />7. <com.example.view.RoundSpinView8. android:layout_width="320dp" android:layout_height="300dp"android:id="@+id/mSelfView"9. android:layout_alignParentBottom="true" />10.</RelativeLayout>11.复制代码如需了解更多相关知识,请至麦子学院官网查询(/)。

android 渐变透明、伸缩、平移、旋转动画效果

android 渐变透明、伸缩、平移、旋转动画效果

android 渐变透明、伸缩、平移、旋转动画效果import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.view.KeyEvent;import android.view.View;import android.view.animation.AlphaAnimation;import android.view.animation.Animation;import android.view.animation.RotateAnimation;import android.view.animation.ScaleAnimation;import android.view.animation.TranslateAnimation;/**•@AlphaAnimation 渐变透明度动画效果•@ScaleAnimation 渐变尺寸伸缩动画效果•@TranslateAnimation 画面转换位置移动动画效果•@RotateAnimation 画面转移旋转动画效果•*/•public class MyViewAnimation extends View {• private Paint paint;• private Bitmap bmp;• private int x = 50;• private Animation mAlphaAnimation;• private Animation mScaleAnimation;• private Animation mTranslateAnimation;• private Animation mRotateAnimation;•public MyViewAnimation(Context context) {super(context);paint = new Paint();paint.setAntiAlias(true);bmp = BitmapFactory.decodeResource(getResources(),R.drawable.icon);this.setFocusable(true);// 只有当该View获得焦点时才会调用onKeyDown方法}@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);canvas.drawColor(Color.BLACK);paint.setColor(Color.WHITE);canvas.drawText("Himi", x, 50, paint);// 备注1canvas.drawText("方向键↑ 渐变透明度动画效果", 80,this.getHeight() - 80, paint);canvas.drawText("方向键↓ 渐变尺寸伸缩动画效果", 80,this.getHeight() - 60, paint);canvas.drawText("方向键← 画面转换位置移动动画效果", 80, this.getHeight() - 40, paint);canvas.drawText("方向键→ 画面转移旋转动画效果", 80,this.getHeight() - 20, paint);canvas.drawBitmap(bmp, this.getWidth() / 2- bmp.getWidth() / 2,this.getHeight() / 2- bmp.getHeight() / 2, paint); x += 1;}public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_DPAD_UP) {// 渐变透明度动画效果mAlphaAnimation = new AlphaAnimation(0.1f, 1.0f);// 第一个参数fromAlpha 为动画开始时候透明度// 第二个参数toAlpha 为动画结束时候透明度// 注意:取值范围[0-1];[完全透明-完全不透明]mAlphaAnimation.setDuration(3000);// //设置时间持续时间为3000 毫秒=3秒this.startAnimation(mAlphaAnimation);} else if (keyCode == KeyEvent.KEYCODE_DPAD_DOWN) {// 渐变尺寸伸缩动画效果mScaleAnimation = new ScaleAnimation(0.0f, 2.0f, 1.5f, 1.5f,Animation.RELATIVE_TO_PARENT, 0.5f,Animation.RELATIVE_TO_PARENT, 0.0f);// 第一个参数fromX为动画起始时X坐标上的伸缩尺寸// 第二个参数toX为动画结束时X坐标上的伸缩尺寸// 第三个参数fromY为动画起始时Y坐标上的伸缩尺寸// 第四个参数toY 为动画结束时Y 坐标上的伸缩尺寸// 注意:// 0.0表示收缩到没有// 1.0表示正常无伸缩// 值小于1.0表示收缩// 值大于1.0表示放大// -----我这里1-4参数表明是起始图像大小不变,动画终止的时候图像被放大1.5倍// 第五个参数pivotXType 为动画在X 轴相对于物件位置类型// 第六个参数pivotXValue 为动画相对于物件的X 坐标的开始位置// 第七个参数pivotXType 为动画在Y 轴相对于物件位置类型// 第八个参数pivotYValue 为动画相对于物件的Y 坐标的开始位置// 提示:位置类型有三种,每种效果大家自己尝试哈~这里偷下懒~ // 毕竟亲眼看到效果的区别才记忆深刻~// Animation.ABSOLUTE// 、Animation.RELATIVE_TO_SELF、Animation.RELATIVE_TO_PARENTmScaleAnimation.setDuration(2000);this.startAnimation(mScaleAnimation);} else if (keyCode == KeyEvent.KEYCODE_DPAD_LEFT) {// 画面转换位置移动动画效果mTranslateAnimation = new TranslateAnimation(0, 100, 0, 100);// 第一个参数fromXDelta为动画起始时X坐标上的移动位置// 第二个参数toXDelta为动画结束时X坐标上的移动位置// 第三个参数fromYDelta为动画起始时Y坐标上的移动位置// 第四个参数toYDelta 为动画结束时Y 坐标上的移动位置mTranslateAnimation.setDuration(2000);this.startAnimation(mTranslateAnimation);} else if (keyCode == KeyEvent.KEYCODE_DPAD_RIGHT) {// 画面转移旋转动画效果mRotateAnimation = new RotateAnimation(0.0f, 360.0f, Animation.RELATIVE_TO_SELF, 0.5f,Animation.RELATIVE_TO_SELF, 0.5f);// 第一个参数fromDegrees为动画起始时的旋转角度// 第二个参数toDegrees 为动画旋转到的角度// 第三个参数pivotXType 为动画在X 轴相对于物件位置类型// 第四个参数pivotXValue 为动画相对于物件的X 坐标的开始位置// 第五个参数pivotXType 为动画在Y 轴相对于物件位置类型// 第六个参数pivotYValue 为动画相对于物件的Y 坐标的开始位置mRotateAnimation.setDuration(3000);this.startAnimation(mRotateAnimation);}return super.onKeyDown(keyCode, event);}}</pre>。

Android部分手机拍照后获取的图片被旋转问题的解决方法

Android部分手机拍照后获取的图片被旋转问题的解决方法

Android部分⼿机拍照后获取的图⽚被旋转问题的解决⽅法调⽤Android系统拍照功能后,三星⼿机拍摄后的照⽚被旋转了90度,横着拍给你变成竖的,竖的拍给你变成横的。

其它品牌的⼿机都是正常的,就三星出现这个怪事。

在Android适配上,我原来⼀直以为国内的⼩⽶⼿机够奇葩了,结果还有更奇葩的!你说你没事旋转照⽚⼲啥,实在是猜不透其居⼼何在,纯粹是在给开发者制造⿇烦啊!解决办法是获取到拍照后照⽚被旋转的⾓度,再旋转回去就好了。

具体思路:1、⾸先在调⽤拍照⽅法时,保存拍照后的相⽚原图,得到原图路径,(PhotoBitmapUtils是我⾃⼰写的⼀个⼯具类)String fileName = "";/*** 启动相机拍照*/private void addBitmapShoots() {Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// 设置图⽚要保存的根路径+⽂件名fileName = PhotoBitmapUtils.getPhotoFileName(getContext());File file = new File(fileName);if (!file.exists()) {try {file.createNewFile();} catch (IOException e) {e.printStackTrace();}}intent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(file));startActivityForResult(intent, OPEN_CAMERA);}2、在获取相机返回的回调⽅法onActivityResult()中,修复被旋转的图⽚并取得修复后的图⽚路径,有了这个路径后就可以展⽰出来了@Overridepublic void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);// 获取相机拍照返回if (resultCode == Activity.RESULT_OK && requestCode == OPEN_CAMERA) {// 得到修复后的照⽚路径String filepath = PhotoBitmapUtils.amendRotatePhoto(fileName, getContext());}}PhotoBitmapUtils类:/*** 集合⼀些图⽚⼯具** Created by zhuwentao on 2016-07-22.*/public class PhotoBitmapUtils {/*** 存放拍摄图⽚的⽂件夹*/private static final String FILES_NAME = "/MyPhoto";/*** 获取的时间格式*/public static final String TIME_STYLE = "yyyyMMddHHmmss";/*** 图⽚种类*/public static final String IMAGE_TYPE = ".png";// 防⽌实例化private PhotoBitmapUtils() {}/*** 获取⼿机可存储路径** @param context 上下⽂* @return ⼿机可存储路径*/private static String getPhoneRootPath(Context context) {// 是否有SD卡if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)|| !Environment.isExternalStorageRemovable()) {// 获取SD卡根⽬录return context.getExternalCacheDir().getPath();} else {// 获取apk包下的缓存路径return context.getCacheDir().getPath();}}/*** 使⽤当前系统时间作为上传图⽚的名称** @return 存储的根路径+图⽚名称*/public static String getPhotoFileName(Context context) {File file = new File(getPhoneRootPath(context) + FILES_NAME);// 判断⽂件是否已经存在,不存在则创建if (!file.exists()) {file.mkdirs();}// 设置图⽚⽂件名称SimpleDateFormat format = new SimpleDateFormat(TIME_STYLE, Locale.getDefault()); Date date = new Date(System.currentTimeMillis());String time = format.format(date);String photoName = "/" + time + IMAGE_TYPE;return file + photoName;}/*** 保存Bitmap图⽚在SD卡中* 如果没有SD卡则存在⼿机中** @param mbitmap 需要保存的Bitmap图⽚* @return 保存成功时返回图⽚的路径,失败时返回null*/public static String savePhotoToSD(Bitmap mbitmap, Context context) {FileOutputStream outStream = null;String fileName = getPhotoFileName(context);try {outStream = new FileOutputStream(fileName);// 把数据写⼊⽂件,100表⽰不压缩press(pressFormat.PNG, 100, outStream);return fileName;} catch (Exception e) {e.printStackTrace();return null;} finally {try {if (outStream != null) {// 记得要关闭流!outStream.close();}if (mbitmap != null) {mbitmap.recycle();}} catch (Exception e) {e.printStackTrace();}}}/*** 把原图按1/10的⽐例压缩** @param path 原图的路径* @return 压缩后的图⽚*/public static Bitmap getCompressPhoto(String path) {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = false;options.inSampleSize = 10; // 图⽚的⼤⼩设置为原来的⼗分之⼀Bitmap bmp = BitmapFactory.decodeFile(path, options);options = null;return bmp;}/*** 处理旋转后的图⽚* @param originpath 原图路径* @param context 上下⽂* @return 返回修复完毕后的图⽚路径*/public static String amendRotatePhoto(String originpath, Context context) {// 取得图⽚旋转⾓度int angle = readPictureDegree(originpath);// 把原图压缩后得到Bitmap对象Bitmap bmp = getCompressPhoto(originpath);;// 修复图⽚被旋转的⾓度Bitmap bitmap = rotaingImageView(angle, bmp);// 保存修复后的图⽚并返回保存后的图⽚路径return savePhotoToSD(bitmap, context);}/*** 读取照⽚旋转⾓度** @param path 照⽚路径* @return ⾓度*/public static int readPictureDegree(String path) {int degree = 0;try {ExifInterface exifInterface = new ExifInterface(path);int orientation = exifInterface.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL); switch (orientation) {case ExifInterface.ORIENTATION_ROTATE_90:degree = 90;break;case ExifInterface.ORIENTATION_ROTATE_180:degree = 180;break;case ExifInterface.ORIENTATION_ROTATE_270:degree = 270;break;}} catch (IOException e) {e.printStackTrace();}return degree;}/*** 旋转图⽚* @param angle 被旋转⾓度* @param bitmap 图⽚对象* @return 旋转后的图⽚*/public static Bitmap rotaingImageView(int angle, Bitmap bitmap) {Bitmap returnBm = null;// 根据旋转⾓度,⽣成旋转矩阵Matrix matrix = new Matrix();matrix.postRotate(angle);try {// 将原始图⽚按照旋转矩阵进⾏旋转,并得到新的图⽚returnBm = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);} catch (OutOfMemoryError e) {}if (returnBm == null) {returnBm = bitmap;}if (bitmap != returnBm) {bitmap.recycle();}return returnBm;}}在调⽤修复图⽚⾓度⽅法的时候需要注意,现在的⼿机像素越来越⼤,拍完后⼀张照⽚有近10M,所以我们需要对图⽚进⾏压缩处理。

Android开发RotateAnimation详解

Android开发RotateAnimation详解

android中提供了如下4种动画效果:1、AlphaAnimation 透明度动画效果2、ScaleAnimation 缩放动画效果3、TranslateAnimation 位移动画效果4、RotateAnimation 旋转动画效果今天主要讲解RotateAnimation 旋转动画效果的实现方法。

RotateAnimation 参数有:float fromDegrees, float toDegrees, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue分别是:float fromDegrees:旋转的开始角度。

float toDegrees:旋转的结束角度。

int pivotXType:X轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。

float pivotXValue:X坐标的伸缩值。

int pivotYType:Y轴的伸缩模式,可以取值为ABSOLUTE、RELATIVE_TO_SELF、RELATIVE_TO_PARENT。

float pivotYValue:Y坐标的伸缩值。

代码示例:public class MainActivity extends Activity {ImageView image;Button start;Button cancel;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);image = (ImageView) findViewById(R.id.main_img);start = (Button) findViewById(R.id.main_start);cancel = (Button) findViewById(R.id.main_cancel);/** 设置旋转动画 */final RotateAnimation animation =newRotateAnimation(0f,360f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);animation.setDuration(3000);//设置动画持续时间/** 常用方法 *///animation.setRepeatCount(int repeatCount);//设置重复次数//animation.setFillAfter(boolean);//动画执行完后是否停留在执行完的状态//animation.setStartOffset(long startOffset);//执行前的等待时间start.setOnClickListener(new OnClickListener() {public void onClick(View arg0) {image.setAnimation(animation);/** 开始动画 */animation.startNow();}});cancel.setOnClickListener(new OnClickListener() {public void onClick(View v) {/** 结束动画 */animation.cancel();}});}}更多android视频学习教程,请至麦子学院官网查看>>/course/2/。

Android动画机制与使用技巧

Android动画机制与使用技巧

Android动画机制与使⽤技巧动画效果⼀直是⼈机交互中⾮常重要的部分,与死板、突兀的显⽰效果不同,动画效果的加⼊,让交互变得更加友好,特别是在提⽰、引导类的场景中,合理地使⽤动画能让⽤户获得更加愉悦的使⽤体验⼀、Android View动画框架Animation框架定义了透明度、旋转、缩放、位移等⼏种常见的动画实现原理:每次绘制View时,ViewGroup中的drawChild函数获取该view的Animation的Transformation值,然后调⽤canvas.concat(transformToApply.getMatrix())通过矩阵运算完成帧动画,如果动画没有完成,就继续调⽤invalidate() 函数,启动下次绘制来驱动动画,从⽽完成整个动画的绘制。

⼆、帧动画帧动画就是⼀张张图⽚不同的切换,形成的动画效果。

⼀般⼿机的开机动画,应⽤的等待动画等都是帧动画,因为只需要⼏张图⽚轮播,极其节省资源,如果真的设计成动画,那么是很耗费资源的事。

在res⽬录下新建⼀个drawable⽂件夹并定义xml⽂件,⼦节点为 animation-list,在这⾥定义要显⽰的图⽚和每张图⽚的显⽰时长。

<animation-list xmlns:android="/apk/res/android"android:oneshot="false"><!-- false表⽰循环播放,true表⽰只播放⼀次 --><item android:drawable="@drawable/g1" android:duration="200" /><item android:drawable="@drawable/g2" android:duration="200" /><item android:drawable="@drawable/g3" android:duration="200" /><item android:drawable="@drawable/g4" android:duration="200" /><item android:drawable="@drawable/g5" android:duration="200" /><item android:drawable="@drawable/g6" android:duration="300" /><item android:drawable="@drawable/g7" android:duration="400" /><!-- 慢动作 --><item android:drawable="@drawable/g8" android:duration="500" /><item android:drawable="@drawable/g9" android:duration="200" /><item android:drawable="@drawable/g10" android:duration="200" /><item android:drawable="@drawable/g11" android:duration="200" /></animation-list>在屏幕上播放帧动画,需要布局⽂件有⼀个ImageView来显⽰动画图⽚public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(yout.activity_main);ImageView iv = (ImageView) findViewById(R.id.iv);//把动画⽂件设置为imageView的背景iv.setBackgroundResource(R.drawable.frameanimation);AnimationDrawable ad = (AnimationDrawable) iv.getBackground();//播放动画ad.start();}}三、补间动画(视图动画)组件由原始状态向终极状态转变时,为了让过渡更⾃然,⽽⾃动⽣成的动画叫做补间动画。

Android开发—Android gallery图片左右循环旋转

Android开发—Android gallery图片左右循环旋转

第一步初始化gallery时设置较大的初始化位置1 2 3 Gallery gallery =((Gallery) findViewById(R.id.myGallery1));gallery.setAdapter(new ImageAdapter(this));gallery.setSelection(200);第二步:重写BaseAdapter方法中的getCount时返回一个较大的值:1 2 3 4 5 // 为了使资源循环使用public int getCount(){return Integer.MAX_VALUE;}第三步:重写BaseAdapter时使用用position对集合大小取余的值,如下:1 2 3 4 5 6 7 8 9101112131415161718 /* 取得目前欲显示的图像View,传入数组ID值使之读取与成像*/ public View getView(int position, View convertView, ViewGroup parent) {/* 创建一个ImageView对象*/ImageView i =new ImageView(this.myContext);i.setPadding(10, 10, 10, 10);i.setAlpha(80);// i.setImageResource(this.myImageIds[position]);if(position<0){position =position+myImageIds.length;}i.setImageResource(this.myImageIds[position% myImageIds.length]);i.setScaleType(ImageView.ScaleType.FIT_XY);i.setBackgroundResource(mGalleryItemBackground);/* 设置这个ImageView对象的宽高,单位为dip */i.setLayoutParams(new youtParams(85, 72));return i;}以下是该类的完整代码:1 2 3/* 依据距离中央的位移量利用getScale返回views的大小(0.0f to 1.0f) */ package irdc.ex03_15;4 5 6 7 8 91011121314151617181920212223242526272829303132333435363738394041424344454647 import android.app.Activity;import android.content.Context;import android.content.res.TypedArray;import android.os.Bundle;import android.view.View;import android.view.ViewGroup;import android.widget.AdapterView;import android.widget.BaseAdapter;import android.widget.Gallery;import android.widget.ImageView;import android.widget.TextView;import android.widget.Toast;import android.widget.AdapterView.OnItemSelectedListener;public class EX03_15 extends Activity{private TextView mT extView01;@Overridepublic void onCreate(Bundle savedInstanceState){super.onCreate(savedInstanceState);setContentView(yout.main);Gallery gallery =((Gallery) findViewById(R.id.myGallery1));gallery.setAdapter(new ImageAdapter(this));gallery.setSelection(200);gallery.setOnItemSelectedListener(new OnItemSelectedListener(){public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2, long arg3){Toast.makeText(EX03_15.this, "当前位置:"+ arg2, Toast.LENGTH_SHORT).show();}public void onNothingSelected(AdapterView<?> arg0){}});}4849505152535455565758596061626364656667686970717273747576777879808182838485868788899091 public class ImageAdapter extends BaseAdapter{/* 类成员myContext为Context父类*/private Context myContext;/*声明GalleryItemBackground*/int mGalleryItemBackground;/* 使用android.R.drawable里的图片作为图库来源,类型为整数数组*/ private int[] myImageIds ={ R.drawable.a1, R.drawable.a2, R.drawable.a3, R.drawable.a4,R.drawable.a5, R.drawable.a27};/* 构造器只有一个参数,即要存储的Context */public ImageAdapter(Context c){myContext = c;/** 使用在res/values/attrs.xml中的<declare-styleable>定义的Gallery属性.*/TypedArray a = obtainStyledAttributes(R.styleable.Gallery);/* 取得Gallery属性的Index id */mGalleryItemBackground = a.getResourceId(R.styleable.Gallery_android_galleryItemBackground, 0);/* 让对象的styleable属性能够反复使用*/a.recycle();}/* 返回所有已定义的图片总数量*/// public int getCount() { return this.myImageIds.length; }// 为了使资源循环使用public int getCount(){return Integer.MAX_VALUE;}/* 利用getItem方法,取得目前容器中图像的数组ID */public Object getItem(int position){return position;}9293949596979899 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122public long getItemId(int position){return position;}/* 取得目前欲显示的图像View,传入数组ID值使之读取与成像*/public View getView(int position, View convertView, ViewGroup parent) {/* 创建一个ImageView对象*/ImageView i =new ImageView(this.myContext);i.setPadding(10, 10, 10, 10);i.setAlpha(80);// i.setImageResource(this.myImageIds[position]);if(position<0){position =position+myImageIds.length;}i.setImageResource(this.myImageIds[position% myImageIds.length]);i.setScaleType(ImageView.ScaleType.FIT_XY);i.setBackgroundResource(mGalleryItemBackground);/* 设置这个ImageView对象的宽高,单位为dip */i.setLayoutParams(new youtParams(85, 72));return i;}/* 依据距离中央的位移量利用getScale返回views的大小(0.0f to 1.0f) */ public float getScale(boolean focused, int offset){return Math.max(0, 1.0f /(float)Math.pow(2, Math.abs(offset)));}}}。

AndroidUI设计系列之ImageView实现ProgressBar旋转效果(1)

AndroidUI设计系列之ImageView实现ProgressBar旋转效果(1)

AndroidUI设计系列之ImageView实现ProgressBar旋转效果(1)提起ProgressBar,想必⼤家都⽐较熟悉,使⽤起来也是⽐较⽅便,直接在XML⽂件中引⽤,然后添加属性,运⾏就OK了,虽然使⽤ProgressBar很⽅便但是在我们开发的每⼀个应⽤基本上都有⾃⼰的主体风格,如果使⽤了系统⾃带的效果图,给⼈的感觉是和总体风格太不搭配了,看上去很是别扭,我们⾃⼰开发也觉得不爽,于是就想着⾃定义⼀下效果,其实⾃定义ProgressBar的效果也不难,⼤概可分为三步⾛吧:⼀、在anim⽂件夹下使⽤animation-list定义动画集<?xml version="1.0" encoding="UTF-8"?><animation-list android:oneshot="false" xmlns:android="/apk/res/android"><item android:duration="50" android:drawable="@drawable/circle_10001" /><item android:duration="50" android:drawable="@drawable/circle_10002" /><item android:duration="50" android:drawable="@drawable/circle_10003" /><item android:duration="50" android:drawable="@drawable/circle_10004" /><item android:duration="50" android:drawable="@drawable/circle_10005" /><item android:duration="50" android:drawable="@drawable/circle_10006" /><item android:duration="50" android:drawable="@drawable/circle_10007" /></animation-list>⼆、在style.xml⽂件中定义风格<style name="CircleProgressStyle" parent="@android:style/rge"><item name="android:indeterminateDrawable">@anim/anim_progress_circle</item></style>三、在使⽤ProgressBar的xml⽂件中设置其style<ProgressBarandroid:layout_width="50dip"android:layout_height="50dip"style="@style/CircleProgressStyle"/>通过以上步骤,基本上就可以实现⾃⼰想要的效果了,这也是我在开发中⼀直习惯使⽤的⽅式,当然了使⽤其它⽅式同样可以实现这种效果,今天我主要是想讲⼀下使⽤AnimationDrawable 和ImageView结合来实现上述效果,所以以上⽅法就不再详解了(如果⼤家想了解其它的⽅式,留你邮箱,给你回信)。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

看到很多人在问如何实现三维的翻转效果,所以今天在这里简单的给大家分析一下,其实在APIDemo中就有这样一个例子,那么我们就以其为例来学习Android中的翻转动画效果的实现,首先看一下运行效果如下图所示。

Android中并没有提供直接做3D翻转的动画,所以关于3D翻转的动画效果需要我们自己实现,那么我们首先来分析一下Animation 和Transformation。

Animation动画的主要接口,其中主要定义了动画的一些属性比如开始时间,持续时间,是否重复播放等等。

而Transformation中则包含一个矩阵和alpha值,矩阵是用来做平移,旋转和缩放动画的,而alpha值是用来做alpha动画的,要实现3D旋转动画我们需要继承自Animation类来实现,我们需要重载getTransformation和applyTransformation,在getTransformation中Animation会根据动画的属性来产生一系列的差值点,然后将这些差值点传给applyTransformation,这个函数将根据这些点来生成不同的Transformation。

下面是具体实现:1.public class Rotate3dAnimation extends Animation {2.//开始角度3. private final float mFromDegrees;4.//结束角度5. private final float mToDegrees;6.//中心点7. private final float mCenterX;8. private final float mCenterY;9. private final float mDepthZ;10.//是否需要扭曲11. private final boolean mReverse;12.//摄像头13. private Camera mCamera;14. public Rotate3dAnimation(float fromDegrees, float toDegrees,15. float centerX, float centerY, float depthZ, boolean reverse) {16. mFromDegrees = fromDegrees;17. mToDegrees = toDegrees;18. mCenterX = centerX;19. mCenterY = centerY;20. mDepthZ = depthZ;21. mReverse = reverse;22. }23.24. @Override25. public void initialize(int width, int height, int parentWidth, int parentHeight) {26. super.initialize(width, height, parentWidth, parentHeight);27. mCamera = new Camera();28. }29.//生成Transformation30. @Override31. protected void applyTransformation(float interpolatedTime, Transformation t) {32. final float fromDegrees = mFromDegrees;33.//生成中间角度34. float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);35.36. final float centerX = mCenterX;37. final float centerY = mCenterY;38. final Camera camera = mCamera;39.40. final Matrix matrix = t.getMatrix();41.42. camera.save();43. if (mReverse) {44. camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);45. } else {46. camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));47. }48. camera.rotateY(degrees);49.//取得变换后的矩阵50. camera.getMatrix(matrix);51. camera.restore();52.53. matrix.preTranslate(-centerX, -centerY);54. matrix.postTranslate(centerX, centerY);55. }56.}其中包括了旋转的开始和结束角度,中心点、是否扭曲、和一个Camera,这里我们主要分析applyTransformation函数,其中第一个参数就是通过getTransformation函数传递的差指点,然后我们根据这个差值通过线性差值算法计算出一个中间角度degrees,Camera 类是用来实现绕Y轴旋转后透视投影的,因此我们首先通过t.getMatrix()取得当前的矩阵,然后通过camera.translate来对矩阵进行平移变换操作,camera.rotateY进行旋转。

这样我们就可以很轻松的实现3D旋转效果了,该例子的原意是通过一个列表来供用户选择要实现翻转的图像,所以我们分析至少需要定义两个控件:ListView和ImageView(要翻转的图像),主界面的xml布局定义如下所示。

1.<FrameLayout xmlns:android="/apk/res/android"2. android:id="@+id/container"3. android:layout_width="match_parent"4. android:layout_height="match_parent">5.6. <ListView7. android:id="@android:id/list"8. android:persistentDrawingCache="animation|scrolling"9. android:layout_width="match_parent"10. android:layout_height="match_parent"11. android:layoutAnimation="@anim/layout_bottom_to_top_slide" />12.13. <ImageView14. android:id="@+id/picture"15. android:scaleType="fitCenter"16. android:layout_width="match_parent"17. android:layout_height="match_parent"18. android:visibility="gone" />19.20.</FrameLayout>然后准备好需要的资源,在onCreate函数中准备好ListView和ImageView,因为要旋转所以我们需要保存视图的缓存信息,通过setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);可以设置该功能,当我们选择列表中的图像资源后在onItemClick中将选择的资源Id对应的图像设置到ImageView中,然后通过applyRotation来启动一个动画,前面有了Rotate3dAnimation的实现,我们要完成3D翻转动画就很简单,直接构建一个Rotate3dAnimation对象,设置其属性(包括动画监听),这里将动画的监听设置为DisplayNextView,可以用来显示下一个视图,在其中的动画结束监听(onAnimationEnd)中,通过一个县城SwapViews来交换两个画面,交换过程则是设置ImageView和ListView 的显示相关属性,并构建一个Rotate3dAnimation对象,对另一个界面进行旋转即可,然后启动动画,整个转换过程实际上就是将第一个界面从0度转好90度,然后就爱你过第二个界面从90度转到0度,这样就形成了一个翻转动画,完整代码如下,我们也加入了一些必要的注解,大家也可以参考APIDemo中的Transition3d例子。

1.public class Transition3d extends Activity implements2. AdapterView.OnItemClickListener, View.OnClickListener {3.//照片列表4. private ListView mPhotosList;5. private ViewGroup mContainer;6. private ImageView mImageView;7.8.// 照片的名字,用于显示在list中9. private static final String[] PHOTOS_NAMES = new String[] {10. "Lyon",11. "Livermore",12. "Tahoe Pier",13. "Lake Tahoe",14. "Grand Canyon",15. "Bodie"16. };17.18.// 资源id19. private static final int[] PHOTOS_RESOURCES = new int[] {20. R.drawable.photo1,21. R.drawable.photo2,22. R.drawable.photo3,23. R.drawable.photo4,24. R.drawable.photo5,25. R.drawable.photo626. };27.28. @Override29. protected void onCreate(Bundle savedInstanceState) {30. super.onCreate(savedInstanceState);31.32. setContentView(yout.animations_main_screen);33.34. mPhotosList = (ListView) findViewById(android.R.id.list);35. mImageView = (ImageView) findViewById(R.id.picture);36. mContainer = (ViewGroup) findViewById(R.id.container);37.38.// 准备ListView39. final ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,40. yout.simple_list_item_1, PHOTOS_NAMES);41.42. mPhotosList.setAdapter(adapter);43. mPhotosList.setOnItemClickListener(this);44.45.// 准备ImageView46. mImageView.setClickable(true);47. mImageView.setFocusable(true);48. mImageView.setOnClickListener(this);49.50.//设置需要保存缓存51. mContainer.setPersistentDrawingCache(ViewGroup.PERSISTENT_ANIMATION_CACHE);52. }53.54./**55. * Setup a new 3D rotation on the container view.56. *57. * @param position the item that was clicked to show a picture, or -1to show the list58. * @param start the start angle at which the rotation must begin59. * @param end the end angle of the rotation60. */61. private void applyRotation(int position, float start, float end) {62.// 计算中心点63. final float centerX = mContainer.getWidth() / 2.0f;64. final float centerY = mContainer.getHeight() / 2.0f;65.66.// Create a new 3D rotation with the supplied parameter67.// The animation listener is used to trigger the next animation68. final Rotate3dAnimation rotation =69. new Rotate3dAnimation(start, end, centerX, centerY, 310.0f, true);70. rotation.setDuration(500);71. rotation.setFillAfter(true);72. rotation.setInterpolator(new AccelerateInterpolator());73.//设置监听74. rotation.setAnimationListener(new DisplayNextView(position));75.76. mContainer.startAnimation(rotation);77. }78.79. public void onItemClick(AdapterView parent, View v, int position, longid) {80.// 设置ImageView81. mImageView.setImageResource(PHOTOS_RESOURCES[position]);82. applyRotation(position, 0, 90);83. }84.//点击图像时,返回listview85. public void onClick(View v) {86. applyRotation(-1, 180, 90);87. }88.89./**90. * This class listens for the end of the first half of the animation.91. * It then posts a new action that effectively swaps the views when the container92. * is rotated 90 degrees and thus invisible.93. */94. private final class DisplayNextView implements Animation.AnimationListener {95. private final int mPosition;96.97. private DisplayNextView(int position) {98. mPosition = position;99. }100.101. public void onAnimationStart(Animation animation) {102. }103.//动画结束104. public void onAnimationEnd(Animation animation) {105. mContainer.post(new SwapViews(mPosition));106. }107.108. public void onAnimationRepeat(Animation animation) {109. }110. }111.112./**113. * This class is responsible for swapping the views and start the second114. * half of the animation.115. */116. private final class SwapViews implements Runnable {117. private final int mPosition;118.119. public SwapViews(int position) {120. mPosition = position;121. }122.123. public void run() {124. final float centerX = mContainer.getWidth() / 2.0f; 125. final float centerY = mContainer.getHeight() / 2.0f; 126. Rotate3dAnimation rotation;127.128. if (mPosition > -1) {129.//显示ImageView130. mPhotosList.setVisibility(View.GONE);131. mImageView.setVisibility(View.VISIBLE);132. mImageView.requestFocus();133.134. rotation = new Rotate3dAnimation(90, 180, centerX, c enterY, 310.0f, false);135. } else {136.//返回listview137. mImageView.setVisibility(View.GONE);138. mPhotosList.setVisibility(View.VISIBLE);139. mPhotosList.requestFocus();140.141. rotation = new Rotate3dAnimation(90, 0, centerX, cen terY, 310.0f, false);142. }143.144. rotation.setDuration(500);145. rotation.setFillAfter(true);146. rotation.setInterpolator(new DecelerateInterpolator()); 147.//开始动画148. mContainer.startAnimation(rotation); 149. }150. }151.152.}。

相关文档
最新文档