android自定义View之刻度尺MnScaleBar

在Q群里看到有同学需要自定义刻度尺如图:


1. 需求:

1)指针固定在屏幕中间;

2)左右可以滑动直尺;

3)返回选择的刻度值;

2. 需要的知识点:

1)继承View重写onDraw()方法

2)重写onTouchEvent()方法

3)Scroller滑动帮助类

4)OnScrollListener回调方法

3. 代码如下:

package cc.mnbase.view.progress.bar;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.MotionEvent;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.Scroller;

/**
 * User: 山野书生(1203596603@qq.com)
 * Date: 2015-11-30
 * Time: 14:29
 * Version 1.0
 */

public class MnScaleBar extends View {

    private Context mContext;

    private Rect mRect;

    private int max = 200; //最大刻度
    private int mCountScale; //滑动的总刻度

    private int screenWidth = 720; //默认屏幕分辨率

    private int mScaleMargin = 15; //刻度间距
    private int mScaleHeight = 20; //刻度线的高度
    private int mScaleMaxHeight = mScaleHeight*2; //整刻度线高度

    private int mRectWidth = max * mScaleMargin; //总宽度
    private int mRectHeight = 150; //高度

    private Scroller mScroller;
    private int mScrollLastX;

    private int mTempScale = screenWidth/mScaleMargin/2; //判断滑动方向
    private int mScreenMidCountScale = screenWidth/mScaleMargin/2; //中间刻度

    private OnScrollListener onScrollListener;

    private String tag = MnScaleBar.class.getSimpleName();

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

    public MnScaleBar(Context context, AttributeSet attrs) {
        this(context, attrs, -1);
    }

    public MnScaleBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        screenWidth = getPhoneW(mContext);

        mTempScale = screenWidth/mScaleMargin/2; //判断滑动方向
        mScreenMidCountScale = screenWidth/mScaleMargin/2; //中间刻度

        mScroller = new Scroller(mContext);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        //设置LayoutParams
        LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(mRectWidth, mRectHeight);
        this.setLayoutParams(lp);
        //相对位置坐标
        mRect = new Rect(0, 0, mRectWidth, mRectHeight);
        //画笔
        Paint mPaint = new Paint();
        mPaint.setColor(Color.GRAY);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.STROKE);


        canvas.drawRect(mRect, mPaint);

        onDrawScale(canvas); //画刻度
        onDrawPointer(canvas); //画指针

        super.onDraw(canvas);
    }

    /**
     * 画刻度
     * */
    private void onDrawScale(Canvas canvas){
        if(canvas == null) return;
        Paint mPaint = new Paint();
        mPaint.setColor(Color.GRAY);
        mPaint.setTextAlign(Paint.Align.CENTER); //文字居中
        mPaint.setTextSize(20);
        for(int i=0; i<max; i++){
            if(i!=0 && i!=max){
                if(i%10==0){ //整值
                    canvas.drawLine(i*mScaleMargin, mRectHeight, i*mScaleMargin, mRectHeight-mScaleMaxHeight, mPaint);
                    //整值文字
                    canvas.drawText(String.valueOf(i), i*mScaleMargin, mRectHeight-mScaleMaxHeight-10, mPaint);
                } else {
                    canvas.drawLine(i*mScaleMargin, mRectHeight, i*mScaleMargin, mRectHeight-mScaleHeight, mPaint);
                }
            }
        }
    }

    /**
     * 画指针
     * */
    private void onDrawPointer(Canvas canvas){
        if(canvas == null) return;
        Paint mPaint = new Paint();
        mPaint.setColor(Color.RED);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setTextSize(20);
        //每一屏幕刻度的个数/2
        int countScale = screenWidth/mScaleMargin/2;
        //根据滑动的距离,计算指针的位置【指针始终位于屏幕中间】
        int finalX =  mScroller.getFinalX();
        //滑动的刻度
        int tmpCountScale = (int) Math.rint((double)finalX/(double)mScaleMargin); //四舍五入取整
        //总刻度
        mCountScale = tmpCountScale+countScale;
        if(onScrollListener!=null){ //回调方法
            onScrollListener.onScrollScale(mCountScale);
        }
        canvas.drawLine(countScale * mScaleMargin + finalX, mRectHeight,
                countScale * mScaleMargin + finalX, mRectHeight - mScaleMaxHeight, mPaint);
        canvas.drawText(String.valueOf(mCountScale), countScale * mScaleMargin + finalX, mRectHeight - mScaleMaxHeight - 10, mPaint);
    }

    @Override
    public void computeScroll() {
        if(mScroller.computeScrollOffset()){
            scrollTo(mScroller.getCurrX(), 0);
            postInvalidate();
        }
        super.computeScroll();
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        int x = (int) event.getX();
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                if(mScroller != null && !mScroller.isFinished()){
                    mScroller.abortAnimation();
                }
                mScrollLastX = x;
                return true;
            case MotionEvent.ACTION_MOVE:
                int dataX = mScrollLastX - x;
                if(mCountScale-mTempScale<0){ //向右边滑动
                    if(mCountScale<0) {
                        if(dataX<0) //禁止继续向右滑动
                        return super.onTouchEvent(event);
                    }
                } else if(mCountScale-mTempScale>0){ //向左边滑动
                    if (mCountScale>max) {
                        if(dataX>0) //禁止继续向左滑动
                        return super.onTouchEvent(event);
                    }
                }
                smoothScrollBy(dataX, 0);
                mScrollLastX = x;
                postInvalidate();
                mTempScale = mCountScale;
                return true;
            case MotionEvent.ACTION_UP:
                if(mCountScale<0) mCountScale=0;
                if(mCountScale>max) mCountScale=max;
                int finalX = (mCountScale-mScreenMidCountScale) * mScaleMargin;
                mScroller.setFinalX(finalX); //纠正指针位置
                postInvalidate();
                return true;
        }
        return super.onTouchEvent(event);
    }


    public void smoothScrollBy(int dx, int dy){
        mScroller.startScroll(mScroller.getFinalX(), mScroller.getFinalY(), dx, dy);
    }

    public void smoothScrollTo(int fx, int fy){
        int dx = fx - mScroller.getFinalX();
        int dy = fy - mScroller.getFinalY();
        smoothScrollBy(dx, dy);
    }

    public void setOnScrollListener(OnScrollListener onScrollListener) {
        this.onScrollListener = onScrollListener;
    }

    public interface OnScrollListener{
        void onScrollScale(int scale);
    }

    /**
     * 获取手机分辨率--W
     * */
    public static int getPhoneW(Context context){
        DisplayMetrics dm = new DisplayMetrics();
        ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(dm);
        int disW = dm.widthPixels;
        return disW;
    }

}

布局代码:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    >

    <cc.mnbase.view.progress.bar.MnScaleBar
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:layout_margin="5dp"
        android:id="@+id/scale_bar"
        />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/text"
        />

</LinearLayout>

Activity代码:

package cc.mnbase;

import android.os.Bundle;
import android.widget.TextView;

import cc.mn.BaseActivity;
import cc.mnbase.view.progress.bar.MnScaleBar;

/**
 * User: 山野书生(1203596603@qq.com)
 * Date: 2015-11-30
 * Time: 14:44
 * Version 1.0
 */

public class MnScaleBarActivity extends BaseActivity{

    private TextView text;
    private MnScaleBar scale_bar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scale_bar_layout);


        scale_bar = (MnScaleBar)findViewById(R.id.scale_bar);
        text = (TextView)findViewById(R.id.text);

        scale_bar.setOnScrollListener(new MnScaleBar.OnScrollListener() {
            @Override
            public void onScrollScale(int scale) {
                text.setText("身高:"+scale+"cm");
            }
        });
    }
}


运行结果如图:





  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Android自定义View圆形刻度在实现上相对简单,主要步骤如下: 1. 创建一个继承自View自定义View类,命名为CircleScaleView。 2. 在该自定义View的构造方法中完成必要的初始化工作,例如设置画笔、设置View的宽高、设置绘制模式等。 3. 重写onMeasure()方法,设置View的尺寸大小。可以根据自定义的需求来决定View的宽高。 4. 重写onDraw()方法,完成绘制整个圆形刻度的逻辑。 5. 在onDraw()方法中,首先通过getMeasuredWidth()和getMeasuredHeight()方法获取到View的宽高,然后计算圆心的坐标。 6. 接着,使用Canvas对象的drawArc()方法来绘制圆弧,根据需求设置圆弧的起始角度和扫描角度。 7. 再然后,通过循环绘制每个刻度线,可以使用Canvas对象的drawLine()方法来绘制。 8. 最后,根据需要绘制刻度值或其他其他附加元素,例如圆心的标记。 9. 至此,整个圆形刻度的绘制逻辑就完成了。 10. 在使用该自定义View的时候,可以通过添加该View到布局文件中或者在代码中动态添加,并按需设置相应的属性。 需要注意的是,自定义圆形刻度的具体样式和行为取决于项目需求,上述步骤仅为基础实现框架,具体细节需要根据实际情况进行相应的调整。 ### 回答2: 在Android中实现一个圆形刻度的自定义View有几个步骤。 首先,我们需要创建一个自定义View类,继承自View或者它的子类(如ImageView)。 接下来,在自定义View的构造方法中,初始化一些必要的属性,比如画笔的颜色、宽度等。我们可以使用Paint类来设置这些属性。 然后,我们需要在自定义View的onMeasure方法中设置View的宽度和高度,确保View在屏幕上正常显示。一种常见的实现方式是将宽度和高度设置为相同的值,使得View呈现出圆形的形状。 接着,在自定义View的onDraw方法中,我们可以利用画笔来绘制圆形刻度。可以使用canvas.drawCircle方法来绘制一个圆形,使用canvas.drawLine方法绘制刻度线。我们可以根据需要,定义不同的刻度颜色和宽度。 最后,我们可以在自定义View的其他方法中,添加一些额外的逻辑。比如,在onTouchEvent方法中处理触摸事件,以实现拖动刻度的功能;在onSizeChanged方法中根据View的尺寸调整刻度的大小等等。 当我们完成了自定义View的代码编写后,我们可以在布局文件中使用这个自定义View。通过设置布局文件中的属性,可以进一步自定义View的外观和行为。 总之,实现一个圆形刻度的自定义View,我们需要定义一个自定义View类,并在其中使用画笔来绘制圆形和刻度。通过处理一些事件和属性,我们可以实现更多的功能和样式。以上就是简单的步骤,可以根据需要进行更加详细的实现。 ### 回答3: Android自定义View圆形刻度可以通过以下步骤实现。 首先,我们需要创建一个自定义View,继承自View类,并重写onDraw方法。在该方法中,我们可以自定义绘制的内容。 其次,我们需要定义一个圆形的刻度尺背景,可以使用Canvas类提供的drawCircle方法来绘制实心圆或空心圆。 接着,我们可以通过Canvas类的drawLine方法来绘制刻度线。根据刻度的数量,可以计算出每个刻度之间的角度,然后循环绘制出所有的刻度线。 然后,我们可以通过Canvas类的drawText方法来绘制刻度的值。根据刻度线的角度和半径,可以计算出刻度的坐标,然后将刻度的值绘制在指定的位置上。 最后,我们可以通过在自定义View的构造方法中获取相关的参数,如刻度的最大值、最小值、当前值等,然后根据这些参数来计算刻度的位置和值。 在使用自定义View时,可以通过设置相关的属性来改变刻度的样式和位置。例如,可以设置刻度线的颜色、粗细、长度等,也可以设置刻度值的颜色、大小等。 通过以上步骤,我们就可以实现一个圆形刻度尺自定义View。在使用时,可以根据需要自行调整绘制的样式和逻辑。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值