实现抽奖轮盘(surfaceView)自定义控件

MainActivity

package com.example.luckyview;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.ImageView;

public class MainActivity extends AppCompatActivity {

    private LuckPan mLuckPan;
    private ImageView mStartBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mLuckPan = findViewById(R.id.id_luckypan);
        mStartBtn = findViewById(R.id.id_start_btn);
        mStartBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                if (!mLuckPan.isStart()){
                    mLuckPan.lucyStart();
                    mStartBtn.setImageResource(R.drawable.stop);
                }else{
                    if (!mLuckPan.isShouldEnd()){
                        mLuckPan.lucyEnd();
                        mStartBtn.setImageResource(R.drawable.start);
                    }
                }
            }
        });
    }
}

Main布局

<?xml version="1.0" encoding="utf-8"?>
<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"
    tools:context=".MainActivity">

    <com.example.luckyview.LuckPan
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="30dp"
        android:layout_centerInParent="true"
        android:id="@+id/id_luckypan"
        />
    <ImageView
        android:id="@+id/id_start_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:src="@drawable/start"
        />

</RelativeLayout>

SurfaceView(没用到)

package com.example.luckyview;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * date:2018/11/3
 * author:
 * function:
 */
public class SurfaceViewImpl extends SurfaceView implements SurfaceHolder.Callback,Runnable{
    private SurfaceHolder holder;
    private Canvas mCanvas;
    //线程的控制开关
    private boolean isruning;
    //用于绘制线程
    private Thread t;

    public SurfaceViewImpl(Context context) {
        this(context,null);
    }

    public SurfaceViewImpl(Context context, AttributeSet attrs) {
        super(context, attrs);

        holder = getHolder();
        holder.addCallback(this);
        //设置可以获得焦点
        setFocusable(true);
        setFocusableInTouchMode(true);
        //设置常量
        setKeepScreenOn(true);

    }

    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {

        isruning = true;
        t = new Thread(this);
        t.start();
    }

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

    }

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

    @Override
    public void run() {

        while(isruning){
            Draw();
        }
    }

    private void Draw() {
        try {
            mCanvas = holder.lockCanvas();

            if (mCanvas !=null){

            }
        }catch (Exception e){

        }finally {
            if (mCanvas != null){
                holder.unlockCanvasAndPost(mCanvas);
            }
        }

    }
}

自定义的控件(LuckyPan)

package com.example.luckyview;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

/**
 * date:2018/11/3
 * author:
 * function:
 */
public class LuckPan extends SurfaceView implements SurfaceHolder.Callback,Runnable{
    private SurfaceHolder holder;
    private Canvas mCanvas;
    //线程的控制开关
    private boolean isruning;
    //用于绘制线程
    private Thread t;

    private String[] mStrs = new String[]{"单反相机","ipad","恭喜发财","IPHONE","服装一套","恭喜发财"};

    private int[] mImgs = new int[]{R.drawable.danfan,R.drawable.ipad,R.drawable.f015,
            R.drawable.iphone,R.drawable.meizi,R.drawable.f040};
    private int[] mColors = new int[]{0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01,0xFFFFC300,0xFFF17E01};

    private int mItemCount=6;

    private Bitmap[] mImgsBitmap;

    private RectF mRange = new RectF();

    private int mRadius ;

    private Paint mArcPaint;

    private Paint mTextPaint;

    private double mSpeed;

    private volatile int mStartAngle = 0;//保证线程间可见性

    private boolean isShouldEnd ;

    private int mCenter;

    //padding 取最小值   或者以left为准
    private int mPadding;

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

    private float mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP,20,getResources().getDisplayMetrics());


    public LuckPan(Context context) {
        this(context,null);
    }

    public LuckPan(Context context, AttributeSet attrs) {
        super(context, attrs);

        holder = getHolder();
        holder.addCallback(this);
        //设置可以获得焦点
        setFocusable(true);
        setFocusableInTouchMode(true);
        //设置常量
        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);
    }

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

        //初始化图片
        mImgsBitmap = new Bitmap[mItemCount];
        for(int i =0 ;i<mItemCount;i++){
            mImgsBitmap[i]=BitmapFactory.decodeResource(getResources(),mImgs[i]);
        }

        isruning = true;
        t = new Thread(this);
        t.start();
    }

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

    }

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

    @Override
    public void run() {

        while(isruning){
            long start = System.currentTimeMillis();

            Draw();

            long end = System.currentTimeMillis();

            if (end - start < 50){
                try {
                    Thread.sleep(50-(end-start));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private void Draw() {
        try {
            mCanvas = holder.lockCanvas();

            if (mCanvas !=null){

                drawBg();

                float tmpAngle = mStartAngle;
                float sweepAngle = 360 / mItemCount;

                for (int i=0;i<mItemCount;i++){
                    mArcPaint.setColor(mColors[i]);

                    //绘制盘快
                    mCanvas.drawArc(mRange,tmpAngle,sweepAngle,true,mArcPaint);

                    DrawText(tmpAngle,sweepAngle,mStrs[i]);

                    DrawIcon(tmpAngle,mImgsBitmap[i]);

                    tmpAngle += sweepAngle;
                }

                mStartAngle += mSpeed;

                //如果点击了停止按钮
                if (isShouldEnd){
                    mSpeed -= 1;
                }
                if (mSpeed <=0){
                    mSpeed = 0;
                    isShouldEnd = false;
                }




            }
        }catch (Exception e){

        }finally {
            if (mCanvas != null){
                holder.unlockCanvasAndPost(mCanvas);
            }
        }

    }

    public void lucyStart(){
        mSpeed = 50;
        isShouldEnd = false;
    }
    public void lucyEnd(){
        isShouldEnd = true;
    }
    public boolean isStart(){
        return mSpeed != 0;
    }
    public boolean isShouldEnd(){
        return isShouldEnd;
    }


    //绘制图片
    private void DrawIcon(float tmpAngle, Bitmap bitmap) {

        //设置图片的宽度为直径的1/8
        int imgWidth = mRadius/8;
        float angle = (float) ((tmpAngle + 360 / mItemCount /2) * Math.PI / 180);
        int x = (int) (mCenter + mRadius /2/2*Math.cos(angle));
        int y = (int) (mCenter + mRadius /2/2*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 tmpAngle, float sweepAngle, String str) {

        Path path = new Path();
        path.addArc(mRange,tmpAngle,sweepAngle);

        //水平偏移量让文字居中

        float textWidth = mTextPaint.measureText(str);
        int hOffest = (int)(mRadius * Math.PI / mItemCount / 2 - textWidth / 2 );

        int vOffest = mRadius/2/6;

        mCanvas.drawTextOnPath(str,path,hOffest,vOffest,mTextPaint);


    }

    private void drawBg() {

        mCanvas.drawColor(0xFFFFFFFF);
        mCanvas.drawBitmap(mBgBitmap,null,new Rect(mPadding/2,
                mPadding/2,getMeasuredWidth()-mPadding/2,
                getMeasuredHeight()-mPadding/2),null);


    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于视频自定义控件,通常可以使用以下方法来实现: 1. 使用 VideoView 控件:Android 提供了 VideoView 控件,可以用来播放视频。通过设置 VideoView 的相关属性和监听器,可以实现自定义控制视频的功能。例如,可以添加播放、暂停、停止、快进、快退等按钮,并在按钮的点击事件中调用 VideoView 的相应方法来控制视频的播放。 2. 自定义播放器控件:你可以创建一个继承自 View 或 ViewGroup 的自定义控件,用于显示视频播放器的界面,并处理用户交互事件。在自定义控件中,你可以使用 SurfaceView 来渲染视频画面,并使用 MediaPlayer 或 ExoPlayer 等播放器库来实现视频的控制和处理。 3. 使用第三方库:除了 Android 默认提供的 VideoView 和 MediaPlayer,还有一些第三方视频播放库可以使用。例如,IjkPlayer、VLC for Android、ExoPlayer 等,这些库提供了更多的功能和灵活性,可以更容易地实现自定义的视频控制界面。 无论选择哪种方式,你需要考虑以下几个方面: - 视频播放控制:包括开始、暂停、停止、快进、快退等功能。 - 视频进度显示:显示当前播放进度和总时长,并可以拖动进度条进行快进/快退。 - 音量和亮度控制:可以调节视频的音量和屏幕亮度。 - 全屏播放:提供全屏播放功能,并处理屏幕旋转时的适配问题。 - 异常处理:处理视频播放异常、网络异常等情况,并给出用户友好的提示。 希望这些信息能对你有所帮助!如有需要,还请提供更具体的需求,我可以给出更详细的解决方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值