Android自定义问题严重程度标尺

 

 

 

 

先上一个效果图

 

 

 

其实只有一个很简单的展示效果,不存在滑动效果,所以控件宽度可以设定为match-parent 或者固定dp值。(没有计算控件的总体宽高)

 

好了,下边开始说我写这个小控件的步骤。

1、根据效果图,首先画出中间的渐变色矩形

把矩形,矩形上边的数据和矩形下边的刻度分为3份,每份所占高度相同

float  recHeight = getHeight / 3;

设置渐变色区域 colors 为渐变色 颜色数组

LinearGradient shader = new LinearGradient(0, 0, 1000, 0, colors, null, Shader.TileMode.CLAMP);
mPaint.setShader(shader);
canvas.drawRect(0, rectHeight, getWidth(), 2 * rectHeight, mPaint);

 

2、画刻度线和刻度值

mPaint.setColor(Color.BLACK);
String index = showItems[i] + "";
float txtWidth = px2dip(mContext, calculateTextWidth(index)) / 2f;
canvas.drawText(index, startX * width - txtWidth, rectHeight * 2.6f, mPaint);
3.画程度
float stringWidth = px2dip(mContext, calculateTextWidth(itemTitle[i])) / 2f;
if (i < showItems.length - 1) {
    float x = (float) showItems[i + 1] / viewAlls;
    float xstart = (x + startX) * width;
    canvas.drawText(itemTitle[i], xstart / 2 - stringWidth, 0.5f * rectHeight, mPaint);
} else {
    float start = (startX + 1f) * width;
    canvas.drawText(itemTitle[i], start / 2 - stringWidth, 0.5f * rectHeight, mPaint);
}

4.倒三角

float triangleStart = (showIndex / viewAlls) * width;
//三角形起点
mPath.moveTo(triangleStart - 20,0.7f * rectHeight);
mPath.lineTo(triangleStart + 20,0.7f * rectHeight);
mPath.lineTo(triangleStart ,rectHeight);
mPath.close(); // 使这些点构成封闭的多边形
canvas.drawPath(mPath, mPaint);

然后就完成了这样一个程度标尺。

 

public class DegreeRulerView extends View {

    private Paint mPaint;

    private Path mPath;

    //渐变色颜色数组
    private int[] colors = {Color.parseColor("#8FF0D2"), Color.parseColor("#F5DF23"), Color.parseColor("#FA3F04")};

    //总刻度数量
    private int viewAlls = 35;
    //需要显示的刻度
    private int[] showItems;
    //显示刻度对应的标题
    private String[] itemTitle;
    //倒三角显示位置
    private float showIndex;

    private Context mContext;

    private float fontSize = 30f;

    private DisplayMetrics metrics = null;

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

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

    public DegreeRulerView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        mContext = context;

        metrics = new DisplayMetrics();
        WindowManager wmg = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        wmg.getDefaultDisplay().getMetrics(metrics);

        mPaint = new Paint();
        mPath = new Path();
        mPaint.setStyle(Paint.Style.FILL);
        mPaint.setAntiAlias(true);
        mPaint.setTextSize(fontSize);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        //根据设计图分成3个部分,每个部分高度相同
        float rectHeight = getHeight() / 3;

        //画矩形框
        //设置渐变色区域
        LinearGradient shader = new LinearGradient(0, 0, 1000, 0, colors, null, Shader.TileMode.CLAMP);
        mPaint.setShader(shader);
        canvas.drawRect(0, rectHeight, getWidth(), 2 * rectHeight, mPaint);

        //清空渐变色区域,不然刻度线,刻度值都会是渐变色的
        int width = getWidth();
        mPaint.setShader(null);
        for (int i = 0; i < showItems.length; i++) {

            float startX = (float) showItems[i] / viewAlls;
            //画刻度线
            mPaint.setColor(Color.WHITE);
            canvas.drawLine(startX * width, rectHeight * 1.4f, startX * width, rectHeight * 2f, mPaint);

            //画刻度值
            mPaint.setColor(Color.BLACK);
            String index = showItems[i] + "";
            float txtWidth = px2dip(mContext, calculateTextWidth(index)) / 2f;
            canvas.drawText(index, startX * width - txtWidth, rectHeight * 2.6f, mPaint);

            //画程度
            float stringWidth = px2dip(mContext, calculateTextWidth(itemTitle[i])) / 2f;
            if (i < showItems.length - 1) {
                float x = (float) showItems[i + 1] / viewAlls;
                float xstart = (x + startX) * width;
                canvas.drawText(itemTitle[i], xstart / 2 - stringWidth, 0.5f * rectHeight, mPaint);
            } else {
                float start = (startX + 1f) * width;
                canvas.drawText(itemTitle[i], start / 2 - stringWidth, 0.5f * rectHeight, mPaint);
            }
        }

        //倒三角形
        float triangleStart = (showIndex / viewAlls) * width;
        //三角形起点
        mPath.moveTo(triangleStart - 20,0.7f * rectHeight);
        mPath.lineTo(triangleStart + 20,0.7f * rectHeight);
        mPath.lineTo(triangleStart ,rectHeight);
        mPath.close(); // 使这些点构成封闭的多边形
        canvas.drawPath(mPath, mPaint);
    }

    public void setColors(int[] colors) {
        this.colors = colors;
    }

    public void setViewAlls(int viewAlls) {
        this.viewAlls = viewAlls;
    }

    public void setShowItems(int[] showItems) {
        this.showItems = showItems;
    }

    public void setItemTitle(String[] itemTitle) {
        this.itemTitle = itemTitle;
    }

    public void setShowIndex(float showIndex) {
        this.showIndex = showIndex;
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */

    public int px2dip(Context context, float pxValue) {

        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 获取TextView中文本的宽度
     */
    private float calculateTextWidth(String text) {
        if (TextUtils.isEmpty(text)) {
            return 0;
        }
        TextPaint textPaint = new TextPaint();
        textPaint.setTextSize(fontSize * metrics.scaledDensity);
        final float textWidth = textPaint.measureText(text);

        return textWidth;
    }
}

使用方法: 

 

<com.xw.example.DegreeRulerView
    android:id="@+id/rulerView"
    android:layout_width="match_parent"
    android:layout_height="80dp"
    android:layout_margin="20dp"
    />

        rulerView.setViewAlls(35);
        rulerView.setItemTitle(title);
        rulerView.setShowItems(index);
        rulerView.setShowIndex(10f);

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android 中实现对齐标尺可以使用 RecyclerView 来实现。具体步骤如下: 1. 首先需要创建一个 RecyclerView,并设置其方向为横向。 2. 在 RecyclerView 中添加一个 ItemDecoration,重写 getItemOffsets() 方法,在该方法中设置每个 item 的左右间距。 3. 在 RecyclerView 中添加一个 OnScrollListener,重写 onScrolled() 方法,在该方法中计算当前列表的滚动距离,然后根据每个 item 的左右间距以及列表的滚动距离,计算出当前 item 应该显示的位置,并将其保存到 item 的 Tag 中。 4. 在 Activity 中创建一个 View(比如 TextView),设置其为可拖动的,并设置一个 OnTouchListener,在该监听器中监听拖动事件,当拖动到某个 item 时,根据该 item 的 Tag 中保存的位置信息,将 View 移动到该位置上。 代码示例: ```java public class AlignRulerItemDecoration extends RecyclerView.ItemDecoration { private int mItemPadding; private int mItemWidth; public AlignRulerItemDecoration(int itemPadding, int itemWidth) { mItemPadding = itemPadding; mItemWidth = itemWidth; } @Override public void getItemOffsets(@NonNull Rect outRect, @NonNull View view, @NonNull RecyclerView parent, @NonNull RecyclerView.State state) { super.getItemOffsets(outRect, view, parent, state); outRect.left = mItemPadding; outRect.right = mItemPadding; } } public class AlignRulerOnScrollListener extends RecyclerView.OnScrollListener { private View mRulerView; private int mItemWidth; private int mItemPadding; private int mTotalScrollDistance; public AlignRulerOnScrollListener(View rulerView, int itemWidth, int itemPadding) { mRulerView = rulerView; mItemWidth = itemWidth; mItemPadding = itemPadding; } @Override public void onScrolled(@NonNull RecyclerView recyclerView, int dx, int dy) { super.onScrolled(recyclerView, dx, dy); mTotalScrollDistance += dx; int rulerPosition = Math.round((float) mTotalScrollDistance / (mItemWidth + mItemPadding)) * (mItemWidth + mItemPadding); mRulerView.setTag(rulerPosition); mRulerView.setTranslationX(rulerPosition); } } public class AlignRulerTouchListener implements View.OnTouchListener { private View mRulerView; private int mItemWidth; private int mItemPadding; public AlignRulerTouchListener(View rulerView, int itemWidth, int itemPadding) { mRulerView = rulerView; mItemWidth = itemWidth; mItemPadding = itemPadding; } @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_MOVE: int rulerPosition = Math.round((event.getRawX() - mItemWidth / 2) / (mItemWidth + mItemPadding)) * (mItemWidth + mItemPadding); mRulerView.setTranslationX(rulerPosition); break; case MotionEvent.ACTION_UP: int itemPosition = Math.round((mRulerView.getTranslationX() + mItemWidth / 2) / (mItemWidth + mItemPadding)) * (mItemWidth + mItemPadding); mRulerView.animate().translationX(itemPosition).start(); break; } return true; } } // 在 Activity 中初始化 RecyclerView标尺 View 并设置监听器 RecyclerView recyclerView = findViewById(R.id.recycler_view); TextView rulerView = findViewById(R.id.ruler_view); recyclerView.addItemDecoration(new AlignRulerItemDecoration(itemPadding, itemWidth)); recyclerView.addOnScrollListener(new AlignRulerOnScrollListener(rulerView, itemWidth, itemPadding)); rulerView.setOnTouchListener(new AlignRulerTouchListener(rulerView, itemWidth, itemPadding)); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值