定制弧形寻宝 [英] custom made arc shaped seekbar

查看:245
本文介绍了定制弧形寻宝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要实现的是制作一个弧形的搜索条。我知道有很多图书馆可以用来实现这一点,但是我只是在定制视图中尝试我的手。
我遇到了几个问题:


  1. 我有一个扩展SeekBar的类,我已经实现了onDraw和onMeasure方法,但是我无法在eclipse的布局编辑器中查看,这里是自定义视图类的代码:

      package com.custom.android.views; 

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.Path.Direction;
    import android.graphics.PathMeasure;


    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;

    import android.widget.SeekBar;
    import android.widget.Toast;



    public class CustomSeekBar extends SeekBar {

    public CustomSeekBar(Context context){
    super(context);
    // TODO自动生成的构造函数存根

    }

    public CustomSeekBar(Context context,AttributeSet attrs){
    this(context,attrs,0 );

    }

    public CustomSeekBar(Context context,AttributeSet attrs,int defStyle){
    super(context,attrs,defStyle);

    }

    @Override
    public void draw(Canvas canvas){
    // TODO自动生成的方法stub
    super.draw (帆布);
    }

    @Override
    protected synchronized void onMeasure(int widthMeasureSpec,
    int heightMeasureSpec){
    // TODO自动生成的方法存根
    super.onMeasure(widthMeasureSpec,heightMeasureSpec);
    }


    }


这是我的布局xml:

 < RelativeLayout xmlns:android =http: /schemas.android.com/apk/res/android
xmlns:tools =http://schemas.android.com/tools
android:layout_width =match_parent
android :layout_height =match_parent
android:paddingBottom =@ dimen / activity_vertical_margin
android:paddingLeft =@ dimen / activity_horizo​​ntal_margin
android:paddingRight =@ dimen / activity_horizo​​ntal_margin
android:paddingTop =@ dimen / activity_vertical_margin
tools:context =。MainActivity>

< com.custom.android.views.CustomSeekBar
android:layout_width =match_parent
android:layout_height =wrap_content
android:id = @ + ID /搜索条/>

< / RelativeLayout>




  1. 如果我使用canvas类绘制一个弧或任何形状,这是一个很好的起点?

eclipse adt有什么问题,我该如何使用onDraw方法来形容那个seekbar?

解决方案

绘制具有任何形状的ProgressBar,很容易。 SeekBar你有一些复杂性,因为你必须实现3个不同的事情:


  1. 画线


  2. 处理用户交互

你必须把它看作是一个在矩形内绘制的圆弧。所以第3点可能很容易:只需让用户在水平线上移动手指,或者恰好在圆弧上移动手指,但仅考虑触摸事件的x坐标。这是什么意思,总之?好的,好消息:你不必做任何事情,因为这是基本SeekBar的正常行为。



对于第二点,您可以为处理程序选择一个图像,并用一些数学写在相应的位置。或者您可以忘记处理程序知道,只需将搜索栏绘制为表示完整曲目的线条,并在其上代替进度。当你有这个工作,如果你想要你可以添加处理程序。



第一点,这是主要的,但它不难实现。您可以使用以下代码:



更新:我在代码中进行了一些改进

  public class ArcSeekBar extends SeekBar {


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

}

public ArcSeekBar(Context context,AttributeSet attrs,int defStyle){
super(context,attrs,defStyle);

}

private Paint mBasePaint;
private Paint mProgressPaint;
private RectF mOval = new RectF(5,5,550,550);
private int defaultmax = 180;
private int startAngle = 180;
private int strokeWidth = 10;

private int trackColor = 0xFF000000;
private int progressColor = 0xFFFF0000;



public void setOval(RectF mOval){
this.mOval = mOval;
}



public void setStartAngle(int startAngle){
this.startAngle = startAngle;
}

public void setStrokeWidth(int strokeWidth){
this.strokeWidth = strokeWidth;
}

public void setTrackColor(int trackColor){
this.trackColor = trackColor;
}

public void setProgressColor(int progressColor){
this.progressColor = progressColor;
}

public ArcSeekBar(Context context){
super(context);
mBasePaint = new Paint();
mBasePaint.setAntiAlias(true);
mBasePaint.setColor(trackColor);
mBasePaint.setStrokeWidth(strokeWidth);
mBasePaint.setStyle(Paint.Style.STROKE);

mProgressPaint = new Paint();
mProgressPaint.setAntiAlias(true);
mProgressPaint.setColor(progressColor);
mProgressPaint.setStrokeWidth(strokeWidth);
mProgressPaint.setStyle(Paint.Style.STROKE);

setMax(defaultmax); //度


}

@Override
protected void onDraw(Canvas canvas) {
canvas.drawArc(mOval,startAngle,getMax(),false,mBasePaint);
canvas.drawArc(mOval,startAngle,getProgress(),false,mProgressPaint);
invalidate();
//Log.i(\"ARC,getProgress()+/+ getMax());

}

}

当然,你可以和你应该使一切可配置,作为构思的手段,或一些设置者的起始和结束角度,包含矩形的尺寸,笔触宽度,颜色等。


$ b $另外,请注意,圆弧从0到getProgress,这个数字是相对于x轴的角度,逐渐增长,所以如果从0到90度,它将是这样的:





当然,您可以更改此选项:canvas.drawArc将任何数字作为一个角度,它不会被视为模块360,但您可以做数学并将其开始和结束任何你想要的点。



在我的例子中,起义是在时钟的9个时钟,它需要180度,到3点钟。

更新



我上传了一个运行的exa mple to github


What I am trying to achieve is to make an arc shaped seekbar. I know there are plenty of libraries I could use to achieve this, but I am just trying my hands on custom made views. I have encountered couple of problems:

  1. I have a class which extends SeekBar, and I have implemented onDraw and onMeasure methods as well, but I am not able to view that in layout editor in eclipse, here is the code for the custom view class:

    package com.custom.android.views;
    
    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.graphics.Path.Direction;
    import android.graphics.PathMeasure;
    
    
    import android.util.AttributeSet;
    import android.view.MotionEvent;
    import android.view.View;
    
    import android.widget.SeekBar;
    import android.widget.Toast;
    
    
    
    public class CustomSeekBar extends SeekBar {
    
        public CustomSeekBar(Context context) {
            super(context);
            // TODO Auto-generated constructor stub
    
        }
    
        public CustomSeekBar(Context context, AttributeSet attrs) {
            this(context, attrs,0);
    
        }
    
        public CustomSeekBar(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
    
        }
    
        @Override
        public void draw(Canvas canvas) {
            // TODO Auto-generated method stub
            super.draw(canvas);
        }
    
        @Override
        protected synchronized void onMeasure(int widthMeasureSpec,
                int heightMeasureSpec) {
            // TODO Auto-generated method stub
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }
    
    
    }
    

Here is my layout xml :

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <com.custom.android.views.CustomSeekBar
         android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/seekBar"/>

</RelativeLayout>

  1. If I use canvas class to draw an arc or any shape, would that be a good starting point?

What exactly is wrong with the eclipse adt and how could I use the onDraw method to give shape to that seekbar?

解决方案

Drawing a ProgressBar with any shape, is pretty easy. With the SeekBar you have some complexity, since you have to achieve 3 diferent things:

  1. Draw the line
  2. Draw the draggable thumb, if you want.
  3. Handle the user interaction

You have to think of it as an arc that is draw inside a rectangle. So point 3 could be easy: just let the user move the finger in a horizontal line, or exactly over the arc, but considering only the x coordinate of the touch event. What does this mean, in short? ok, good news: you dont have to do anything, since thats the normal behavior of the base SeekBar.

For the second point, you can choose an image for the handler, and write it in the corresponding position with a little maths. Or you can forget the handler for know, and just draw the seek bar as a line representing the full track, and another line over it representing the progress. When you have this working, if you want you can add the handler.

And for the first point, this is the main one, but its not hard to achieve. You can use this code:

UPDATE: I made some improvements in the code

public class ArcSeekBar extends SeekBar {


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

    }

    public ArcSeekBar(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);

    }

    private Paint mBasePaint;
    private Paint mProgressPaint;
    private RectF mOval = new RectF(5, 5, 550, 550);
    private int defaultmax = 180;
    private int startAngle=180;
    private int strokeWidth=10;

    private int trackColor=0xFF000000;
    private int progressColor=0xFFFF0000;



    public void setOval(RectF mOval) {
            this.mOval = mOval;
    }



    public void setStartAngle(int startAngle) {
            this.startAngle = startAngle;
    }

    public void setStrokeWidth(int strokeWidth) {
            this.strokeWidth = strokeWidth;
    }

    public void setTrackColor(int trackColor) {
            this.trackColor = trackColor;
    }

    public void setProgressColor(int progressColor) {
            this.progressColor = progressColor;
    }

    public ArcSeekBar(Context context) {
            super(context);
            mBasePaint = new Paint();
            mBasePaint.setAntiAlias(true);
            mBasePaint.setColor(trackColor);
            mBasePaint.setStrokeWidth(strokeWidth);
            mBasePaint.setStyle(Paint.Style.STROKE);

            mProgressPaint = new Paint();
            mProgressPaint.setAntiAlias(true);
            mProgressPaint.setColor(progressColor);
            mProgressPaint.setStrokeWidth(strokeWidth);
            mProgressPaint.setStyle(Paint.Style.STROKE);

            setMax(defaultmax);// degrees


    }

    @Override
    protected void onDraw(Canvas canvas) {
            canvas.drawArc(mOval, startAngle, getMax(), false, mBasePaint);
            canvas.drawArc(mOval, startAngle, getProgress(), false, mProgressPaint);
            invalidate();
            //Log.i("ARC", getProgress()+"/"+getMax());

    }

 }

Of course, you can and you should make everything configurable, be means of the contructor, or with some setters for the start and end angles, dimensions of the containing rectangle, stroke widths, colors, etc.

Also, note that the arc is drawn from 0 to getProgress, being this number an angle relative to the x axis, growing clocwise, so, if it go from 0 to 90 degrees, it will be something like:

Of course you can change this: canvas.drawArc get any number as an angle, and it is NOT treated as module 360, but you can do the maths and have it starting and ending in any point you want.

In my example the beggining is in the 9 of a clock, and it takes 180 degrees, to the 3 in the clock.

UPDATE

I uploaded a running example to github

这篇关于定制弧形寻宝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆