定制的弧形搜索栏 [英] custom made arc shaped seekbar

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

问题描述

我试图做到的,是使一个弧形搜索栏。我知道有很多我可以用它来实现这一目标库,但我只是想我的手定制的意见。 我也遇到了一些问题:

  1. 我有扩展搜索栏一类,我已经实现的OnDraw和onMeasure方法为好,但我不能够查看在Eclipse布局编辑器,这里是code为自定义视图类:

     包com.custom.android.views;
    
    进口android.content.Context;
    进口android.graphics.Canvas;
    进口android.graphics.Color;
    进口android.graphics.Paint;
    进口android.graphics.Path;
    进口android.graphics.Path.Direction;
    进口android.graphics.PathMeasure;
    
    
    进口android.util.AttributeSet;
    进口android.view.MotionEvent;
    进口android.view.View;
    
    进口android.widget.SeekBar;
    进口android.widget.Toast;
    
    
    
    公共类CustomSeekBar扩展搜索栏{
    
        公共CustomSeekBar(上下文的背景下){
            超(上下文);
            // TODO自动生成构造函数存根
    
        }
    
        公共CustomSeekBar(上下文的背景下,ATTRS的AttributeSet){
            这(背景下,ATTRS,0);
    
        }
    
        公共CustomSeekBar(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
            超(背景下,ATTRS,defStyle);
    
        }
    
        @覆盖
        公共无效画(油画画布){
            // TODO自动生成方法存根
            super.draw(画布);
        }
    
        @覆盖
        保护同步无效onMeasure(INT widthMeasureSpec,
                INT heightMeasureSpec){
            // TODO自动生成方法存根
            super.onMeasure(widthMeasureSpec,heightMeasureSpec);
        }
    
    
    }
     

下面是我的布局XML:

 < RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
    的xmlns:工具=htt​​p://schemas.android.com/tool​​s
    机器人:layout_width =match_parent
    机器人:layout_height =match_parent
    机器人:paddingBottom会=@扪/ activity_vertical_margin
    机器人:以下属性来=@扪/ activity_horizo​​ntal_margin
    机器人:paddingRight =@扪/ activity_horizo​​ntal_margin
    机器人:paddingTop =@扪/ activity_vertical_margin
    工具:上下文=MainActivity。>

    < com.custom.android.views.CustomSeekBar
         机器人:layout_width =match_parent
        机器人:layout_height =WRAP_CONTENT
        机器人:ID =@ + ID /搜索栏/>

< / RelativeLayout的>
 

  1. 如果我用帆布类划出一道弧线,或任何形状,那又是一个很好的起点?

到底什么是错的日食ADT,我怎么可以使用的OnDraw方法给予形状与搜索栏?

解决方案

绘制进度与任何形状,是pretty的方便。随着搜索栏,你有一定的复杂性,因为你必须达到3 diferent事情:

  1. 在画线
  2. 绘制拖动滑块,如果你想要的。
  3. 在处理用户的交互

您必须把它作为一个弧是绘制一个矩形内。因此,3点可以很容易:只要让用户将手指在一个水平线上,或正好在弧线,但考虑到只有X触摸事件的坐标。这是什么意思,总之?好了,好消息:你没有做任何事情,因为多数民众赞成基地搜索栏的正常行为

对于第二点,你可以选择的处理图像,并与一个小数学的相应位置写。或者,你可以忘记的处理程序知道,只是画了搜索栏为行再presenting全面跟踪,另一条线在它重新presenting的进展。当你有这方面的工作,如果你愿意,你可以添加处理程序。

和为第一点,这是主要的,但它不是很难达到的。您可以使用此code:

更新:我做了code一些改进

 公共类ArcSeekBar扩展搜索栏{


    公共ArcSeekBar(上下文的背景下,ATTRS的AttributeSet){
            超(背景下,ATTRS);

    }

    公共ArcSeekBar(上下文的背景下,ATTRS的AttributeSet,诠释defStyle){
            超(背景下,ATTRS,defStyle);

    }

    私人油漆mBasePaint;
    私人油漆mProgressPaint;
    私人RectF MOVAL =新RectF(5,5,550,550);
    私人诠释defaultmax = 180;
    私人诠释startAngle开始= 180;
    私人诠释strokeWidth = 10;

    私人诠释trackColor = 0xFF000000;
    私人诠释progressColor = 0xFFFF0000地址;



    公共无效setOval(RectF MOVAL){
            this.mOval = MOVAL;
    }



    公共无效setStartAngle(INT由startAngle){
            this.startAngle = startAngle开始;
    }

    公共无效setStrokeWidth(INT strokeWidth){
            this.strokeWidth = strokeWidth;
    }

    公共无效setTrackColor(INT trackColor){
            this.trackColor = trackColor;
    }

    公共无效setProgressColor(INT progressColor){
            this.progressColor = progressColor;
    }

    公共ArcSeekBar(上下文的背景下){
            超(上下文);
            mBasePaint =新的油漆();
            mBasePaint.setAntiAlias​​(真正的);
            mBasePaint.setColor(trackColor);
            mBasePaint.setStrokeWidth(strokeWidth);
            mBasePaint.setStyle(Paint.Style.STROKE);

            mProgressPaint =新的油漆();
            mProgressPaint.setAntiAlias​​(真正的);
            mProgressPaint.setColor(progressColor);
            mProgressPaint.setStrokeWidth(strokeWidth);
            mProgressPaint.setStyle(Paint.Style.STROKE);

            SETMAX(defaultmax); //度


    }

    @覆盖
    保护无效的OnDraw(帆布油画){
            canvas.drawArc(MOVAL,startAngle开始,GetMax的(),假的,mBasePaint);
            canvas.drawArc(MOVAL,startAngle开始,getProgress(),假的,mProgressPaint);
            无效();
            //Log.i("ARC,getProgress()+/+ GetMax的());

    }

 }
 

当然,你可以,你应该做的一切配置,是构造器的方式,或用一些setter方法​​的开始和结束的角度,包含长方形,笔画的宽度,颜色等方面。

此外,请注意电弧从0绘制getProgress,作为这个号码角相对于x轴线的,生长clocwise,因此,如果它从0至90度去,这将是这样的:

当然,你可以改变这一点:canvas.drawArc得到任何数量的角度,它不被视为模块360,但你可以做的数学和有它开始和你想要的任何点结束。

在我的例子beggining是在一个时钟的9,它需要180度,到3中的时钟

更新

我上传了运行例子 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天全站免登陆