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.

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

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.


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

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

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

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

}
}

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


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

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>

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! :)



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>

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


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

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

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>


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

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

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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.