Android绘制竖直虚线完美解决方案—自定义View

简介: 开发中我们经常会遇到绘制虚线的需求,一般我们使用一个drawable文件即可实现,下面我会先列举常规drawable文件的实现方式。

Android绘制竖直虚线完美解决方案—自定义View

开发中我们经常会遇到绘制虚线的需求,一般我们使用一个drawable文件即可实现,下面我会先列举常规drawable文件的实现方式。

使用drawable绘制水平虚线

水平方向的虚线最好绘制,drawable文件如下所示:

drawable/imaginary_line.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="line">

    <stroke
        android:width="1dp"
        android:color="#000"
        android:dashWidth="5dp"
        android:dashGap="2dp" />

</shape>

在布局中使用如下:

<!-- 这里的高度必须大于drawable中设置的虚线宽度 -->
<View
    android:layout_width="match_parent"
    android:layout_height="2dp"
    android:layout_marginTop="50dp"
    android:background="@drawable/imaginary_line"
    android:layerType="software" />

这里我们需要注意一下几点,第一最好设置android:layerType="software"属性,第二View的高度,最好大于drawable中设置的虚线高度。不然都可能导致虚线不显示。

使用drawable绘制竖直方向虚线

与水平方向虚线相比,竖直方向虚线就麻烦的多了,而且有很多缺陷。

drawable代码如下所示:

drawable/vertical_imaginary_line.xml:

<?xml version="1.0" encoding="utf-8"?>
<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="90"
    android:toDegrees="90">
    <shape android:shape="line">
        <stroke
            android:width="1dp"
            android:color="#000"
            android:dashWidth="5dp"
            android:dashGap="2dp" />
    </shape>
</rotate>

可以看出,实质上是通过View动画,对水平方向的View进行了旋转操作。

具体使用如下:跟水平方向使用方式一样。

 <View
    android:layout_width="200dp"
    android:layout_height="200dp"
    android:layout_alignParentRight="true"
    android:background="@drawable/vertical_imaginary_line"
    android:layerType="software" />

因为View是先绘制水平方向的虚线,然后进行旋转,所以竖直虚线默认就会有偏移量,我们需要手动的去调整位置。

实现效果如下所示:

单个虚线还好说,如果需要绘制图表的网格线之类的需求,那就要欲哭无泪了。

自定义DividerView

接下来祭出我们的大杀器自定义View。

先定义下需求,我们的虚线需要支持自定义背景色,支持自定义虚线宽度,支持水平和竖直方向,支持虚线的dash宽度和dash间隔,所以我们的自定义属性就如下所示:

attrs.xml:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <!-- 垂直方向的虚线 -->
    <declare-styleable name="DividerView">
        <!-- 虚线颜色 -->
        <attr name="divider_line_color" format="color"/>
        <!-- 虚线宽度 -->
        <attr name="dashThickness" format="dimension"/>
        <!-- 虚线dash宽度 -->
        <attr name="dashLength" format="dimension"/>
        <!-- 虚线dash间隔 -->
        <attr name="dashGap" format="dimension"/>
        <!-- 虚线朝向 -->
        <attr name="divider_orientation" format="enum">
            <enum name="horizontal" value="0"/>
            <enum name="vertical" value="1"/>
        </attr>
    </declare-styleable>
</resources>

接下来我们看下DividerView的具体实现:
自定义View的第一步,通常是获取自定义的属性值,具体如下所示:

public DividerView(Context context, AttributeSet attrs) {
    super(context, attrs);
    int dashGap, dashLength, dashThickness;
    int color;

    TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.DividerView, 0, 0);

    try {
        dashGap = a.getDimensionPixelSize(R.styleable.DividerView_dashGap, 5);
        dashLength = a.getDimensionPixelSize(R.styleable.DividerView_dashLength, 5);
        dashThickness = a.getDimensionPixelSize(R.styleable.DividerView_dashThickness, 3);
        color = a.getColor(R.styleable.DividerView_divider_line_color, 0xff000000);
        orientation = a.getInt(R.styleable.DividerView_divider_orientation, ORIENTATION_HORIZONTAL);
    } finally {
        a.recycle();
    }

    mPaint = new Paint();
    mPaint.setAntiAlias(true);
    mPaint.setColor(color);
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setStrokeWidth(dashThickness);
    mPaint.setPathEffect(new DashPathEffect(new float[]{dashGap, dashLength,}, 0));
}

我们通过TypedArray获取到我们设置的自定义属性值,并给各个属性设置默认值;接着初始化我们的画笔paint。

初始化工作完毕后,就是绘制工作了,代码如下所示:

@Override
protected void onDraw(Canvas canvas) {
    if (orientation == ORIENTATION_HORIZONTAL) {
        float center = getHeight() * 0.5f;
        canvas.drawLine(0, center, getWidth(), center, mPaint);
    } else {
        float center = getWidth() * 0.5f;
        canvas.drawLine(center, 0, center, getHeight(), mPaint);
    }
}

具体使用如下所示:

横向虚线:

<com.tinytongtong.dividerviewdemo.DividerView
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:layout_marginTop="50dp"
    android:layerType="software"
    custom:dashGap="4dp"
    custom:dashLength="1dp"
    custom:dashThickness="1dp"
    custom:divider_line_color="#ef5350"
    custom:divider_orientation="horizontal" />

竖向虚线:

<com.tinytongtong.dividerviewdemo.DividerView
    android:layout_width="1dp"
    android:layout_height="match_parent"
    android:layout_alignParentRight="true"
    android:layout_marginRight="50dp"
    android:layerType="software"
    custom:dashGap="4dp"
    custom:dashLength="1dp"
    custom:dashThickness="1dp"
    custom:divider_line_color="#ef5350"
    custom:divider_orientation="vertical" />

效果图如下所示:

DividerView项目地址

参考:
Android竖虚线绘制

相关文章
|
1月前
|
缓存 前端开发 Android开发
安卓开发中的自定义视图:从零到英雄
【10月更文挑战第42天】 在安卓的世界里,自定义视图是一块画布,让开发者能够绘制出独一无二的界面体验。本文将带你走进自定义视图的大门,通过深入浅出的方式,让你从零基础到能够独立设计并实现复杂的自定义组件。我们将探索自定义视图的核心概念、实现步骤,以及如何优化你的视图以提高性能和兼容性。准备好了吗?让我们开始这段创造性的旅程吧!
27 1
|
1月前
|
XML 前端开发 Android开发
Android:UI:Drawable:View/ImageView与Drawable
通过本文的介绍,我们详细探讨了Android中Drawable、View和ImageView的使用方法及其相互关系。Drawable作为图像和图形的抽象表示,提供了丰富的子类和自定义能力,使得开发者能够灵活地实现各种UI效果。View和ImageView则通过使用Drawable实现了各种图像和图形的显示需求。希望本文能为您在Android开发中使用Drawable提供有价值的参考和指导。
40 2
|
1月前
|
开发框架 前端开发 Android开发
探索安卓和iOS应用开发中的跨平台解决方案
【10月更文挑战第42天】在移动应用开发的广阔天地中,安卓和iOS系统如同两座巍峨的山峰,分别占据着半壁江山。开发者们在这两座山峰之间穿梭,努力寻找一种既能节省资源又能提高效率的跨平台开发方案。本文将带你走进跨平台开发的世界,探讨各种解决方案的优势与局限,并分享一些实用的代码示例,助你在应用开发的道路上更加游刃有余。
|
1月前
|
搜索推荐 前端开发 Android开发
安卓应用开发中的自定义视图实现
【10月更文挑战第30天】在安卓开发的海洋中,自定义视图是那抹不可或缺的亮色,它为应用界面的个性化和交互体验的提升提供了无限可能。本文将深入探讨如何在安卓平台创建自定义视图,并展示如何通过代码实现这一过程。我们将从基础出发,逐步引导你理解自定义视图的核心概念,然后通过一个实际的代码示例,详细讲解如何将理论应用于实践,最终实现一个美观且具有良好用户体验的自定义控件。无论你是想提高自己的开发技能,还是仅仅出于对安卓开发的兴趣,这篇文章都将为你提供价值。
|
1月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
41 5
|
2月前
|
缓存 数据处理 Android开发
在 Android 中使用 RxJava 更新 View
【10月更文挑战第20天】使用 RxJava 来更新 View 可以提供更优雅、更高效的解决方案。通过合理地运用操作符和订阅机制,我们能够轻松地处理异步数据并在主线程中进行 View 的更新。在实际应用中,需要根据具体情况进行灵活运用,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在 Android 中使用 RxJava 更新 View 的技巧和方法,为开发高质量的 Android 应用提供有力支持。
|
2月前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
43 2
|
2月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
2月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
29 2
|
1月前
|
安全 搜索推荐 程序员
深入探索Android系统的碎片化问题及其解决方案
在移动操作系统的世界中,Android以其开放性和灵活性赢得了广泛的市场份额。然而,这种开放性也带来了一个众所周知的问题——系统碎片化。本文旨在探讨Android系统碎片化的现状、成因以及可能的解决方案,为开发者和用户提供一种全新的视角来理解这一现象。通过分析不同版本的Android系统分布、硬件多样性以及更新机制的影响,我们提出了一系列针对性的策略,旨在减少碎片化带来的影响,提升用户体验。