Bagaimana cara membuat garis putus-putus / putus-putus di Android?

254

Saya mencoba membuat garis putus-putus. Saya menggunakan ini sekarang untuk garis padat:

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 ) );

Saya butuh sesuatu seperti ini, tetapi bertitik bukannya padat. Saya ingin menghindari membuat ratusan tata letak secara bergantian antara tata letak transparan dan tata letak solid.

Jason Robinson
sumber

Jawaban:

517

Tanpa kode 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="#C7B299"
       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" />
embo
sumber
21
Saya tidak mengerti mengapa saya mendapatkan saluran tanpa celah di ponsel saya, sementara saya melihat celah di Tata Letak Grafis di Eclipse.
Dante
73
Sudahlah, saya menemukan solusinya di sini: stackoverflow.com/questions/10843402/… Cukup setel jenis layer ke perangkat lunak: android: layerType = "software"
Dante
7
Ada bug yang dikenal saat menggunakan canvas.drawLine(). Sebagai alternatif untuk menonaktifkan akselerasi perangkat keras, Anda dapat menggunakannya canvas.drawPath.
hgoebl
10
gunakan dp sebagai ganti px .
S.M_Emamian
7
Diverifikasi bahwa ini berfungsi pada Android 6.0.1 dan 4.4.4. Dua hal yang perlu diperhatikan: 1) Anda memang membutuhkan ImageView, sebuah Tampilan dengan drawable karena background tidak melakukannya; 2) android:layerType="software"harus diatur pada ImageView.
Jonik
206

efek jalur diatur pada objek cat

Paint fgPaintSel = new Paint();
fgPaintSel.setARGB(255, 0, 0,0);
fgPaintSel.setStyle(Style.STROKE);
fgPaintSel.setPathEffect(new DashPathEffect(new float[] {10,20}, 0));

Anda dapat membuat segala macam pola titik-titik dengan menyediakan lebih banyak angka dalam array int [] yang menentukan rasio dasbor dan celah. Ini adalah garis yang sederhana, sama-sama putus-putus.

siliconeagle
sumber
mengapa ini sekarang bagi saya? stackoverflow.com/questions/12401311/…
Chris.Zou
coba float baru [] {5,10,15,20} di konstruktor
siliconeagle
4
Saya sedikit baru dalam pengembangan android. Saya ingin bertanya bagaimana objek cat dengan efek putus-putus ditambahkan ke tata letak linier yang baru saja saya buat?
DirkJan
Saya menyalin dan menempelkan kode ini secara langsung, tetapi tidak ada yang terjadi. Haruskah saya menulis kode tambahan untuk membuatnya berfungsi?
jason
50

Membuat garis putus-putus menggunakan XML.
Buat xml di folder yang dapat digambar dan berikan latar belakang itu ke item yang ingin Anda tetapkan batas bertitik.

Membuat Latar Belakang 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>

Menambahkan latar belakang itu ke item:

<Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@drawable/dashed_border"/>
Sargam
sumber
Jika Anda membutuhkan radius untuk sudut, cukup tambahkan <corners android:radius="5dp" />ke bentuk Anda. Lihat stackoverflow.com/a/41940609/1000551 untuk info lebih lanjut
Vadim Kotov
Saya pikir daftar layer tidak perlu untuk satu item. Saya menggunakan <shape> sebagai elemen root dan kerjanya sama.
big_m
37

Buat 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>

Tetapkan sebagai latar belakang tampilan Anda:

<View
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="@drawable/view_line_dotted" />
tier777
sumber
Bisakah Anda jelaskan?
skywall
1
Terima kasih, petunjuknya adalah <item android:bottom="-1dp" android:left="-1dp" android:right="-1dp" >, jika Anda menginginkan ketebalan garis 1dp garis horizontal.
CoolMind
Luar biasa. Hampir berhasil di luar kotak untuk saya. Satu-satunya perubahan yang saya butuhkan adalah mengubah tag stroke; Lebar 2dp dan dashDap 4dp.
Sufian
Untuk perangkat dengan API <21 tambahkan android:layerType="software"ke tampilan atau tulis view.setLayerType(View.LAYER_TYPE_SOFTWARE, null)(lihat stackoverflow.com/questions/10843402/… ).
CoolMind
24

Apa yang saya lakukan ketika saya ingin menggambar garis putus-putus adalah mendefinisikan dash_line.xml yang dapat ditarik :

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="line" >
<stroke
    android:dashGap="3dp"
    android:dashWidth="2dp"
    android:width="1dp"
    android:color="@color/black" />
</shape>

Dan kemudian dalam tata letak hanya mendefinisikan tampilan dengan latar belakang sebagai dash_line . Catatan untuk menyertakan android: layerType = "software" , jika tidak maka tidak akan berfungsi.

<View
            android:layout_width="match_parent"
            android:layout_height="5dp"
            android:background="@drawable/dash_line"
            android:layerType="software" />
Tony Vu
sumber
Terima kasih sobat! Ini android:layerType="software"adalah hal yang saya cari! Bersulang!
Toochka
20

Saya memiliki kustom garis garis yang mendukung garis garis horizontal & vertikal. kode di bawah ini:

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);
    }

}
}
ruidge
sumber
Apakah pendekatan ini lebih disukai daripada bentuk xml?
IgorGanapolsky
sempurna! apa yang saya cari
Ayub M
9

Dengan menggunakan kelas ini, Anda dapat menerapkan efek "putus-putus dan garis bawah" ke beberapa baris teks. untuk menggunakan DashPathEffect Anda harus mematikan hardwareAccelerated dari TextView Anda (meskipun metode DashPathEffect memiliki masalah dengan teks yang panjang). Anda dapat menemukan contoh proyek saya di sini: https://github.com/jintoga/Dashed-Underlined-TextView/blob/master/Untitle.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);
        }
    }
}

Hasil:

garis bawah putus-putus

Nguyen Quoc Dat
sumber
8

Jika Anda mencari garis vertikal, gunakan drawable ini.

<?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>

Nilai bagian bawah dan kiri atas negatif menghilangkan sisi yang tidak diinginkan dari bentuk meninggalkan garis putus-putus tunggal.

Gunakan dalam tampilan seperti itu.

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

Saya telah menggunakan di bawah ini sebagai latar belakang untuk tata letak:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
<stroke
   android:width="1dp"
    android:dashWidth="10px"
   android:dashGap="10px"
    android:color="android:@color/black" 
   />
</shape>
Udai
sumber
Kenapa android:shape="rectangle"bukannya line?
IgorGanapolsky
4

Saya telah membuat garis putus-putus untuk EditText. Ini dia Buat xml baru Anda. mis. dashed_border.xml Kode di sini:

<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>

Dan gunakan file xml baru Anda di EditText Anda misalnya:

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

Bersulang! :)

Wiktor Kalinowski
sumber
3

Solusi Terbaik untuk Dotted Background bekerja dengan sempurna

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
       android:shape="rectangle">
  <stroke
    android:dashGap="3dp"
    android:dashWidth="2dp"
    android:width="1dp"
    android:color="@color/colorBlack" />
</shape>
Arun Prajapati
sumber
3

Untuk efek Dotted pada Kanvas, atur atribut ini ke objek cat:

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

Dan ubah nilai 30 sesuai dengan yang Anda render: ini mewakili "jarak" antara setiap titik.

masukkan deskripsi gambar di sini

Arnaud
sumber
2

Satu-satunya hal yang bekerja untuk saya dan saya pikir itu adalah cara paling sederhana menggunakan Path dengan objek cat seperti ini:

    Paint paintDash = new Paint();
    paintDash.setARGB(255, 0, 0, 0);
    paintDash.setStyle(Paint.Style.STROKE);
    paintDash.setPathEffect(new DashPathEffect(new float[]{10f,10f}, 0));
    paintDash.setStrokeWidth(2);
    Path pathDashLine = new Path();

Kemudian onDraw (): (reset panggilan penting jika Anda mengubah titik-titik antara panggilan ondraw, menyebabkan Path menyimpan semua gerakan)

    pathDashLine.reset();
    pathDashLine.moveTo(porigenX, porigenY);
    pathDashLine.lineTo(cursorX,cursorY);
    c.drawPath(pathDashLine, paintDash);
takluiper
sumber
2

Saya menyukai solusi dari Ruidge , tetapi saya membutuhkan lebih banyak kontrol dari XML. Jadi saya mengubahnya ke Kotlin dan menambahkan atribut.

1) Salin kelas Kotlin:

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.View

class DashedDividerView : View {
constructor(context: Context) : this(context, null, 0)
constructor(context: Context, attributeSet: AttributeSet) : this(context, attributeSet, 0)

companion object {
    const val DIRECTION_VERTICAL = 0
    const val DIRECTION_HORIZONTAL = 1
}

private var dGap = 5.25f
private var dWidth = 5.25f
private var dColor = Color.parseColor("#EE0606")
private var direction = DIRECTION_HORIZONTAL
private val paint = Paint()
private val path = Path()

constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
    context,
    attrs,
    defStyleAttr
) {
    val typedArray = context.obtainStyledAttributes(
        attrs,
        R.styleable.DashedDividerView,
        defStyleAttr,
        R.style.DashedDividerDefault
    )

    dGap = typedArray.getDimension(R.styleable.DashedDividerView_dividerDashGap, dGap)
    dWidth = typedArray.getDimension(R.styleable.DashedDividerView_dividerDashWidth, dWidth)
    dColor = typedArray.getColor(R.styleable.DashedDividerView_dividerDashColor, dColor)
    direction =
        typedArray.getInt(R.styleable.DashedDividerView_dividerDirection, DIRECTION_HORIZONTAL)

    paint.color = dColor
    paint.style = Paint.Style.STROKE
    paint.pathEffect = DashPathEffect(floatArrayOf(dWidth, dGap), 0f)
    paint.strokeWidth = dWidth

    typedArray.recycle()
}

override fun onDraw(canvas: Canvas) {
    super.onDraw(canvas)
    path.moveTo(0f, 0f)

    if (direction == DIRECTION_HORIZONTAL) {
        path.lineTo(measuredWidth.toFloat(), 0f)
    } else {
        path.lineTo(0f, measuredHeight.toFloat())
    }
    canvas.drawPath(path, paint)
}

}

2) Buat file attr di direktori / res dan tambahkan ini

 <declare-styleable name="DashedDividerView">
    <attr name="dividerDashGap" format="dimension" />
    <attr name="dividerDashWidth" format="dimension" />
    <attr name="dividerDashColor" format="reference|color" />
    <attr name="dividerDirection" format="enum">
        <enum name="vertical" value="0" />
        <enum name="horizontal" value="1" />
    </attr>
</declare-styleable>

3) Tambahkan gaya ke file gaya

 <style name="DashedDividerDefault">
    <item name="dividerDashGap">2dp</item>
    <item name="dividerDashWidth">2dp</item>
    <!-- or any color -->
    <item name="dividerDashColor">#EE0606</item>
    <item name="dividerDirection">horizontal</item>
</style>

4) Sekarang Anda dapat menggunakan gaya default

<!-- here will be your path to the class -->
<com.your.package.app.DashedDividerView
    android:layout_width="match_parent"
    android:layout_height="2dp"
    />

atau atur atribut dalam XML

<com.your.package.app.DashedDividerView
    android:layout_width="match_parent"
    android:layout_height="2dp"
    app:dividerDirection="horizontal"
    app:dividerDashGap="2dp"
    app:dividerDashWidth="2dp"
    app:dividerDashColor="@color/light_gray"/>
Igor
sumber
2

Tidak satu pun dari jawaban ini yang berhasil untuk saya. Sebagian besar jawaban ini memberi Anda batas setengah transparan. Untuk menghindari hal ini, Anda perlu membungkus wadah Anda sekali lagi dengan wadah lain dengan warna pilihan Anda. Berikut ini sebuah contoh:

Ini adalah tampilannya

dashed_border_layout.xml

<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="@color/black"
android:background="@drawable/dashed_border_out">
<LinearLayout
    android:layout_width="150dp"
    android:layout_height="50dp"
    android:padding="5dp"
    android:background="@drawable/dashed_border_in"
    android:orientation="vertical">
    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="This is&#10;Dashed Container"
        android:textSize="16sp" />
</LinearLayout>

dashed_border_in.xml

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

dashed_border_out.xml

<layer-list xmlns:android="http://schemas.android.com/apk/res/android" >
<item>
    <shape>
        <corners android:radius="12dp" />
    </shape>
</item>

Yunus Emre
sumber
1

Saya tidak tahu mengapa tetapi jawaban yang dipilih tidak bekerja untuk saya. Saya menulis seperti ini dan bekerja dengan baik.
Tentukan tampilan khusus:

public class XDashedLineView extends View {

private Paint   mPaint;
private Path    mPath;
private int     vWidth;
private int     vHeight;

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

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

public XDashedLineView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    mPaint = new Paint();
    mPaint.setColor(Color.parseColor("#3F577C"));
    mPaint.setStyle(Paint.Style.STROKE);
    mPaint.setPathEffect(new DashPathEffect(new float[] {10,10}, 0));
    mPath = new Path();
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    this.vWidth = getMeasuredWidth();
    this.vHeight = getMeasuredHeight();
    mPath.moveTo(0, this.vHeight / 2);
    mPath.quadTo(this.vWidth / 2, this.vHeight / 2, this.vWidth, this.vHeight / 2);
}

@Override
protected void onDraw(Canvas canvas) {
    super.onDraw(canvas);
    canvas.drawPath(mPath, mPaint);
}
}

Kemudian Anda bisa menggunakannya di xml Anda:

        <com.YOUR_PACKAGE_NAME.XDashedLineView
        android:layout_width="690dp"
        android:layout_height="1dp"
        android:layout_marginLeft="30dp"
        android:layout_marginTop="620dp"/>
Kyeson
sumber
1

Saya telah membuat perpustakaan dengan tampilan khusus untuk menyelesaikan masalah ini, dan itu harus sangat mudah digunakan. Lihat https://github.com/Comcast/DahDit untuk lebih lanjut. Anda dapat menambahkan garis putus-putus seperti ini:

<com.xfinity.dahdit.DashedLine
    android:layout_width="250dp"
    android:layout_height="wrap_content"
    app:dashHeight="4dp"
    app:dashLength="8dp"
    app:minimumDashGap="3dp"
    app:layout_constraintRight_toRightOf="parent"
    android:id="@+id/horizontal_dashes"/>
Calvin
sumber
Terima kasih telah berbagi. Saya harus memperbaikinya untuk kasus penggunaan saya, tetapi inilah yang saya butuhkan untuk memulai dengan tampilan khusus. Bersulang.
0

Mirip dengan tier777 di sini adalah solusi untuk garis horizontal:

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

Petunjuknya adalah <item android:top="-1dp">.

Untuk menunjukkan garis putus-putus pada perangkat lama (<= API 21) Anda harus membuat tampilan dengan android:layerType="software"(lihat Android melacak garis putus-putus potensi gangguan ICS yang dapat ditarik ):

<?xml version="1.0" encoding="utf-8"?>
<View xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="1dp"
    android:background="@drawable/dashed_line"
    android:layerType="software"
    />

Anda juga dapat menambahkan pandangan yang sama tanpa android:layerType="software"ke layout-v23untuk kinerja yang lebih baik, tapi saya tidak yakin itu akan bekerja pada semua perangkat dengan API 23.

CoolMind
sumber