Android自定义View实现QQ音乐中圆形旋转碟子

QQ音乐中圆形旋转碟子

思路分析:
1、在onMeasure中测量整个View的宽和高后,设置宽高
2、获取我们res的图片资源后,在ondraw方法中进行绘制圆形图片
3、通过Handler发送Runnable来启动旋转线程(如果只想做圆形头像的话,这步可以去掉)
4、在布局中使用我们的View

效果图:

贴出我们的变量信息:

//view的宽和高
int mHeight = 0;
int mWidth = 0;
//圆形图片
Bitmap bitmap = null;
//圆形图片的真实半径
int radius = 0;
//旋转动画的矩形
Matrix matrix = new Matrix();
//旋转动画的角度
int degrees = 0;

步骤一:测量整个View的宽和高后,设置宽高

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
 super.onMeasure(widthMeasureSpec, heightMeasureSpec);
 //测量整个View的宽和高
 mWidth = measuredWidth(widthMeasureSpec);
 mHeight= measuredHeight(heightMeasureSpec);
 setMeasuredDimension(mWidth, mHeight);
} 

private int measuredWidth(int widthMeasureSpec) {
 int Mode = MeasureSpec.getMode(widthMeasureSpec);
 int Size = MeasureSpec.getSize(widthMeasureSpec);
 if (Mode == MeasureSpec.EXACTLY) {
  mWidth = Size;
 } else {
  //由图片决定宽度
  int value = getPaddingLeft() + getPaddingRight() + bitmap.getWidth();
  if (Mode == MeasureSpec.AT_MOST) {
   //由图片和Padding决定宽度,但是不能超过View的宽
   mWidth = Math.min(value, Size);
  }
 }
 return mWidth;
} 

private int measuredHeight(int heightMeasureSpec) {
 int Mode = MeasureSpec.getMode(heightMeasureSpec);
 int Size = MeasureSpec.getSize(heightMeasureSpec);
 if (Mode == MeasureSpec.EXACTLY) {
  mHeight = Size;
 } else {
  //由图片决定高度
  int value = getPaddingTop() + getPaddingBottom() + bitmap.getHeight();
  if (Mode == MeasureSpec.AT_MOST) {
   //由图片和Padding决定高度,但是不能超过View的高
   mHeight = Math.min(value, Size);
  }
 }
 return mHeight;
} 

步骤二:获取我们res的图片资源后,在ondraw方法中进行绘制圆形图片

//获取res的图片资源
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
@Override
protected void onDraw(Canvas canvas) {
 super.onDraw(canvas);
 canvas.concat(matrix);
 //真实的半径必须是View的宽高最小值
 radius = Math.min(mWidth, mHeight);
 //如果图片本身宽高太大,进行相应的缩放
 bitmap = Bitmap.createScaledBitmap(bitmap, radius, radius, false);
 //画圆形图片
 canvas.drawBitmap(createCircleImage(bitmap, radius), 0, 0, null);
 matrix.reset();
} 

private Bitmap createCircleImage(Bitmap source, int radius) {
 Paint paint = new Paint();
 paint.setAntiAlias(true);
 Bitmap target = Bitmap.createBitmap(radius, radius, Bitmap.Config.ARGB_8888);
 //产生一个同样大小的画布
 Canvas canvas = new Canvas(target);
 //首先绘制圆形
 canvas.drawCircle(radius / 2, radius / 2, radius / 2, paint);
 //使用SRC_IN模式显示后画图的交集处
 paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
 //绘制图片,从(0,0)画
 canvas.drawBitmap(source, 0, 0, paint);
 return target;
}

步骤三:通过Handler发送Runnable来启动旋转线程

//开始旋转
mHandler.post(runnable);
[java] view plain copy 在CODE上查看代码片派生到我的代码片
//-----------旋转动画-----------
Handler mHandler = new Handler();
Runnable runnable = new Runnable() {
 @Override
 public void run() {
  matrix.postRotate(degrees++, radius / 2, radius / 2);
  //重绘
  invalidate();
  mHandler.postDelayed(runnable, 50);
 }
};

步骤四:在布局中使用我们的View

<com.handsome.cycle.MyCycleView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content" />

下面是整个类的源码

public class MyCycleView extends View { 

 //view的宽和高
 int mHeight = 0;
 int mWidth = 0;
 //圆形图片
 Bitmap bitmap = null;
 //圆形图片的真实半径
 int radius = 0;
 //旋转动画的矩形
 Matrix matrix = new Matrix();
 //旋转动画的角度
 int degrees = 0; 

 //-----------旋转动画-----------
 Handler mHandler = new Handler();
 Runnable runnable = new Runnable() {
  @Override
  public void run() {
   matrix.postRotate(degrees++, radius / 2, radius / 2);
   //重绘
   invalidate();
   mHandler.postDelayed(runnable, 50);
  }
 }; 

 public MyCycleView(Context context) {
  super(context);
  initView();
 } 

 public MyCycleView(Context context, AttributeSet attrs) {
  super(context, attrs);
  initView();
 } 

 public MyCycleView(Context context, AttributeSet attrs, int defStyleAttr) {
  super(context, attrs, defStyleAttr);
  initView();
 } 

 public void initView() {
  //获取res的图片资源
  bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
  //开始旋转
  mHandler.post(runnable);
 } 

 @Override
 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  //测量整个View的宽和高
  mWidth = measuredWidth(widthMeasureSpec);
  mHeight = measuredHeight(heightMeasureSpec);
  setMeasuredDimension(mWidth, mHeight);
 } 

 private int measuredWidth(int widthMeasureSpec) {
  int Mode = MeasureSpec.getMode(widthMeasureSpec);
  int Size = MeasureSpec.getSize(widthMeasureSpec);
  if (Mode == MeasureSpec.EXACTLY) {
   mWidth = Size;
  } else {
   //由图片决定宽度
   int value = getPaddingLeft() + getPaddingRight() + bitmap.getWidth();
   if (Mode == MeasureSpec.AT_MOST) {
    //由图片和Padding决定宽度,但是不能超过View的宽
    mWidth = Math.min(value, Size);
   }
  }
  return mWidth;
 } 

 private int measuredHeight(int heightMeasureSpec) {
  int Mode = MeasureSpec.getMode(heightMeasureSpec);
  int Size = MeasureSpec.getSize(heightMeasureSpec);
  if (Mode == MeasureSpec.EXACTLY) {
   mHeight = Size;
  } else {
   //由图片决定高度
   int value = getPaddingTop() + getPaddingBottom() + bitmap.getHeight();
   if (Mode == MeasureSpec.AT_MOST) {
    //由图片和Padding决定高度,但是不能超过View的高
    mHeight = Math.min(value, Size);
   }
  }
  return mHeight;
 } 

 @Override
 protected void onDraw(Canvas canvas) {
  super.onDraw(canvas);
  canvas.concat(matrix);
  //真实的半径必须是View的宽高最小值
  radius = Math.min(mWidth, mHeight);
  //如果图片本身宽高太大,进行相应的缩放
  bitmap = Bitmap.createScaledBitmap(bitmap, radius, radius, false);
  //画圆形图片
  canvas.drawBitmap(createCircleImage(bitmap, radius), 0, 0, null);
  matrix.reset();
 } 

 private Bitmap createCircleImage(Bitmap source, int radius) {
  Paint paint = new Paint();
  paint.setAntiAlias(true);
  Bitmap target = Bitmap.createBitmap(radius, radius, Bitmap.Config.ARGB_8888);
  //产生一个同样大小的画布
  Canvas canvas = new Canvas(target);
  //首先绘制圆形
  canvas.drawCircle(radius / 2, radius / 2, radius / 2, paint);
  //使用SRC_IN模式显示后画图的交集处
  paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
  //绘制图片,从(0,0)画
  canvas.drawBitmap(source, 0, 0, paint);
  return target;
 }
} 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android自定义View实现飘动的叶子效果(三)

    上一篇对自定义View及一些方法有所了解,下面做一个简单的叶子飘动的例子 主要技术点 1.添加背景图片canvas.drawBitmap() 2.Matrix动画类 3.Matrix添加到画布上 步骤 1.添加黄色背景颜色 public LeafView(Context context, AttributeSet attrs) { super(context, attrs); bgPaint = new Paint(); bgPaint.setColor(mResources.getColor(

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

    提起ProgressBar,想必大家都比较熟悉,使用起来也是比较方便,直接在XML文件中引用,然后添加属性,运行就OK了,虽然使用ProgressBar很方便但是在我们开发的每一个应用基本上都有自己的主体风格,如果使用了系统自带的效果图,给人的感觉是和总体风格太不搭配了,看上去很是别扭,我们自己开发也觉得不爽,于是就想着自定义一下效果,其实自定义ProgressBar的效果也不难,大概可分为三步走吧: 一.在anim文件夹下使用animation-list定义动画集 <?xml version=

  • Android自定义View叶子旋转完整版(六)

    上一篇实现多叶子飘动旋转,今天完成最后的功能. 1.添加右侧旋转枫叶 2.添加滑动条效果,显示百分比 3.修复叶子飘出边框问题 1.添加右侧旋转叶子 Bitmap turnBitmap = ((BitmapDrawable) mResources.getDrawable(R.drawable.fengshan, null)).getBitmap(); int turnLeafAngle = 0; private void setTurnLeaf(Canvas canvas) { Matrix m

  • Android自定义View实现多片叶子旋转滑动(五)

    上一篇<Android 自定义View(四) 叶子飘动+旋转效果>实现了单片叶子的滑动及旋转,下面实现多片叶子的滑动旋转功能 实现思路比较简单,就是添加一个叶子Leaf类,储存每片叶子的信息, 然后随机产生叶子的坐标及旋转角度,最后实时获取每片叶子信息,添加到画布中 1.Leaf.java 叶子类 private class Leaf { // 叶子的坐标 float x, y; // 旋转角度 int rotateAngle; // 起始时间(ms) long startTime; } 2.

  • Android自定义View实现叶子飘动旋转效果(四)

    上一篇实现了叶子飘动功能,<Android自定义叶子飘动> 现在实现旋转效果 要实现这个效果,要在之前的功能上添加2个功能 1.通过matrix.postTranslate(int x, int y)在添加在Y轴上滑动 2.通过matrix.postRotate(float degrees, float px, float py)实现叶子旋转 代码实现 1.获取Y坐标 private float getMatrixY() { float w = (float) ((float) 2 * Mat

  • Android UI之ImageView实现图片旋转和缩放

    这一篇,给大家介绍一下ImageView控件的使用,ImageView主要是用来显示图片,可以对图片进行放大.缩小.旋转的功能. android:sacleType属性指定ImageVIew控件显示图片的方式,例如:center表示图像以不缩放的方式显示在ImageView控件的中心,如果设置为fitCenter,表示图像按照比例缩放至合适的位置,并在ImageView控件的中心. 首先我们开发一个简单的案例,实现图片的放大缩小和旋转: 先看看实现的效果: 缩放截图1: 缩放截图2: 旋转截图1

  • Android使用RotateImageView 旋转ImageView

    废话不多说了,直接给大家代码. 具体代码如下所示: package com.droidhen.game.layout; import android.content.Context; import android.graphics.Bitmap; import android.graphics.Bitmap.Config; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.

  • Android自定义View实现QQ音乐中圆形旋转碟子

    QQ音乐中圆形旋转碟子 思路分析: 1.在onMeasure中测量整个View的宽和高后,设置宽高 2.获取我们res的图片资源后,在ondraw方法中进行绘制圆形图片 3.通过Handler发送Runnable来启动旋转线程(如果只想做圆形头像的话,这步可以去掉) 4.在布局中使用我们的View 效果图: 贴出我们的变量信息: //view的宽和高 int mHeight = 0; int mWidth = 0; //圆形图片 Bitmap bitmap = null; //圆形图片的真实半径

  • Android自定义View 仿QQ侧滑菜单的实现代码

    先看看QQ的侧滑效果 分析一下 先上原理图(不知道能否表达的清楚 ==) -首先这里使用了 Android 的HorizontalScrollView 水平滑动布局作为容器,当然我们需要继承它自定义一个侧滑视图 - 这个容器里面有一个父布局(一般用LinerLayout,本demo用的是),这个父布局里面有且只有两个子控件(布局),初始状态菜单页的位置在Y轴上存在偏移这样可以就可以形成主页叠在菜单页的上方的视觉效果:然后在滑动的过程程中 逐渐修正偏移,最后菜单页和主页并排排列.原理搞清了实现起来

  • Android自定义View实现QQ消息气泡

    本文实例为大家分享了Android自定义View实现QQ消息气泡的具体代码,供大家参考,具体内容如下 效果图: 原理: 控件源码: public class DragView extends View {     private int defaultZoomSize = 8;     //初始化圆的大小     private int initRadius;     //圆1的圆心位置     private PointF center1;     private PointF center2

  • Android自定义View绘制贝塞尔曲线中小红点的方法

    目录 前言 需求 效果图 代码 主要问题 简单画法 使用贝塞尔曲线 前言 上一篇文章用扇形图练习了一下安卓的多点触控,实现了单指旋转.二指放大.三指移动,四指以上同时按下进行复位的功能.今天这篇文章用很多应用常见的小红点,来练习一下贝塞尔曲线的使用. 需求 这里想法来自QQ的拖动小红点取消显示聊天条数功能,不过好像是记忆里的了,现在看了下好像效果变了.总而言之,就是一个小圆点,拖动的时候变成水滴状,超过一定范围后触发消失回调,核心思想如下: 1.一个正方形view,中间是小红点,小红点距离边框有

  • Android自定义view仿QQ的Tab按钮动画效果(示例代码)

    话不多说 先上效果图 实现其实很简单,先用两张图 一张是背景的图,一张是笑脸的图片,笑脸的图片是白色,可能看不出来.实现思路:主要是再触摸view的时候同时移动这两个图片,但是移动的距离不一样,造成的错位感,代码很简单: import android.content.Context import android.graphics.* import android.util.AttributeSet import android.view.MotionEvent import android.vi

  • Android自定义View图片按Path运动和旋转

    本文实例为大家分享了Android自定义View图片按Path运动旋转的具体代码,供大家参考,具体内容如下 View: /** * author : stone * email : aa86799@163.com * time : 16/5/29 15 29 */ public class EarthPathView extends View { private Path mPath; private Paint mPaint; private Bitmap mBitmap; private P

  • Android自定义View实现QQ运动积分转盘抽奖功能

    因为偶尔关注QQ运动, 看到QQ运动的积分抽奖界面比较有意思,所以就尝试用自定义View实现了下,原本想通过开发者选项查看下界面的一些信息,后来发现积分抽奖界面是在WebView中展示的,应该是在H5页面中用js代码实现的,暂时不去管它了. 这里的自定义View针对的是继承自View的情况,你可以将Canvas想象为画板, Paint为画笔,自定义View的过程和在画板上用画笔作画其实类似,想象在画板上作画的过程,你要画一个多大图形(对应View的测量 onMeasure方法),你要画什么样的图

  • Android自定义View仿QQ健康界面

    最近一直在学习自定义View相关的知识,今天给大家带来的是QQ健康界面的实现.先看效果图: 可以设置数字颜色,字体颜色,运动步数,运动排名,运动平均步数,虚线下方的蓝色指示条的长度会随着平均步数改变而进行变化.整体效果还是和QQ运动健康界面很像的. 自定义View四部曲,一起来看看怎么实现的. 1.自定义view的属性: <?xml version="1.0" encoding="utf-8"?> <resources> //自定义属性名,定

  • Android自定义View仿QQ运动步数效果

    本文实例为大家分享了Android QQ运动步数的具体代码,供大家参考,具体内容如下 今天我们实现下面这样的效果: 首先自定义属性: <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyQQStep"> <attr name="out_color" format="colo

  • Android自定义View仿QQ等级天数进度

    最近一直都在看自定义View这一块.差不多一个星期了吧.这个星期坚持每天更新博客,感觉自己的技术也有点突破,对自定义View的计算也有了更深的认识. 今天看到手机一个成长天数进度的控件,觉得挺有意思的,于是想自己也写一个.效果如下: 由图可以知道,这里面有很多个元素,首先是背景的矩形区域,其次就是两个环形,然后三个Text文本.其实不复杂,我们一点一点的去实现. 首先呢,画矩形背景.这里用到一个RectF的类,这个类包含一个矩形的四个单精度浮点坐标.矩形通过上下左右4个边的坐标来表示一个矩形.这

随机推荐