我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Android 美食大转盘详解流程

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Android 美食大转盘详解流程

效果视频

前言

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

美食大转盘

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

初始化SurfaceView


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

测量

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


    @Override
    protected 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;

        // 如果需要停止,让转速逐渐变小直到0
        if (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.Turntable
        android:id="@+id/TurnTable"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="20dp"
        android:layout_margin="10dp"
        android:layout_centerInParent="true"/>
        
        <ImageView
        android:id="@+id/StartAndEnd"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        android:class="lazy" data-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封装的知识,请移步到另一篇博文Android SharedPreferences存取操作以及封装详解


private void SelectNumber() {
        RG.setOnCheckedChangeListener( new RadioGroup.OnCheckedChangeListener() {
            @Override
            public 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,代码如下


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="horizontal"
        android:background="#cc00cc"
        android:gravity="center"
        android:paddingTop="20dp">
        <TextView
            android: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;
    
    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;
    
    private int mPadding;

    
    private volatile float mStartAngle = 0;

    
    private boolean isShouldEnd = false;

    
    private long mOneTimeMinMillionSeconds = 50;

    private int mDifferSpeed = 1;// 调用停止后递减的速度差值 要大于0

    public 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);
    }

    @Override
    protected 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]);
        }
    }
    @Override
    public 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();
    }

    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        isRunning = false;
    }

    @Override
    public 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;

        // 如果需要停止,让转速逐渐变小直到0
        if (isShouldEnd) {
            mSpeed -= mDifferSpeed;
        }
        if (mSpeed <= 0) {
            mSpeed = 0;
            isShouldEnd = false;
        }
    }

    
    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);
    }

    
    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);
    }

    
    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 boolean isStart() {
        return mSpeed != 0;
    }

    
    public boolean isShouldEnd() {
        return isShouldEnd;
    }
}

XML布局代码


<RelativeLayout
    xmlns: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">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="80dp"
        android:orientation="horizontal"
        android:background="#cc00cc"
        android:gravity="center"
        android:paddingTop="20dp">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="吃货大赏"
            android:textColor="#ffffff"
            android:textSize="17sp"
            android:padding="10dp"
            />
    </LinearLayout>
    <com.franzliszt.foodturntable.Turntable
        android:id="@+id/TurnTable"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="20dp"
        android:layout_margin="10dp"
        android:layout_centerInParent="true"/>
    <ImageView
        android:id="@+id/StartAndEnd"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_centerInParent="true"
        android:class="lazy" data-src="@drawable/start"
        android:onClick="Start"/>
    <com.franzliszt.foodturntable.AnimatedCircleLoadingView
        android: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"
        />
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/TurnTable"
        android:orientation="vertical"
        android:layout_marginTop="20dp"
        >
        <RadioGroup
            android:id="@+id/RG"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_gravity="center"
            android:gravity="center"
            >
            <RadioButton
                android:id="@+id/fourParts"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="主食"
                android:layout_marginRight="10dp"
                />
            <RadioButton
                android:id="@+id/sixParts"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="外卖"
                android:layout_marginRight="10dp"
                android:layout_marginLeft="10dp"/>
            <RadioButton
                android:id="@+id/eightParts"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="水果"
                android:layout_marginLeft="10dp"/>
        </RadioGroup>
        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:gravity="center"
            android:layout_marginTop="20dp">

            <Button
                android: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" />
            <Button
                android: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;


    @Override
    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();
    }

    private void InitView() {
        turntable = findViewById( R.id.TurnTable );
        loadingView = findViewById( R.id.loadingView );
        ChangeStatus = findViewById( R.id.StartAndEnd );
        RG = findViewById( R.id.RG );
        
        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() {
            @Override
            public 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() {
            @Override
            public void run() {
                loadingView.setPercent( percent );
            }
        } );
    }

    public void resetLoading() {
        runOnUiThread( new Runnable() {
            @Override
            public 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() {
            @Override
            public 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 美食大转盘详解流程的文章就介绍到这了,更多相关Android 美食大转盘内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Android 美食大转盘详解流程

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Android如何实现美食大转盘

这篇文章给大家分享的是有关Android如何实现美食大转盘的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。效果视频初始化SurfaceViewprivate void init() { mSurfac
2023-06-25

详解Android USB转串口通信开发基本流程

好久没有写文章了,年前公司新开了一个项目,是和usb转串口通信相关的,需求是用安卓平板通过usb转接后与好几个外设进行通信,一直忙到最近,才慢慢闲下来,趁着这个周末不忙,记录下usb转串口通信开发的基本流程。 我们开发使用的是usb主机模式
2022-06-06

编程热搜

  • Android:VolumeShaper
    VolumeShaper(支持版本改一下,minsdkversion:26,android8.0(api26)进一步学习对声音的编辑,可以让音频的声音有变化的播放 VolumeShaper.Configuration的三个参数 durati
    Android:VolumeShaper
  • Android崩溃异常捕获方法
    开发中最让人头疼的是应用突然爆炸,然后跳回到桌面。而且我们常常不知道这种状况会何时出现,在应用调试阶段还好,还可以通过调试工具的日志查看错误出现在哪里。但平时使用的时候给你闹崩溃,那你就欲哭无泪了。 那么今天主要讲一下如何去捕捉系统出现的U
    Android崩溃异常捕获方法
  • android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
    系统的设置–>电池–>使用情况中,统计的能耗的使用情况也是以power_profile.xml的value作为基础参数的1、我的手机中power_profile.xml的内容: HTC t328w代码如下:
    android开发教程之获取power_profile.xml文件的方法(android运行时能耗值)
  • Android SQLite数据库基本操作方法
    程序的最主要的功能在于对数据进行操作,通过对数据进行操作来实现某个功能。而数据库就是很重要的一个方面的,Android中内置了小巧轻便,功能却很强的一个数据库–SQLite数据库。那么就来看一下在Android程序中怎么去操作SQLite数
    Android SQLite数据库基本操作方法
  • ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
    工作的时候为了方便直接打开编辑文件,一些常用的软件或者文件我们会放在桌面,但是在ubuntu20.04下直接直接拖拽文件到桌面根本没有效果,在进入桌面后发现软件列表中的软件只能收藏到面板,无法复制到桌面使用,不知道为什么会这样,似乎并不是很
    ubuntu21.04怎么创建桌面快捷图标?ubuntu软件放到桌面的技巧
  • android获取当前手机号示例程序
    代码如下: public String getLocalNumber() { TelephonyManager tManager =
    android获取当前手机号示例程序
  • Android音视频开发(三)TextureView
    简介 TextureView与SurfaceView类似,可用于显示视频或OpenGL场景。 与SurfaceView的区别 SurfaceView不能使用变换和缩放等操作,不能叠加(Overlay)两个SurfaceView。 Textu
    Android音视频开发(三)TextureView
  • android获取屏幕高度和宽度的实现方法
    本文实例讲述了android获取屏幕高度和宽度的实现方法。分享给大家供大家参考。具体分析如下: 我们需要获取Android手机或Pad的屏幕的物理尺寸,以便于界面的设计或是其他功能的实现。下面就介绍讲一讲如何获取屏幕的物理尺寸 下面的代码即
    android获取屏幕高度和宽度的实现方法
  • Android自定义popupwindow实例代码
    先来看看效果图:一、布局
  • Android第一次实验
    一、实验原理 1.1实验目标 编程实现用户名与密码的存储与调用。 1.2实验要求 设计用户登录界面、登录成功界面、用户注册界面,用户注册时,将其用户名、密码保存到SharedPreference中,登录时输入用户名、密码,读取SharedP
    Android第一次实验

目录