效果:
实现大转盘主要工作还是图片的处理,以及自定义view中的控件定位
下面来操作吧:
旋转的箭头图:
自定义view代码:
package bw.com.zhuanpan.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Typeface; import android.os.Build; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.WindowManager; import java.util.ArrayList; import java.util.List; /** * Created by mypc on 2018/1/3. */ public class Turnplate extends View { private Context context; private final float StrarLocation=270; private Paint paint; private float mRadios;//绘制的角度 private List<String> listText;//显示的文字 private List<Float>listRadios;//每个特定弧度的中心位置 private int mCount;//绘制的次数 private List<Integer>listColor;//每个弧度的颜色(最大数目10个) public Turnplate(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.context=context;//此构造方法会在xml生成时调用,而不是在Activity使用中调用 paint=new Paint(); paint.setAntiAlias(true); Path path=new Path();//初始化路径path listText=new ArrayList<>(); listRadios=new ArrayList<>(); listColor=new ArrayList<>();//测试用的颜色,方便给每个item添加不同颜色 listColor.add(0xFF0b87f4);//色值不能在此引用xml中的数据,否则不起效果,必须以16进制形式添加 listColor.add(0xFFc316de); listColor.add(0xFFcbce25); listColor.add(0xFFf47378); listColor.add(0xFF18dfd8); listColor.add(0xFF7d1ed1); listColor.add(0xFFe6a1ef); listColor.add(0xFFfdd700); listColor.add(0xfba0ec25); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (listText!=null&&listText.size()>0){ //初始化绘制文字的画笔 Paint mTextPaint=new Paint(); mTextPaint.setColor(Color.WHITE); mTextPaint.setAntiAlias(true); mTextPaint.setDither(true); if(Build.VERSION.SDK_INT>20){ mTextPaint.setLetterSpacing(0.1f); } mTextPaint.setTextAlign(Paint.Align.CENTER);//设置文本内容的位置 mTextPaint.setTextSize(30);//设置文本字体大小 Typeface typeface=Typeface.create(Typeface.MONOSPACE , Typeface.NORMAL); mTextPaint.setTypeface(typeface); float startRadios=270-mRadios/2; RectF rectF=new RectF(0,0,canvas.getWidth(),canvas.getHeight()); for (int i=0;i<listText.size();i++){ if (i<listColor.size()-1){ paint.setColor(listColor.get(i)); } else { paint.setColor(Color.WHITE); } Path path=new Path(); path.addArc(rectF, startRadios, mRadios); float textWidth = mTextPaint.measureText(listText.get(i)); Paint.FontMetrics metrics=mTextPaint.getFontMetrics(); float assent=metrics.ascent; float descent=metrics.descent; float height=(descent-assent); canvas.drawArc(rectF, startRadios, mRadios, true, paint); canvas.drawTextOnPath(listText.get(i),path,0,height,mTextPaint); startRadios+=mRadios; } //测试用 if (listRadios!=null&&listRadios.size()>0){ for (int i=0;i<listRadios.size();i++){ Log.i("listRadios--i--"+i,"==="+listRadios.get(i)); } } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //view的宽高度相等,大小为屏幕宽度的3/4 WindowManager manager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); int width=manager.getDefaultDisplay().getWidth(); width-=width/4; setMeasuredDimension(width, width); } /* * 设置显示的文字 * */ public void setText(String[] text){ try { mCount=text.length; if (mCount<1){ mCount=1; } for (int i=0;i<text.length;i++){ listText.add(text[i]); } mRadios=360.0f/mCount;//每个item所占的弧度 Log.i("mRadios===",""+mRadios); Log.i("mCount===",""+mCount); //-------------------- for (int i=0;i<listText.size();i++) { float start = 270 + mRadios * i; if (start < 360) { listRadios.add(start); } else { listRadios.add(start - 360); } } invalidate(); } catch (Exception e){ Log.e("Turnplate-setText-","传入的字符串数组为空,请确认"); } } /* * 获取每个环的弧度 * */ public float getMyRadios(){ return mRadios; } public float getStartRadios(){//获取开始的角度 return StrarLocation; } //获取所有选项中心位置的弧度数目 public List<Float>getRadioList(){ return listRadios; } }
Activity的代码:
package bw.com.zhuanpan; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.ImageView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import java.util.Random; import bw.com.zhuanpan.view.Turnplate; public class MainActivity extends AppCompatActivity { private Turnplate turnplate; private ImageView image; private RotateAnimation anim; private float rot; private ImageView imageA; private Float StartRadios;//转盘起始的位置 private int CurrentRadiosId;//转盘当前所处的位置 private List<Float> listRadios; private List<Float>listImaRadios; private int round;//用于产生随机数 private String[]text={"谢谢抽奖","中奖1元","中奖2元","中奖5元", "中奖10元","中奖50元","中奖100元"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); turnplate= (Turnplate) findViewById(R.id.turnplate); image= (ImageView) findViewById(R.id.image); // imageA= (ImageView) findViewById(R.id.imageA); round=text.length; turnplate.setText(text); StartRadios=turnplate.getStartRadios(); CurrentRadiosId=0; listRadios=new ArrayList<>(); listRadios=turnplate.getRadioList(); listImaRadios=new ArrayList<>(); for (int i=0;i<listRadios.size();i++){ float rado=listRadios.get(i)-270; if (rado>0|rado==0){ listImaRadios.add(rado); } else { listImaRadios.add(360+rado); } Log.i("---------listImag",""+listImaRadios.get(i)); } } /* * 转动的view * */ public void rotate(View view) { //产生0-round之间的随机数 image.setClickable(false); int sc=new Random().nextInt(round); // Log.i("产生的随机数---"+sc,"item的总数目--"+round); Log.i("当前item的id===" + CurrentRadiosId, "结束的item的id==" + sc); rotateTo(CurrentRadiosId, sc);//从当前的id旋转到sc CurrentRadiosId=sc;//记录新的当前id } private void rotateTo(int currentId, int rotateId) { float curRadio=listRadios.get(currentId);//当前的item的弧度 float rotaRadio=listRadios.get(rotateId);//结束的item的弧度 // if (curRadio-rotaRadio>0){ // rot=360-curRadio+rotaRadio; // } // else if (curRadio-rotaRadio==0){ // rot=0; // } // else { // rot=rotaRadio-curRadio; // } float rotateRadio=360*4+listImaRadios.get(rotateId);//总的旋转度数 // Log.i("开始转动的弧度-qq====" + listImaRadios.get(currentId), "转动的弧度====" + rot); // Log.i("开始转动的item位置"+currentId,"结束时的item位置"+rotateId); anim=new RotateAnimation(listImaRadios.get(currentId),rotateRadio, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.7f); anim.setDuration(2000); anim.setFillAfter(true); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { image.setClickable(true); Toast.makeText(MainActivity.this,""+text[CurrentRadiosId],Toast.LENGTH_SHORT).show(); // Log.i("转动结束后的当前item===", "" + CurrentRadiosId); Log.i("----------","---------------------------------------------"); } @Override public void onAnimationRepeat(Animation animation) { } }); //启动动画 image.startAnimation(anim); } }
布局:
<?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" tools:context="bw.com.zhuanpan.MainActivity"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <bw.com.zhuanpan.view.Turnplate android:background="#aaeeaa" android:id="@+id/turnplate" android:layout_gravity="center" android:layout_width="100dp" android:layout_height="100dp" /> <ImageView android:id="@+id/image" android:clickable="true" android:onClick="rotate" android:src="@mipmap/chou" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="-20dp"/> </FrameLayout> </RelativeLayout>
Android实现大转盘带吐司作用域
效果:
实现大转盘主要工作还是图片的处理,以及自定义view中的控件定位
下面来操作吧:
旋转的箭头图:
自定义view代码:
package bw.com.zhuanpan.view; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.graphics.Path; import android.graphics.RectF; import android.graphics.Typeface; import android.os.Build; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.WindowManager; import java.util.ArrayList; import java.util.List; /** * Created by mypc on 2018/1/3. */ public class Turnplate extends View { private Context context; private final float StrarLocation=270; private Paint paint; private float mRadios;//绘制的角度 private List<String> listText;//显示的文字 private List<Float>listRadios;//每个特定弧度的中心位置 private int mCount;//绘制的次数 private List<Integer>listColor;//每个弧度的颜色(最大数目10个) public Turnplate(Context context, @Nullable AttributeSet attrs) { super(context, attrs); this.context=context;//此构造方法会在xml生成时调用,而不是在Activity使用中调用 paint=new Paint(); paint.setAntiAlias(true); Path path=new Path();//初始化路径path listText=new ArrayList<>(); listRadios=new ArrayList<>(); listColor=new ArrayList<>();//测试用的颜色,方便给每个item添加不同颜色 listColor.add(0xFF0b87f4);//色值不能在此引用xml中的数据,否则不起效果,必须以16进制形式添加 listColor.add(0xFFc316de); listColor.add(0xFFcbce25); listColor.add(0xFFf47378); listColor.add(0xFF18dfd8); listColor.add(0xFF7d1ed1); listColor.add(0xFFe6a1ef); listColor.add(0xFFfdd700); listColor.add(0xfba0ec25); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (listText!=null&&listText.size()>0){ //初始化绘制文字的画笔 Paint mTextPaint=new Paint(); mTextPaint.setColor(Color.WHITE); mTextPaint.setAntiAlias(true); mTextPaint.setDither(true); if(Build.VERSION.SDK_INT>20){ mTextPaint.setLetterSpacing(0.1f); } mTextPaint.setTextAlign(Paint.Align.CENTER);//设置文本内容的位置 mTextPaint.setTextSize(30);//设置文本字体大小 Typeface typeface=Typeface.create(Typeface.MONOSPACE , Typeface.NORMAL); mTextPaint.setTypeface(typeface); float startRadios=270-mRadios/2; RectF rectF=new RectF(0,0,canvas.getWidth(),canvas.getHeight()); for (int i=0;i<listText.size();i++){ if (i<listColor.size()-1){ paint.setColor(listColor.get(i)); } else { paint.setColor(Color.WHITE); } Path path=new Path(); path.addArc(rectF, startRadios, mRadios); float textWidth = mTextPaint.measureText(listText.get(i)); Paint.FontMetrics metrics=mTextPaint.getFontMetrics(); float assent=metrics.ascent; float descent=metrics.descent; float height=(descent-assent); canvas.drawArc(rectF, startRadios, mRadios, true, paint); canvas.drawTextOnPath(listText.get(i),path,0,height,mTextPaint); startRadios+=mRadios; } //测试用 if (listRadios!=null&&listRadios.size()>0){ for (int i=0;i<listRadios.size();i++){ Log.i("listRadios--i--"+i,"==="+listRadios.get(i)); } } } } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //view的宽高度相等,大小为屏幕宽度的3/4 WindowManager manager= (WindowManager) context.getSystemService(Context.WINDOW_SERVICE); int width=manager.getDefaultDisplay().getWidth(); width-=width/4; setMeasuredDimension(width, width); } /* * 设置显示的文字 * */ public void setText(String[] text){ try { mCount=text.length; if (mCount<1){ mCount=1; } for (int i=0;i<text.length;i++){ listText.add(text[i]); } mRadios=360.0f/mCount;//每个item所占的弧度 Log.i("mRadios===",""+mRadios); Log.i("mCount===",""+mCount); //-------------------- for (int i=0;i<listText.size();i++) { float start = 270 + mRadios * i; if (start < 360) { listRadios.add(start); } else { listRadios.add(start - 360); } } invalidate(); } catch (Exception e){ Log.e("Turnplate-setText-","传入的字符串数组为空,请确认"); } } /* * 获取每个环的弧度 * */ public float getMyRadios(){ return mRadios; } public float getStartRadios(){//获取开始的角度 return StrarLocation; } //获取所有选项中心位置的弧度数目 public List<Float>getRadioList(){ return listRadios; } }
Activity的代码:
package bw.com.zhuanpan; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.view.animation.Animation; import android.view.animation.RotateAnimation; import android.widget.ImageView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import java.util.Random; import bw.com.zhuanpan.view.Turnplate; public class MainActivity extends AppCompatActivity { private Turnplate turnplate; private ImageView image; private RotateAnimation anim; private float rot; private ImageView imageA; private Float StartRadios;//转盘起始的位置 private int CurrentRadiosId;//转盘当前所处的位置 private List<Float> listRadios; private List<Float>listImaRadios; private int round;//用于产生随机数 private String[]text={"谢谢抽奖","中奖1元","中奖2元","中奖5元", "中奖10元","中奖50元","中奖100元"}; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); turnplate= (Turnplate) findViewById(R.id.turnplate); image= (ImageView) findViewById(R.id.image); // imageA= (ImageView) findViewById(R.id.imageA); round=text.length; turnplate.setText(text); StartRadios=turnplate.getStartRadios(); CurrentRadiosId=0; listRadios=new ArrayList<>(); listRadios=turnplate.getRadioList(); listImaRadios=new ArrayList<>(); for (int i=0;i<listRadios.size();i++){ float rado=listRadios.get(i)-270; if (rado>0|rado==0){ listImaRadios.add(rado); } else { listImaRadios.add(360+rado); } Log.i("---------listImag",""+listImaRadios.get(i)); } } /* * 转动的view * */ public void rotate(View view) { //产生0-round之间的随机数 image.setClickable(false); int sc=new Random().nextInt(round); // Log.i("产生的随机数---"+sc,"item的总数目--"+round); Log.i("当前item的id===" + CurrentRadiosId, "结束的item的id==" + sc); rotateTo(CurrentRadiosId, sc);//从当前的id旋转到sc CurrentRadiosId=sc;//记录新的当前id } private void rotateTo(int currentId, int rotateId) { float curRadio=listRadios.get(currentId);//当前的item的弧度 float rotaRadio=listRadios.get(rotateId);//结束的item的弧度 // if (curRadio-rotaRadio>0){ // rot=360-curRadio+rotaRadio; // } // else if (curRadio-rotaRadio==0){ // rot=0; // } // else { // rot=rotaRadio-curRadio; // } float rotateRadio=360*4+listImaRadios.get(rotateId);//总的旋转度数 // Log.i("开始转动的弧度-qq====" + listImaRadios.get(currentId), "转动的弧度====" + rot); // Log.i("开始转动的item位置"+currentId,"结束时的item位置"+rotateId); anim=new RotateAnimation(listImaRadios.get(currentId),rotateRadio, Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.7f); anim.setDuration(2000); anim.setFillAfter(true); anim.setAnimationListener(new Animation.AnimationListener() { @Override public void onAnimationStart(Animation animation) { } @Override public void onAnimationEnd(Animation animation) { image.setClickable(true); Toast.makeText(MainActivity.this,""+text[CurrentRadiosId],Toast.LENGTH_SHORT).show(); // Log.i("转动结束后的当前item===", "" + CurrentRadiosId); Log.i("----------","---------------------------------------------"); } @Override public void onAnimationRepeat(Animation animation) { } }); //启动动画 image.startAnimation(anim); } }
布局:
<?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" tools:context="bw.com.zhuanpan.MainActivity"> <FrameLayout android:layout_width="match_parent" android:layout_height="match_parent"> <bw.com.zhuanpan.view.Turnplate android:background="#aaeeaa" android:id="@+id/turnplate" android:layout_gravity="center" android:layout_width="100dp" android:layout_height="100dp" /> <ImageView android:id="@+id/image" android:clickable="true" android:onClick="rotate" android:src="@mipmap/chou" android:layout_gravity="center" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="-20dp"/> </FrameLayout> </RelativeLayout>