美食大转盘

  • 效果视频
    • 前言
      • 美食大转盘
        • 初始化SurfaceView
        • 测量
        • 绘制
          • 绘制圆盘背景
        • 绘制盘块
          • 绘制盘块内文字
          • 绘制盘块内图标
        • 开始旋转转盘
        • 停止旋转转盘
        • 自定义转盘等份
        • 控件引用
          • 布局引用
          • Activity 引用
            • 图标切换
            • 更换转盘等份
      • 沉浸式体验
        • 效果图
          • 建立一个样式
          • 引用空标题栏样式
          • 自定义标题栏
          • 合二为一
      • Reveal Animator
        • 效果视频
          • 建立一个圆形样式
          • 动画设置
    • 自定义转盘代码
    • XML布局代码
    • Activity代码
    • 代码下载地址

效果视频

前言

你还在为明天吃什么而烦恼嘛
美食大赏帮你解决选择困难症
帮你做出最佳的选择
做吃货,我们是认真的

美食大转盘

本示例使用SurfaceView绘制而成,接下来逐步分析,
文末会贴出全部代码``文末会贴出全部代码``文末会贴出全部代码

初始化SurfaceView

    private void init() {mSurfaceHolder = this.getHolder();// 管理SurfaceView的生命周期mSurfaceHolder.addCallback(this);this.setFocusable(true);this.setFocusableInTouchMode(true);this.setKeepScreenOn(true);}

测量

通过获取高、宽,然后减去mPadding 的长度获取到控件中心点,然后存储测量的宽、高

    @Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = Math.min(getMeasuredWidth(), getMeasuredHeight());mPadding = getPaddingLeft();mRadius = width - mPadding * 2;// 中心点mCenter = width / 2;setMeasuredDimension(width, width);}

绘制

绘制圆盘背景

设置背景图片

private Bitmap mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.turntable_bgcolor );

绘制背景突出部分

private void drawBgColor() {mCanvas.drawColor(0xFFFFFFFF);mCanvas.drawBitmap(mBgBitmap, null, new Rect(mPadding / 2, mPadding / 2, getMeasuredWidth() - mPadding / 2, getMeasuredWidth() - mPadding / 2), null);}

绘制盘块

 private void drawArea() {// 起始角度float tempAngle = mStartAngle;// 每个盘块绘制的角度float sweepAngele = 360 / mItemCount;for (int i = 0; i < mItemCount; i++) {mArcPaint.setColor(itemColors[i]);// 绘制盘块mCanvas.drawArc(mRange, tempAngle, sweepAngele, true, mArcPaint);// 绘制文本drawText(tempAngle, sweepAngele, itemCharString[i]);// 绘制图标drawIcon(tempAngle, mBitmaps[i]);tempAngle += sweepAngele;}mStartAngle += mSpeed;// 如果需要停止,让转速逐渐变小直到0if (isShouldEnd) {mSpeed -= mDifferSpeed;}if (mSpeed <= 0) {mSpeed = 0;isShouldEnd = false;}}
绘制盘块内文字
 private void drawText(float tempAngle, float sweepAngele, String itemTextStr) {Path path = new Path();path.addArc(mRange, tempAngle, sweepAngele);// 利用水平偏移量让文字居中float textWidth = mTextPaint.measureText(itemTextStr);int hOffset = (int) (mRadius * Math.PI / mItemCount / 2 - textWidth / 2);// 利用垂直偏移量让文字向圆心靠拢int vOffset = mRadius / 2 / 6;mCanvas.drawTextOnPath(itemTextStr, path, hOffset, vOffset, mTextPaint);}
绘制盘块内图标
private void drawIcon(float tempAngle, Bitmap bitmap) {// 约束图片的宽度,为直径的1/8,可以作为可变参数设置int imgWidth = mRadius / 8;// 获取弧度值float angle = (float) ((tempAngle + 360 / mItemCount / 2) * Math.PI / 180);// 约定图片位置在直径1/4处int x = (int) (mCenter + mRadius / 4 * Math.cos(angle));int y = (int) (mCenter + mRadius / 4 * Math.sin(angle));// 确定图片位置Rect rect = new Rect(x - imgWidth / 2, y - imgWidth / 2, x + imgWidth / 2, y + imgWidth / 2);mCanvas.drawBitmap(bitmap, null, rect, null);}

开始旋转转盘

   public void Start(int index) {if (isStart()) {return;}if (index < 0) {mSpeed = 50 * (1 + Math.random() * (0.5));isShouldEnd = false;return;}}

停止旋转转盘

    public void Stop() {if (isShouldEnd()) {return;}// 将初始角度重置mStartAngle = 0;isShouldEnd = true;}

自定义转盘等份

因为我们要根据需要制作不同等份的转盘,需要跟用户产生交互,所有需要暴露一个方法供用户选择

public void InitNumber(int number){if (number <= 0){return;}/*** 确保为偶数*/if (number % 2 == 0){InitArea(number);}}

本示例以4,6,8等份为例

private void InitArea(int number){switch (number){case 4:fourParts();break;case 6:sixParts();break;case 8:eightParts();break;default:sixParts();}}

每一次选择转盘等份,都需要对View进行重绘,需要多次改变图片数量,所以我们将图片设置成一个公共的方法,避免内存浪费

private void fourParts(){mItemCount = 4;itemCharString = new String[]{"粉条", "面条", "米饭", "粥",};itemImages = new int[]{R.drawable.fen, R.drawable.mian, R.drawable.rice, R.drawable.tang};itemColors = new int[]{0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01};InitImage(mItemCount,itemImages);}
private void InitImage(int count,int[] item){mBitmaps = new Bitmap[mItemCount];for (int i = 0; i < count; i++) {mBitmaps[i] = BitmapFactory.decodeResource(getResources(), item[i]);}}

控件引用

布局引用

XML布局文件内引用如下,其中中间的指针为图片类型

<com.franzliszt.foodturntable.Turntableandroid:id="@+id/TurnTable"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="20dp"android:layout_margin="10dp"android:layout_centerInParent="true"/><ImageViewandroid:id="@+id/StartAndEnd"android:layout_width="100dp"android:layout_height="100dp"android:layout_centerInParent="true"android:src="@drawable/start"android:onClick="Start"/>
Activity 引用

默认设置8等份,如果自定义多种等份,默认必须为最大的等份,不然会出现区域空白

turntable.InitNumber( 8 );
图标切换

对开始与暂停图标进行切换,根据点击次数进行切换

 public void Start(View view) {count++;/*暂停*/if (count % 2 == 0) {turntable.Stop();StartIcon();} else {/*开始*/turntable.Start( -1 );StopIcon();}}
更换转盘等份

首先提供三个RadioButton供用户选择,然后通过SharedPreferences进行存储数据,有关SharedPreferences封装的知识,请移步到另一篇博文SharedPreferences封装

private void SelectNumber() {RG.setOnCheckedChangeListener( new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {switch (checkedId) {case R.id.fourParts:sp.PutData( context, "num", 4 );break;case R.id.sixParts:sp.PutData( context, "num", 6 );break;case R.id.eightParts:sp.PutData( context, "num", 8 );break;}}} );}

然后取出数据,并回调等份数值即可

public void Confirm(View view) {RevealAnim( view );loadingView.setVisibility( View.VISIBLE );startLoading();startPercentMockThread();int num = (int) sp.GetData( context, "num", 0 );turntable.InitNumber( num );}

沉浸式体验

效果图


沉浸式体验即标题栏与系统状态栏主题一致我们分为以下几个步骤完成以上效果

建立一个样式

首先我们需要建立一个标题栏为空的样式,我们有两种方式去实现
第一种,使用系统提供样式

<style name="NotActionBar_1" parent="Theme.AppCompat.Light.NoActionBar"><item name="colorPrimary">@color/colorPrimary</item><item name="colorPrimaryDark">@color/colorPrimaryDark</item><item name="colorAccent">@color/colorAccent</item></style>

第二种,直接使用标志进行设置
其实第一种的源码就是第二种,(废话文学)

<style name="NotActionBar" parent="Theme.AppCompat.Light.DarkActionBar"><!-- Customize your theme here. --><item name="windowNoTitle">true</item><item name="windowActionBar">false</item></style>
引用空标题栏样式

我们需要在我们要隐藏标题栏的Activity中引用如下代码android:theme="@style/NotActionBar"
配置图如下,地址:清单文件中进行配置

自定义标题栏

我们隐藏了标题栏之后,我们需要自定义一个自己喜欢的风格的标题栏
推荐使用ToolBar,本示例为了简单,就直接使用了TextView,代码如下

    <LinearLayoutandroid:layout_width="match_parent"android:layout_height="80dp"android:orientation="horizontal"android:background="#cc00cc"android:gravity="center"android:paddingTop="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="吃货大赏"android:textColor="#ffffff"android:textSize="17sp"android:padding="10dp"/></LinearLayout>
合二为一

终于到了最后一步,我们需要在设置Activity对系统栏进行设置
首先需要对版本进行一个判定,防止版本不兼容
其次获取DecorView实例
然后使用标志符对系统状态进行设置,其中以下两个系统标志符为全屏和隐藏系统状态栏
重中之重,以下代码必须在setContentView( R.layout.activity_main );之前执行
重中之重,以下代码必须在setContentView( R.layout.activity_main );之前执行
重中之重,以下代码必须在setContentView( R.layout.activity_main );之前执行

View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN和View.SYSTEM_UI_FLAG_LAYOUT_STABLE
 protected void onCreate(Bundle savedInstanceState) {super.onCreate( savedInstanceState );if (Build.VERSION.SDK_INT >= 21) {View decorView = getWindow().getDecorView();decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE );getWindow().setStatusBarColor( Color.TRANSPARENT );}setContentView( R.layout.activity_main );InitView();SelectNumber();}

Reveal Animator

效果视频

建立一个圆形样式

首先我们需要建立一个圆形样式,在res->drawable下建立一个oval.xml文件
代码如下:

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"><solid android:color="#cc00cc"/>
</shape>
动画设置

在XML文件中配置我们建立的圆形样式

 android:background="@drawable/oval"

然后再Activity中进行动画设置,其中createCircularReveal()方法的五个参数分别为:控件,动画开始的中心的X,动画开始的中心的Y,动画开始的半径,动画结束的半径

 private void RevealAnim(View view) {Animator animator = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, view.getWidth(), 0);animator.setInterpolator( new AccelerateDecelerateInterpolator() );animator.setDuration( 2000 );animator.start();}

自定义转盘代码

public class Turntable extends SurfaceView implements SurfaceHolder.Callback, Runnable {private SurfaceHolder mSurfaceHolder;private Canvas mCanvas;/*** 用于SurfaceView绘制的子线程*/private Thread mThread;/*** 控制子线程开关*/private boolean isRunning;/*** 字样*/private String[] itemCharString;/*** 图片*/private int[] itemImages;private Bitmap[] mBitmaps;/*** 背景*/private Bitmap mBgBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.turntable_bgcolor );/*** 色块*/private int[] itemColors;/*** 默认等份*/private int mItemCount = 8;/*** 整个盘块的范围*/private RectF mRange = new RectF();/*** 整个盘块的直径*/private int mRadius;/*** 绘制盘块的画笔*/private Paint mArcPaint;/*** 绘制文本的画笔*/private Paint mTextPaint;/*** 字体大小*/private float mTextSize = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_SP, 20, getResources().getDisplayMetrics());/*** 盘块滚动的速度*/private double mSpeed = 0;/*** 转盘的中心位置*/private int mCenter;/*** 这里我们的padding直接取paddingLeft*/private int mPadding;/*** volatile保证线程间的可见性*/private volatile float mStartAngle = 0;/*** 判断是否点击了停止按钮*/private boolean isShouldEnd = false;/*** 设置单次绘制最低时间,如果在该时间内绘制完成,让子线程sleep到改时间结束* 这样防止了线程绘制频繁,先消耗性能的问题*/private long mOneTimeMinMillionSeconds = 50;private int mDifferSpeed = 1;// 调用停止后递减的速度差值 要大于0public Turntable(Context context) {super(context);init();}public Turntable(Context context, AttributeSet attrs) {super(context, attrs);init();}public Turntable(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);init();}public void InitNumber(int number){if (number <= 0){return;}/*** 确保为偶数*/if (number % 2 == 0){InitArea(number);}}private void InitArea(int number){switch (number){case 4:fourParts();break;case 6:sixParts();break;case 8:eightParts();break;default:sixParts();}}private void fourParts(){mItemCount = 4;itemCharString = new String[]{"粉条", "面条", "米饭", "粥",};itemImages = new int[]{R.drawable.fen, R.drawable.mian, R.drawable.rice, R.drawable.tang};itemColors = new int[]{0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01};InitImage(mItemCount,itemImages);}private void sixParts(){mItemCount = 6;itemCharString = new String[]{"火锅", "汉堡", "巧克力", "奶茶", "蛋糕", "炸鸡"};itemImages = new int[]{R.drawable.huoguo, R.drawable.hanbao, R.drawable.qiaokeli, R.drawable.naicha, R.drawable.dangao, R.drawable.zhaji1};itemColors = new int[]{0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01};InitImage(mItemCount,itemImages);}private void eightParts(){mItemCount = 8;itemCharString = new String[]{"苹果", "香蕉", "榴莲", "西瓜", "葡萄", "火龙果","芒果","草莓"};itemImages = new int[]{R.drawable.apple, R.drawable.xaingjiao, R.drawable.liulian, R.drawable.xigua, R.drawable.putao, R.drawable.huolongguo,R.drawable.mangguo,R.drawable.caomei};itemColors = new int[]{0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01, 0xffffc300, 0xfff17e01,0xffffc300,0xfff17e01};InitImage(mItemCount,itemImages);}private void init() {mSurfaceHolder = this.getHolder();// 管理SurfaceView的生命周期mSurfaceHolder.addCallback(this);// 能够获取焦点this.setFocusable(true);this.setFocusableInTouchMode(true);// 保持常亮this.setKeepScreenOn(true);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);int width = Math.min(getMeasuredWidth(), getMeasuredHeight());mPadding = getPaddingLeft();mRadius = width - mPadding * 2;// 中心点mCenter = width / 2;setMeasuredDimension(width, width);}private void InitImage(int count,int[] item){mBitmaps = new Bitmap[mItemCount];for (int i = 0; i < count; i++) {mBitmaps[i] = BitmapFactory.decodeResource(getResources(), item[i]);}}@Overridepublic void surfaceCreated(SurfaceHolder surfaceHolder) {// 初始化盘块画笔mArcPaint = new Paint();mArcPaint.setAntiAlias(true);mArcPaint.setDither(true);// 初始化文字画笔mTextPaint = new Paint();mTextPaint.setColor(0xffffffff);mTextPaint.setTextSize(mTextSize);// 初始化盘块绘制范围mRange = new RectF(mPadding, mPadding, mPadding + mRadius, mPadding + mRadius);// 初始化图片InitImage(mItemCount,itemImages);isRunning = true;mThread = new Thread(this);mThread.start();}@Overridepublic void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {}@Overridepublic void surfaceDestroyed(SurfaceHolder surfaceHolder) {isRunning = false;}@Overridepublic void run() {/*** 不断的进行绘制*/while (isRunning) {long preMillions = System.currentTimeMillis();draw();long afterMillions = System.currentTimeMillis();long drawOnceTime = afterMillions - preMillions;if (drawOnceTime < mOneTimeMinMillionSeconds) {try {Thread.sleep(mOneTimeMinMillionSeconds - drawOnceTime);} catch (InterruptedException e) {e.printStackTrace();}}}}private void draw() {try {mCanvas = mSurfaceHolder.lockCanvas();if (mCanvas != null) {/* 绘制背景颜色*/drawBgColor();/*绘制区域*/drawArea();}} catch (Exception e) {e.printStackTrace();} finally {if (mCanvas != null) {mSurfaceHolder.unlockCanvasAndPost(mCanvas);}}}/*** 绘制盘块*/private void drawArea() {// 起始角度float tempAngle = mStartAngle;// 每个盘块绘制的角度float sweepAngele = 360 / mItemCount;for (int i = 0; i < mItemCount; i++) {mArcPaint.setColor(itemColors[i]);// 绘制盘块mCanvas.drawArc(mRange, tempAngle, sweepAngele, true, mArcPaint);// 绘制文本drawText(tempAngle, sweepAngele, itemCharString[i]);// 绘制图标drawIcon(tempAngle, mBitmaps[i]);tempAngle += sweepAngele;}mStartAngle += mSpeed;// 如果需要停止,让转速逐渐变小直到0if (isShouldEnd) {mSpeed -= mDifferSpeed;}if (mSpeed <= 0) {mSpeed = 0;isShouldEnd = false;}}/*** 绘制每个盘块的图标** @param tempAngle* @param bitmap*/private void drawIcon(float tempAngle, Bitmap bitmap) {// 约束图片的宽度,为直径的1/8,可以作为可变参数设置int imgWidth = mRadius / 8;// 获取弧度值float angle = (float) ((tempAngle + 360 / mItemCount / 2) * Math.PI / 180);// 约定图片位置在直径1/4处int x = (int) (mCenter + mRadius / 4 * Math.cos(angle));int y = (int) (mCenter + mRadius / 4 * Math.sin(angle));// 确定图片位置Rect rect = new Rect(x - imgWidth / 2, y - imgWidth / 2, x + imgWidth / 2, y + imgWidth / 2);mCanvas.drawBitmap(bitmap, null, rect, null);}/*** 绘制每个盘块的文本** @param tempAngle* @param sweepAngele* @param itemTextStr*/private void drawText(float tempAngle, float sweepAngele, String itemTextStr) {Path path = new Path();path.addArc(mRange, tempAngle, sweepAngele);// 利用水平偏移量让文字居中float textWidth = mTextPaint.measureText(itemTextStr);int hOffset = (int) (mRadius * Math.PI / mItemCount / 2 - textWidth / 2);// 利用垂直偏移量让文字向圆心靠拢int vOffset = mRadius / 2 / 6;mCanvas.drawTextOnPath(itemTextStr, path, hOffset, vOffset, mTextPaint);}/*** 绘制背景*/private void drawBgColor() {mCanvas.drawColor(0xFFFFFFFF);mCanvas.drawBitmap(mBgBitmap, null, new Rect(mPadding / 2, mPadding / 2, getMeasuredWidth() - mPadding / 2, getMeasuredWidth() - mPadding / 2), null);}/*** 启动转盘* 能够控制到具体某个index范围内停止*/public void Start(int index) {if (isStart()) {return;}if (index < 0) {mSpeed = 50 * (1 + Math.random() * (0.5));isShouldEnd = false;return;}}/*** 停止转盘*/public void Stop() {if (isShouldEnd()) {return;}// 将初始角度重置mStartAngle = 0;isShouldEnd = true;}/*** 转盘是否在旋转** @return*/public boolean isStart() {return mSpeed != 0;}/*** 是否停止状态(但可能处于旋转减速到停止)** @return*/public boolean isShouldEnd() {return isShouldEnd;}
}

XML布局代码

<RelativeLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="80dp"android:orientation="horizontal"android:background="#cc00cc"android:gravity="center"android:paddingTop="20dp"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:text="吃货大赏"android:textColor="#ffffff"android:textSize="17sp"android:padding="10dp"/></LinearLayout><com.franzliszt.foodturntable.Turntableandroid:id="@+id/TurnTable"android:layout_width="match_parent"android:layout_height="match_parent"android:padding="20dp"android:layout_margin="10dp"android:layout_centerInParent="true"/><ImageViewandroid:id="@+id/StartAndEnd"android:layout_width="100dp"android:layout_height="100dp"android:layout_centerInParent="true"android:src="@drawable/start"android:onClick="Start"/><com.franzliszt.foodturntable.AnimatedCircleLoadingViewandroid:id="@+id/loadingView"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#000000"android:alpha="0.9"android:layout_centerInParent="true"app:animCircleLoadingView_mainColor="#cc00cc"app:animCircleLoadingView_secondaryColor="#ff0000"app:animCircleLoadingView_textColor="@android:color/white"android:visibility="gone"/><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:layout_below="@+id/TurnTable"android:orientation="vertical"android:layout_marginTop="20dp"><RadioGroupandroid:id="@+id/RG"android:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:layout_gravity="center"android:gravity="center"><RadioButtonandroid:id="@+id/fourParts"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="主食"android:layout_marginRight="10dp"/><RadioButtonandroid:id="@+id/sixParts"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="外卖"android:layout_marginRight="10dp"android:layout_marginLeft="10dp"/><RadioButtonandroid:id="@+id/eightParts"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="水果"android:layout_marginLeft="10dp"/></RadioGroup><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal"android:gravity="center"android:layout_marginTop="20dp"><Buttonandroid:id="@+id/ConfirmSelection"android:layout_width="40dp"android:layout_height="50dp"android:layout_alignParentLeft="true"android:layout_alignParentBottom="true"android:layout_marginRight="20dp"android:background="@drawable/oval"android:elevation="4dp"android:onClick="Confirm"android:text="Confirm"android:textAllCaps="false"android:textColor="#ffffff"android:textSize="12sp" /><Buttonandroid:elevation="10dp"android:layout_width="50dp"android:layout_height="50dp"android:text="Reset"android:textSize="12sp"android:textAllCaps="false"android:textColor="#ffffff"android:layout_alignParentRight="true"android:layout_alignParentBottom="true"android:onClick="Reset"android:background="@drawable/oval"android:layout_marginLeft="20dp"/></LinearLayout></LinearLayout>
</RelativeLayout>

Activity代码

public class MainActivity extends AppCompatActivity {private AnimatedCircleLoadingView loadingView;private Turntable turntable;private int count = 0;private ImageView ChangeStatus;private RadioGroup RG;private SP sp;private Context context = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate( savedInstanceState );if (Build.VERSION.SDK_INT >= 21) {View decorView = getWindow().getDecorView();decorView.setSystemUiVisibility( View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_STABLE );getWindow().setStatusBarColor( Color.TRANSPARENT );}setContentView( R.layout.activity_main );InitView();SelectNumber();}private void InitView() {turntable = findViewById( R.id.TurnTable );loadingView = findViewById( R.id.loadingView );ChangeStatus = findViewById( R.id.StartAndEnd );RG = findViewById( R.id.RG );/*默认设置8等份*/turntable.InitNumber( 8 );if (context == null) {context = MainActivity.this;}sp = new SP( context );}public void Start(View view) {count++;/*暂停*/if (count % 2 == 0) {turntable.Stop();StartIcon();} else {/*开始*/turntable.Start( -1 );StopIcon();}}private void StartIcon() {ChangeStatus.setImageDrawable( getResources().getDrawable( R.drawable.start ) );}private void StopIcon() {ChangeStatus.setImageDrawable( getResources().getDrawable( R.drawable.stop ) );}public void Confirm(View view) {RevealAnim( view );loadingView.setVisibility( View.VISIBLE );startLoading();startPercentMockThread();int num = (int) sp.GetData( context, "num", 0 );turntable.InitNumber( num );}public void Reset(View view) {RevealAnim( view );loadingView.setVisibility( View.GONE );resetLoading();}private void startLoading() {loadingView.startIndeterminate();}private void startPercentMockThread() {Runnable runnable = new Runnable() {@Overridepublic void run() {try {Thread.sleep( 500 );for (int i = 0; i <= 100; i++) {Thread.sleep( 40 );changePercent( i );}} catch (InterruptedException e) {e.printStackTrace();}}};new Thread(runnable).start();}private void changePercent(final int percent) {runOnUiThread( new Runnable() {@Overridepublic void run() {loadingView.setPercent( percent );}} );}public void resetLoading() {runOnUiThread( new Runnable() {@Overridepublic void run() {loadingView.resetLoading();}} );}private void RevealAnim(View view) {Animator animator = ViewAnimationUtils.createCircularReveal(view, view.getWidth() / 2, view.getHeight() / 2, view.getWidth(), 0);animator.setInterpolator( new AccelerateDecelerateInterpolator() );animator.setDuration( 2000 );animator.start();}private void SelectNumber() {RG.setOnCheckedChangeListener( new RadioGroup.OnCheckedChangeListener() {@Overridepublic void onCheckedChanged(RadioGroup group, int checkedId) {switch (checkedId) {case R.id.fourParts:sp.PutData( context, "num", 4 );break;case R.id.sixParts:sp.PutData( context, "num", 6 );break;case R.id.eightParts:sp.PutData( context, "num", 8 );break;}}} );}
}

代码下载地址

gitee下载地址

Android美食大赏——做一名合格的吃货相关推荐

  1. 如何做一名合格的甲方项目经理

    本人做过乙方的项目管理,也做过甲方的项目管理,所以结合"围城"内外以不同的角度对甲方项目经理这一角色进行了一些思考,个人认为,做为一名合格的甲方项目经理,应该有以下几个物质,这里说 ...

  2. 生产者(厨师做面条)消费者(吃货吃面条)模式synchronized 法和Lock+Condition法(不使用集合),代码详解

    1. synchronized + wait + notifyAll synchronized:包裹着同步代码块,代码块执行完释放锁 wait:线程挂起,失去锁 notifyAll:唤醒同个对象的wa ...

  3. 做一名合格的网络管理员

    下面就结合我多年的网管从业经历浅谈一下,想要成为一名合格的网络管理员所必须要知道的知识.你不一定非要有网管证书,你不一定非要有CCNA或是其它的什么证书,但下面的东西你必须的会: 1.会重装各类系统. ...

  4. 如何做一名合格的管理者?

    定义管理者 首先,需要定义一下管理者. 我认为,作为一名管理者,需要符合下述条件: 有项目 有能够调动的人力资源(你应该能够直接或间接决定他们的薪水) 被上级管理(如果你位于金字塔的顶端,我认为你不只 ...

  5. MIT:谈如何做一名合格的研究生

    本文的主要内容包括: 一.掌握一些阅读的诀窍. 二.如何成为研究领域的一员:与相关人员保持联系,他们可以使你保持对研究前沿的跟踪,知道应该读什么材料. 三.学习相关领域的知识:对几个领域都有基本的理解 ...

  6. 如何做一名合格的研究生?

    摘要:本文是台湾王汎森院士一篇演讲稿,对所有读研或考研同学非常有意义值得赏析,小编也是在网上无意之中看到的,觉得讲的非常好,也解决了我心中的很多疑惑,所以在此分享出来,与各位即将考研或是准研究生们共勉 ...

  7. js页面加载前执行_做一名合格的前端开发工程师:Javascript加载执行问题探索

    做前端开发少不了各种利器.比如我习惯用的还是Google浏览器和重型武器Fiddller. 一:原始情况 首先大家看看如下的代码: 估计90%的程序员都会把js文件放在head中,但是大家有没有深究过 ...

  8. 如何做一名合格的面试官

    发一篇特别的文章,纪念自己已经写了 100 篇 面试官最主要的 ???? 是判断力,即指:主观地收集.整理.加工客观意识能力 面试官需要具备专业素质:感受能力.心理能力.情绪能力.认知能力.发展意愿. ...

  9. 怎么做一名合格的测试工程师

    我最初参加测试工作的时候,不知道什么是软件测试,集成测试和系统测试的概念经常混淆, CMM 是什么就更加不知道了.那时候最简单的开关机也是通过直接拔插电源完成,安装系统对我来说简直是有史以来人类的最高 ...

最新文章

  1. 手机客户端和web端开发的异同
  2. SPOJ problem 42: Adding Reversed Numbers
  3. NET Core微服务之路:自己动手实现Rpc服务框架,基于DotEasy.Rpc服务框架的介绍和集成...
  4. 工业级PoE交换机是如何进行工作的?使用中要注意什么?
  5. android 360旋转动画,ANDROID——仿360手机卫士的旋转打分控件
  6. mysql 删除了授权_mysql用户授权访问与删除授权
  7. 【Flink】Could not instantiate the executor. Make sure a planner module is on the classpath
  8. Activiti的历史记录级别
  9. chainmaker-go-sdk get cert hash failed, get cert hash failed, send QUERY_SYSTEM_CONTRACT failed
  10. 计算机科学与应用论文,计算机科学与应用论文
  11. 海思35xx移动侦测-修改sdk中sample到嵌入式设备测试成功
  12. VM虚拟机安装苹果雪豹操作系统
  13. 用相关函数法计算信号的延迟量
  14. 动态修改svg图片颜色
  15. EXCEL成绩分出优秀及格与不及格
  16. 开始写博客~~~~~
  17. 权御天下计算机音乐数字乐谱,天谕手游权御天下乐谱代码是什么-天谕手游权御天下乐谱代码分享_快吧手游...
  18. tun驱动之open
  19. 计算机表文件课程 pdf,计算机应用基础课程标准文件.pdf
  20. 图片去水印工具 Inpaint 3.0

热门文章

  1. NFT:使用 EIP-2981 开启 NFT 版税之旅
  2. 小白从零开始在jetson nano上进行YOLOV3-Tiny 与 tensorrt加速检测
  3. Java判断某特殊字符串结尾的2种方法
  4. Linux连接工具(一)XShell7(免费版)下载及安装步骤
  5. 网吧倒闭了,100台电脑回收25万多元,谁说电脑店难经营?
  6. 关于keil的一些基础知识(持续更新)
  7. PG守护进程(Postmaster)——后台二等公民进程第一波启动maybe_start_bgworkers
  8. buuctf——(SUCTF2019)SignIn
  9. 伯乐识英才,我们招聘啦!
  10. 一切编程语言都是纸老虎