欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android自定义View仿IOS圆盘时间选择器

程序员文章站 2023-11-17 12:30:04
通过自定义view实现仿ios实现滑动两端的点选择时间的效果 效果图 自定义的view代码 public class ring_slide2 exte...

通过自定义view实现仿ios实现滑动两端的点选择时间的效果

效果图

Android自定义View仿IOS圆盘时间选择器

Android自定义View仿IOS圆盘时间选择器

自定义的view代码

public class ring_slide2 extends view {
 private static final double radian = 180 / math.pi;
 private int max_progress; // 设置最大进度
 private int cur_progress; //设置锚点1当前进度
 private int cur_progress2; //设置锚点2进度
 private int bottom_color;//设置底色
 private int circle_color; //设置圆的颜色(锚点)
 private int slide_color; //设置滑动过的颜色
 private float ring_width; //圆环的宽度
 private double cur_angle; //当前锚点1旋转角度
 private double cur_angle2; //当前锚点2的旋转角度
 private float ring_radius;//圆环的半径
 private final int[] arrcolorcircle = new int[]{0xffffde37, 0xffffa400};
 private int main_width; //圆的宽度
 private float mwheelcurx, mwheelcury; //圆的位置
 private float mwheelcurx2, mwheelcury2; //圆2的位置
 private paint circle_paint; //圆环的画笔
 private paint select_paint;//选中的画笔
 private paint dot1; //圆点1
 private paint dot2; //圆点2
 private context context;
 private onseekbarchangelistener changelistener,changelistener2;
 public ring_slide2(context context) {
  this(context,null);
 }
 public ring_slide2(context context, attributeset attrs) {
  this(context, attrs,0);
 }
 public ring_slide2(context context, attributeset attrs, int defstyleattr) {
  super(context, attrs, defstyleattr);
  this.context=context;
  initattrs(attrs,defstyleattr);
  initpadding();
  //初始化画笔
  initpaints();
 }
 //初始化属性
 private void initattrs(attributeset attrs, int defstyle){
  typedarray typedarray = getcontext().obtainstyledattributes(attrs, r.styleable.cricle_slide, defstyle, 0);
  max_progress=typedarray.getint(r.styleable.cricle_slide_max_progress,720);
  cur_progress=typedarray.getint(r.styleable.cricle_slide_cur_progress,420);
  cur_progress2=typedarray.getint(r.styleable.cricle_slide_cur_progress2,540);
  if (cur_progress > max_progress) cur_progress = max_progress;
  if (cur_progress2 > max_progress) cur_progress2 = max_progress;
  bitmap bitmap = bitmapfactory.decoderesource(context.getresources(), r.mipmap.select_sun_bg2);
  main_width= bitmap.getwidth();
  ring_width=typedarray.getfloat(r.styleable.cricle_slide_ring_width,main_width);
  bottom_color=typedarray.getcolor(r.styleable.cricle_slide_bottom_color,getcolor(r.color.select_main_bg_color));
  circle_color=typedarray.getcolor(r.styleable.cricle_slide_circle_color,getcolor(r.color.duration));
  slide_color=typedarray.getcolor(r.styleable.cricle_slide_slide_color,getcolor(r.color.time));
  typedarray.recycle();
 }
 //初始化边距
 private void initpadding(){
  int paddingleft = getpaddingleft();
  int paddingtop = getpaddingtop();
  int paddingright = getpaddingright();
  int paddingbottom = getpaddingbottom();
  int paddingstart = 0, paddingend = 0;
  if (build.version.sdk_int >= 17) {
   paddingstart = getpaddingstart();
   paddingend = getpaddingend();
  }
  int maxpadding = math.max(paddingleft, math.max(paddingtop,
    math.max(paddingright, math.max(paddingbottom, math.max(paddingstart, paddingend)))));
  setpadding(maxpadding, maxpadding, maxpadding, maxpadding);
 }
 private void initpaints(){
  /*
  圆环的画笔
   */
  circle_paint=new paint(paint.anti_alias_flag);
  circle_paint.setantialias(true);
  circle_paint.setcolor(bottom_color);
  circle_paint.setstyle(paint.style.stroke);
  circle_paint.setstrokewidth(ring_width);
  /*
  选中区域的画笔
   */
  select_paint=new paint(paint.anti_alias_flag);
  select_paint.setshader(new sweepgradient(0, 0, arrcolorcircle, null));
  /*select_paint.setcolor(circle_color);*/
  select_paint.setantialias(true);
  select_paint.setstyle(paint.style.stroke);
  select_paint.setstrokewidth(ring_width);
  // 画锚点
  dot1 = new paint(paint.anti_alias_flag);
  dot1.setcolor(circle_color);
  dot1.setantialias(true);
  dot1.setstyle(paint.style.fill);
  // 画锚点2
  dot2 = new paint(paint.anti_alias_flag);
  dot2.setcolor(slide_color);
  dot2.setantialias(true);
  dot2.setstyle(paint.style.fill);
 }
 //获取宽度
 private float getdimen(int dimenid) {
  return getresources().getdimension(dimenid);
 }
 //获取颜色
 @targetapi(build.version_codes.m)
 private int getcolor(int colorid) {
  final int version = build.version.sdk_int;
  if (version >= 23) {
   return getcontext().getcolor(colorid);
  } else {
   return contextcompat.getcolor(getcontext(), colorid);
  }
 }
 @override
 protected void onmeasure(int widthmeasurespec, int heightmeasurespec) {
  super.onmeasure(widthmeasurespec, heightmeasurespec);
  bitmap bitmap = bitmapfactory.decoderesource(context.getresources(), r.mipmap.setalarm_colock_bg);
  int height = bitmap.getheight()+main_width*2;
  int width = bitmap.getwidth()+main_width*2;
  int min = math.min(height, width);
  setmeasureddimension(min,min);
  initposition();
 }
 private void initposition(){
  //转换为360度
  cur_angle=(double) cur_progress / max_progress*360.0;
  cur_angle2=(double)cur_progress2 / max_progress*360.0;
  //计算初始化旋转的角度
  double cos = -math.cos(math.toradians(cur_angle));
  double cos2 = -math.cos(math.toradians(cur_angle2));
  //根据旋转的角度来确定位置
  makecurposition(cos);
  makecurposition2(cos2);
  //确定圆环的半径
  ring_radius=(getmeasuredwidth() - getpaddingleft() - getpaddingright() - ring_width) / 2;
 }
 private void makecurposition(double cos){
  //根据旋转的角度来确定圆的位置
  //确定x点的坐标
  mwheelcurx = calcxlocationinwheel(cur_angle, cos);
  //确定y点的坐标
  mwheelcury=calcylocationinwheel(cos);
 }
 private void makecurposition2(double cos2){
  //根据旋转的角度来确定圆的位置
  //确定x点的坐标
  mwheelcurx2 = calcxlocationinwheel(cur_angle2, cos2);
  //确定y点的坐标
  mwheelcury2=calcylocationinwheel(cos2);
 }
 //确定x点的坐标
 private float calcxlocationinwheel(double angle,double cos){
  if (angle < 180) {
   return (float) (getmeasuredwidth() / 2 + math.sqrt(1 - cos * cos) * ring_radius); //math.sqrt正平分根 9-3
  } else {
   return (float) (getmeasuredwidth() / 2 - math.sqrt(1 - cos * cos) * ring_radius);
  }
 }
 //确定y点的坐标
 private float calcylocationinwheel(double cos) {
  return getmeasuredwidth() / 2 + ring_radius * (float) cos;
 }
 @override
 protected void ondraw(canvas canvas) {
  super.ondraw(canvas);
  float left = getpaddingleft() + ring_width / 2;
  float top = getpaddingtop() + ring_width / 2;
  float right = canvas.getwidth() - getpaddingright() - ring_width / 2;
  float bottom = canvas.getheight() - getpaddingbottom() - ring_width / 2;
  float centerx = (left + right) / 2;
  float centery = (top + bottom) / 2;
  float wheelradius = (canvas.getwidth() - getpaddingleft() - getpaddingright()) / 2 - ring_width / 2;
  canvas.drawcircle(centerx, centery, wheelradius, circle_paint);
  //画选中区域
  // canvas.drawarc(new rectf(left, top, right, bottom), (float) (math.pi * radian + math.acos(cur_angle) * radian), (float) (math.abs(cur_angle-cur_angle2)), false, select_paint);
  log.i("tag","第一个的角度="+cur_angle);
  log.i("tag","第一个的角度2="+cur_angle2);
  float begin=0; //圆弧的起点位置
  float stop=0;
  if(cur_angle>180 && cur_angle>cur_angle2 ){ //180 -- 360
   begin=(float) (-math.abs(cur_angle-360)-90);
   stop=(float) math.abs(math.abs(cur_angle-360)+cur_angle2);
   log.i("tag","begin="+begin);
   log.i("tag","stop="+stop);
  }else if(cur_angle>cur_angle2){
   begin=(float) cur_angle-90;
   stop=(float)(360-(cur_angle-cur_angle2));
  }else {
    begin=(float) cur_angle-90;
   stop=(float) math.abs(cur_angle-cur_angle2);
  }
  canvas.drawarc(new rectf(left, top, right, bottom), begin,stop, false, select_paint);
  //画锚点 画圆
  canvas.drawcircle(mwheelcurx, mwheelcury, ring_width/2, dot1);
  //画锚点 画圆
  canvas.drawcircle(mwheelcurx2, mwheelcury2, ring_width/2, dot2);
  log.i("tag","锚点1y"+mwheelcury+"锚点1x"+mwheelcurx);
  log.i("tag","锚点2y"+mwheelcury2+"锚点1x"+mwheelcurx2);
 }
 @override
 public boolean ontouchevent(motionevent event) {
  float x = event.getx();
  float y = event.gety();
  int flag=0;
  //判断是否触控到两个点中的其中某个点
  if(ismovedot2(x,y)){
   flag=2;
  }else if(ismovedot1(x,y)){
   flag=1;
  }
  /* if(ismovedot1(x,y)){
   flag=1;
  }else if(ismovedot2(x,y)){
   flag=2;
  }*/
  if(event.getaction()==motionevent.action_move || ismovedot1(x,y) ==true || ismovedot2(x,y)==true ){
   log.i("tag","进入x="+x+"进入y="+y);
   //通过触摸点算出cos角度值
   float cos = calculatecos(x, y);
   // 通过反三角函数获得角度值
   double angle; //获取滑动的角度
   if (x < getwidth() / 2) { // 滑动超过180度
    angle = math.pi * radian + math.acos(cos) * radian; //通过计算得到滑动的角度值
   } else { // 没有超过180度
    angle = math.pi * radian - math.acos(cos) * radian; //pi 周长比直径 返回弧角度的余弦值
   }
   if(flag==1){
    cur_angle=angle;
    cur_progress=getselectedvalue(cur_angle);
    makecurposition(cos);
    if (changelistener != null) {
     changelistener.onchanged(this, cur_progress);
    }
   }else if(flag==2){
    cur_angle2=angle;
    cur_progress2=getselectedvalue(cur_angle2);
    makecurposition2(cos);
    if (changelistener2 != null) {
     changelistener2.onchanged(this, cur_progress2);
    }
   }
   invalidate();
   return true;
  }else {
   return super.ontouchevent(event);
  }
 }
 private boolean ismovedot1(float x,float y){
  float dot1x = math.abs(mwheelcurx - x);
  float dot1y = math.abs(mwheelcury - y);
  if(dot1x<30 && dot1y<30){
   return true;
  }else{
   return false;
  }
 }
 private boolean ismovedot2(float x,float y){
  float dot1x = math.abs(mwheelcurx2 - x);
  float dot1y = math.abs(mwheelcury2 - y);
  if(dot1x<30 && dot1y<30){
   return true;
  }else{
   return false;
  }
 }
 //拿到切斜角的cos值
 private float calculatecos(float x, float y){
  float width = x - getwidth() / 2;
  float height = y - getheight() / 2;
  float slope = (float) math.sqrt(width * width + height * height);
  return height / slope;
 }
 private int getselectedvalue(double mcurangle) { //角度转进度
  return math.round(max_progress * ((float) mcurangle / 360)); //四舍五入
 }
 public void setonseekbarchangelistener(onseekbarchangelistener listener) {
  changelistener = listener;
 }
 public void setonseekbarchangelistener2(onseekbarchangelistener listener) {
  changelistener2 = listener;
 }
 public void initradian(int pro1,int pro2){
  this.cur_progress=pro1;
  this.cur_progress2=pro2;
  invalidate();
 }
 public interface onseekbarchangelistener {
  void onchanged(ring_slide2 seekbar, int curvalue);
 }
}

自定义stayle样式,在values下新建sttrs.xml文件

 <declare-styleable name="cricle_slide">
  //设置最大进度
  <attr name="max_progress" format="integer"></attr>
  //设置当前进度
  <attr name="cur_progress" format="integer"></attr>
  //设置当前进度
  <attr name="cur_progress2" format="integer"></attr>
  //设置底色
  <attr name="bottom_color" format="color"></attr>
  //设置圆的颜色
  <attr name="circle_color" format="color"></attr>
  //设置滑动的颜色
  <attr name="slide_color" format="color"></attr>
  //圆环的宽度 (dimension是代表尺寸值)
  <attr name="ring_width" format="dimension"></attr>
 </declare-styleable>

以上所述是小编给大家介绍的android自定义view仿ios圆盘时间选择器,希望对大家有所帮助