如何在Android中制作虚线/破折号线?

336

我想要制作一条虚线。目前我正在使用以下代码绘制实线:

LinearLayout divider = new LinearLayout( this );
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( LinearLayout.LayoutParams.FILL_PARENT, 2 );
divider.setLayoutParams( params );
divider.setBackgroundColor( getResources().getColor( R.color.grey ) );

我需要类似这样的东西,但是要点状而不是实心的。 我想避免制作数百个布局,交替使用透明布局和实体布局。

20个回答

711

没有Java代码:

drawable/dotted.xml:

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

    <stroke
       android:color="#FF00FF"
       android:dashWidth="10px"
       android:dashGap="10px"
       android:width="1dp"/>
</shape>

view.xml:

<ImageView
    android:layout_width="match_parent"
    android:layout_height="5dp"
    android:src="@drawable/dotted"
    android:layerType="software" />

效果: 在此输入图片描述

27
为什么我在手机上看不到断点线,但在Eclipse的图形化布局中却能看到? - Dante
81
没关系,我在这里找到了解决方案:https://dev59.com/Vmgv5IYBdhLWcg3wHNHG 只需将层类型设置为软件:android:layerType="software" - Dante
7
在使用canvas.drawLine()时存在已知的bug(已知问题),作为禁用硬件加速的替代方案,您可以使用canvas.drawPath代替。 - hgoebl
13
使用“dp”代替“px”。 - S.M_Emamian
10
已验证此方法适用于 Android 6.0.1 和 4.4.4 两个版本。需要注意两点:1)确实需要一个 ImageView,带 drawable 作为背景的 View 不能实现此效果;2)必须在 ImageView 上设置 android:layerType="software" - Jonik
显示剩余9条评论

246
路径效果设置在绘制对象上。
Paint fgPaintSel = new Paint();
fgPaintSel.setARGB(255, 0, 0,0);
fgPaintSel.setStyle(Style.STROKE);
fgPaintSel.setPathEffect(new DashPathEffect(new float[] {10f,20f}, 0f));

通过在指定破折号和间隔比率的int[]数组中提供更多数字,您可以创建各种点状图案。这是一条简单的、等距虚线。


2
我直接复制粘贴了这段代码,但没有反应。我需要写额外的代码让它工作吗? - jason
我想申请多种颜色。还有其他解决方案吗? - Bhaven Shah

69

使用XML创建虚线。
在drawable文件夹中创建XML,并将该背景分配给您想要设置点状边框的项。

创建XML背景“dashed_border”:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
    <item>
        <shape>
            <solid android:color="#ffffff" />
            <stroke
                android:dashGap="5dp"
                android:dashWidth="5dp"
                android:width="1dp"
                android:color="#0000FF" />
            <padding
                android:bottom="5dp"
                android:left="5dp"
                android:right="5dp"
                android:top="5dp" />
        </shape>
    </item>
</layer-list>

将该背景添加到项目中:

<Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/dashed_border"/>

1
如果需要边角半径,请在形状中添加<corners android:radius="5dp" />。有关详细信息,请参见https://dev59.com/sZ7ha4cB1Zd3GeqPm6xO#41940609。 - Vadim Kotov
4
我认为对于单个项目而言,layer-list 是不必要的。我使用 <shape> 作为根元素,效果是一样的。 - big_m

43

创建xml文件(view_line_dotted.xml):

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
        <item
            android:bottom="-1dp"
            android:left="-1dp"
            android:right="-1dp"
            android:top="0dp">

            <shape android:shape="rectangle">
                <stroke
                    android:width="1dp"
                    android:color="#ffff0017"
                    android:dashGap="3dp"
                    android:dashWidth="1dp" />

                <solid android:color="@android:color/transparent" />

                <padding
                    android:bottom="10dp"
                    android:left="10dp"
                    android:right="10dp"
                    android:top="10dp" />
            </shape>
        </item>
</layer-list>

将其设置为您视图的背景:

<View
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="@drawable/view_line_dotted" />

请您能否解释一下? - skywall
1
谢谢,关键是 <item android:bottom="-1dp" android:left="-1dp" android:right="-1dp" >,如果你想要一条水平线,厚度为1dp。 - CoolMind
太棒了。对我来说几乎可以直接使用。我唯一需要更改的是更改描边标签;2dp宽度和4dp虚线间隔。 - Sufian
对于 API < 21 的设备,在视图中添加 android:layerType="software" 或写入 view.setLayerType(View.LAYER_TYPE_SOFTWARE, null)(参见 https://dev59.com/Vmgv5IYBdhLWcg3wHNHG)。 - CoolMind

30
当我想要绘制虚线时,我所做的是定义一个可绘制的dash_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="@color/black"
        android:dashWidth="2dp"
        android:dashGap="3dp" />
</shape>

然后在布局中定义一个背景为dash_line的视图。注意要包含android:layerType="software",否则它将无法工作。

<View
    android:layout_width="match_parent"
    android:layout_height="5dp"
    android:background="@drawable/dash_line"
    android:layerType="software" />

25

我有一个自定义的虚线,支持水平和垂直虚线。代码如下:

public class DashedLineView extends View
{
    private float density;
    private Paint paint;
    private Path path;
    private PathEffect effects;

    public DashedLineView (Context context)
    {
        super(context);
        init(context);
    }

    public DashedLineView (Context context, AttributeSet attrs)
    {
        super(context, attrs);
        init(context);
    }

    public DashedLineView (Context context, AttributeSet attrs, int defStyle)
    {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context)
    {
        density = DisplayUtil.getDisplayDensity(context);
        paint = new Paint ();
        paint.setStyle(Paint.Style.STROKE);
        paint.setStrokeWidth(density * 4);
        //set your own color
        paint.setColor(context.getResources().getColor(R.color.XXX));
        path = new Path ();
        //array is ON and OFF distances in px (4px line then 2px space)
        effects = new DashPathEffect (new float [] { 4, 2, 4, 2 }, 0);

    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        // TODO Auto-generated method stub
        super.onDraw(canvas);
        paint.setPathEffect(effects);
        int measuredHeight = getMeasuredHeight ();
        int measuredWidth = getMeasuredWidth ();
        if (measuredHeight <= measuredWidth) {
            // horizontal
            path.moveTo(0, 0);
            path.lineTo(measuredWidth, 0);
            canvas.drawPath(path, paint);
        } else {
            // vertical
            path.moveTo(0, 0);
            path.lineTo(0, measuredHeight);
            canvas.drawPath(path, paint);
        }

    }
}

这种方法比使用XML Shape更可取吗? - IgorGanapolsky

16

如果您正在寻找一条垂直线,请使用此可绘制对象。

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:top="-8dp"
        android:bottom="-8dp"
        android:left="-8dp">
        <shape>
            <solid android:color="@android:color/transparent"/>
            <stroke
                android:width="4dp"
                android:color="#ffffff"
                android:dashGap="4dp"
                android:dashWidth="4dp"/>
        </shape>
    </item>
</layer-list>

负的上、下和左值可以去除形状不需要的边界,只留下一条虚线。

在视图中使用它的方法如下。

<View
android:layout_width="4dp"
android:layout_height="match_parent"
android:background="@drawable/dash_line_vertical"
android:layerType="software" />

12
通过使用这个类,您可以将虚线和下划线效果应用于多行文本。要使用DashPathEffect,您必须关闭TextView的硬件加速(尽管DashPathEffect方法在长文本方面存在问题)。你可以在这里找到我的示例项目:https://github.com/jintoga/Dashed-Underlined-TextView/blob/master/Untitled.png
public class DashedUnderlineSpan implements LineBackgroundSpan, LineHeightSpan {

    private Paint paint;
    private TextView textView;
    private float offsetY;
    private float spacingExtra;

    public DashedUnderlineSpan(TextView textView, int color, float thickness, float dashPath,
                               float offsetY, float spacingExtra) {
        this.paint = new Paint();
        this.paint.setColor(color);
        this.paint.setStyle(Paint.Style.STROKE);
        this.paint.setPathEffect(new DashPathEffect(new float[] { dashPath, dashPath }, 0));
        this.paint.setStrokeWidth(thickness);
        this.textView = textView;
        this.offsetY = offsetY;
        this.spacingExtra = spacingExtra;
    }

    @Override
    public void chooseHeight(CharSequence text, int start, int end, int spanstartv, int v,
                             Paint.FontMetricsInt fm) {
        fm.ascent -= spacingExtra;
        fm.top -= spacingExtra;
        fm.descent += spacingExtra;
        fm.bottom += spacingExtra;
    }

    @Override
    public void drawBackground(Canvas canvas, Paint p, int left, int right, int top, int baseline,
                               int bottom, CharSequence text, int start, int end, int lnum) {
        int lineNum = textView.getLineCount();
        for (int i = 0; i < lineNum; i++) {
            Layout layout = textView.getLayout();
            canvas.drawLine(layout.getLineLeft(i), layout.getLineBottom(i) - spacingExtra + offsetY,
                    layout.getLineRight(i), layout.getLineBottom(i) - spacingExtra + offsetY,
                    this.paint);
        }
    }
}

结果:

虚线下划线


7

要在Canvas上实现点状效果,将此属性设置为绘制对象:

paint.setPathEffect(new DashPathEffect(new float[] {0,30}, 0));

根据您的需要调整数值30:此数值代表每个圆点之间的“距离”。

图片描述


5
我已经为EditText创建了虚线边框,以下是代码示例:
创建一个新的xml文件,例如dashed_border.xml,插入以下代码:
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item
    android:bottom="1dp"
    android:left="-2dp"
    android:right="-2dp"
    android:top="-2dp">
    <shape android:shape="rectangle">
        <stroke
            android:width="2dp"
            android:color="#000000"
            android:dashGap="3dp"
            android:dashWidth="1dp" />

        <solid android:color="#00FFFFFF" />

        <padding
            android:bottom="10dp"
            android:left="10dp"
            android:right="10dp"
            android:top="10dp" />
    </shape>
</item></layer-list>

然后在EditText中使用您的新xml文件,例如:

<EditText
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@drawable/dashed_border"/>

乾杯!:)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接