Android自定义View—RulerView

本文介绍了如何在Android中利用自定义View创建一个标准的刻度尺。通过分析屏幕适配问题,结合WindowManager和DisplayMetrics获取设备信息,实现了单位转换并绘制边框。重点讲解了绘制刻度尺的关键步骤,包括限制Activity横屏显示,以及提供了源代码链接供读者参考和拓展功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.前言

       在日常的生活中我们有时会用到刻度尺去测量某些东西,但是我们又不可能随身携带一把尺子,那么接下来我们就利用自定义View的方式在手机上绘制一把标准的刻度尺,但是目前在手机上绘制的刻度尺只能满足测量的粗略要求,如果想要精确的测量还是需要使用专业的设备

实现后的效果:


2.实现分析

       在前面的文章中已经介绍了怎样画出简单的图形和直线,其实画出标准的刻度尺也很容易,需要先画出一个矩形作为尺子的轮廓,然后在上边缘画出刻度和数值即可。

       这里要注意的就是屏幕适配的问题,因为在安卓中会有屏幕大小不同,分辨率不同的设备,我们需要保证在不同的设备上同样一厘米长度是相同的。

实现的关键是:

1.获取设备屏幕的信息

2.根据参数绘制尺子和刻度

3.设定尺子的相关动作

       在获取设备屏幕的信息方面,我们需要用到WindowManager和DisplayMetrics这两个类,WindowManager是应用程序使用界面和窗口的管理器,DisplayMetrics用来描述一般显示信息,如它的大小,密度,和字体缩放。

首先我们通过得到一个WindowManager的对象去获取界面的信息

//获取屏幕窗口
WindowManager windowManager = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);

       再得到一个DisplayMetrics的对象获取屏幕的信息

DisplayMetrics phoneDisplay = new DisplayMetrics();
windowManager.getDefaultDisplay().getMetrics(phoneDisplay);

       此时我们就可以通过xdpi()和ydpi()去分别获取在X轴上每英寸长度包含像素点的数量和Y轴上每英寸长度包含像素点的数量,这时的单位是pixal/inch,由于我们要画的是厘米刻度尺(1英寸=2.54厘米),所以我们还要通过除以2.54将单位转化成pixal/cm

//将单位是pixal/inch转换成单位是pixal/cm
xcm = (float) (phoneDisplay.xdpi / 2.54);

       此时,我们就可以通过drawRect()方法画出刻度尺的边框,假定这时我们要画一个长度为6CM,宽度为1CM的刻度尺

xcm = (float) (phoneDisplay.xdpi / 2.54);
//刻度尺的长度
rulerLength = 6 * xcm;
//刻度尺的宽度
rulerWidth = xcm;
//绘制尺子的外边框
canvas.drawRect(0, 0, (int)rulerLength + 30, (int)rulerWidth, paint);

       这里的长度需要多30px,是需要在开头和结尾处留出一定的空间,这样子看起来比较美观,具体的在开头和结尾留出多少空间可以由开发者自行决定
在边框绘制好以后就需要在这个边框的上边缘加上数字和刻度,由观察可以知道从0开始每10MM都有一个数字和长刻度线,每5MM都有一个中刻度线而每,每1MM都有一个短刻度线,由于我们定义的刻度尺长度为6CM,在这里我们就需要画60个刻度

//最小刻度的长度
xmm = rulerLength/60;
for(int i = 0; i <= 60; i++)
{
    //绘制数字
    if(i%10 == 0)
    {
        markLine = longMarkLine;
        canvas.drawText(String.valueOf(i/10), (int)(15+i*xmm), markLine + 20, paint);
    }//绘制中刻度线
    else if(i%5 == 0)
    {
        markLine = middleMarkLine;
    }//绘制短刻度线
    else
    {
        markLine = shortMarkLine;
    }
    canvas.drawLine((int)(15+i*xmm), 0, (int)(15+i*xmm), markLine, paint);
}

       此时刻度尺的已经绘制好了,但是只是固定在屏幕的左上角不能移动,最后我们还需要根据操作让刻度尺可以在屏幕上进行移动。在这里我们选择使用layout()的方法使View滑动。我们都知道,在View进行绘制的时候,会调用layout()方法来设置显示的位置。同样,可以通过修改View的left,top,right,bottom这四个属性来控制View的坐标,在每次回调onTouchEvent()方法的时候,通过计算出新的坐标点使用layout()对View重绘起到View移动的作用

public boolean onTouchEvent(MotionEvent event)
    {
        //获得当前View的位置坐标(这里获取的是绝对坐标)
        int rawX = (int) event.getRawX();
        int rawY = (int) event.getRawY();
        switch(event.getAction())
        {
            //手指按下
            case MotionEvent.ACTION_DOWN:
                //将开始移动前的坐标储存到lastX和lastY中
                lastX = rawX;
                lastY = rawY;
                break;
            //手指移动
            case MotionEvent.ACTION_MOVE:
                //使用移动后的绝对坐标减去初始坐标,计算出View的偏移量
                int offsetX = rawX - lastX;
                int offsetY = rawY - lastY;
                //使用layout()对移动后的View重绘
                layout(getLeft() + offsetX, getTop() + offsetY, getRight() + offsetX, getBottom() + offsetY);
                //对View重绘后需要重新设置初始坐标
                lastX = rawX;
                lastY = rawY;
                break;
            //手指离开
            case MotionEvent.ACTION_UP:
                break;
        }
        return true;
    }

由于在使用刻度尺时我们需要横屏来使用,所以在进入程序中我们需要将所在的Activity做限制横竖屏切换。只需要在AndroidManifest.xml文件中加入android:screenOrientation属性限制。

android:screenOrientation设定该活动的方向,该值可以是任何一个下面的字符串:

"unspecified"
- 默认值,由系统选择指示方向,在不同的设备可能会有所不同默認值

"landscape"
- 横向

"portrait"
- 纵向

"user"
- 用户当前的首选方向

"behind"
- 与在任务栈(活动堆栈)下的Activity方向相同

"sensor"
- 根据重力感应器确定方向,取决于用户手持的方向,随着设备的转动而改变

"nosensor"
- 不经过重力感应器确定方向,该传感器被忽略,不随设备的转动而改变

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.administrator.rulerview" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:supportsRtl="true"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTask"
            android:screenOrientation="landscape">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

3.总结

       自定义控件对于开发者来说是一项必备的技能,在做自定义控件之前应该掌握好自定义View的基础知识,再根据相应的绘制逻辑就可以绘制出我们想要的样式。本篇文章只是介绍了一个很简单的自定义刻度尺,有兴趣的读者也可以在刻度尺上加上游标等功能,使得功能更加的完善。

 

以上Demo的源代码地址:点击打开链接









评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值