Android'de noktalı / kesikli bir çizgiyi nasıl oluşturabilirim?


254

Noktalı bir çizgi yapmaya çalışıyorum. Bunu şu anda sağlam bir çizgi için kullanıyorum:

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

Böyle bir şeye ihtiyacım var ama katı yerine noktalı. Saydam bir düzen ile sağlam bir düzen arasında dönüşümlü olarak yüzlerce düzen yapmaktan kaçınmak istiyorum.

Yanıtlar:


517

Java kodu olmadan:

çekilebilir / 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
Eclipse'deki Grafiksel Düzen'deki boşlukları görürken neden telefonumda boşluklar olmadan bir çizgi elde ettiğimi anlamıyorum.
Dante

73
Boş verin, çözümü burada buldum: stackoverflow.com/questions/10843402/… Sadece katman türünü yazılıma ayarlayın: android: layerType = "yazılım"
Dante

7
Bir yoktur bilinen bir hata kullanarak canvas.drawLine(). Donanım hızlandırmayı devre dışı bırakmaya alternatif olarak canvas.drawPathbunun yerine kullanabilirsiniz .
hgoebl

10
dp yerine kullanın px .
S.M_Emamian

7
Bunun hem Android 6.0.1 hem de 4.4.4 sürümlerinde çalıştığı doğrulandı. Dikkat edilmesi gereken iki şey: 1) gerçekten bir ImageView'a ihtiyacınız var, arka plan olarak çekilebilir bir Görünüm bunu yapmadı; 2) android:layerType="software"ImageView üzerinde ayarlanmalıdır.
Jonik

206

boya efekti üzerinde yol efekti ayarlanır

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

tire ve boşluk oranlarını belirttiği int [] dizisine daha fazla sayı sağlayarak her türlü noktalı deseni oluşturabilirsiniz. Bu basit, eşit kesik çizgili bir çizgidir.


neden şimdi benim için yapıyor? stackoverflow.com/questions/12401311/…
Chris.Zou

Yeni şamandıra deneyin [] {5,10,15,20} yapıcıda
siliconeagle

4
Android geliştirmede biraz yeniyim. Çizdi efektli boya nesnesinin az önce oluşturduğum doğrusal düzene nasıl eklendiğini sormak istiyorum.
DirkJan

Bu kodu doğrudan kopyalayıp yapıştırdım, ancak hiçbir şey olmadı. Çalışması için fazladan kod yazmalı mıyım?
Jason

50

XML kullanarak noktalı çizgi oluşturma.
Çekilebilir klasörde xml oluşturun ve bu arka planı noktalı kenarlık ayarlamak istediğiniz öğeye verin.

XML Arka Planı "dashed_border" oluşturuluyor:

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

Bu arka planı öğeye ekleme:

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

Köşeler için yarıçapa ihtiyacınız varsa, sadece <corners android:radius="5dp" />şekline ekleyin . Daha fazla bilgi için stackoverflow.com/a/41940609/1000551
Vadim Kotov

Katman listesinin tek bir öğe için gereksiz olduğunu düşünüyorum. <shape> 'i kök eleman olarak kullandım ve aynı şekilde çalışıyor.
big_m

37

Xml oluşturun (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>

Görünümünüzün arka planı olarak ayarlayın:

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

Açıklayabilir misiniz lütfen?
skywall

1
Teşekkürler, ipucu, <item android:bottom="-1dp" android:left="-1dp" android:right="-1dp" >yatay bir çizgi 1dp kalınlık istiyorsanız.
CoolMind

Muhteşem. Neredeyse benim için kutudan çıkıyor. İhtiyacım olan tek değişiklik kontur etiketini değiştirmekti; 2dp genişlik ve 4dp dashGap.
Sufyan

API <21 olan cihazlar için android:layerType="software"bir görünüme ekleyin veya yazın view.setLayerType(View.LAYER_TYPE_SOFTWARE, null)(bkz. Stackoverflow.com/questions/10843402/… ).
CoolMind

24

Noktalı bir çizgi çizmek istediğimde, çekilebilir bir dash_line.xml tanımlamak için ne yaptım :

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

Ve sonra mizanpajda arka planlı bir görünümü dash_line olarak tanımlayın . Android'i eklemeyi unutmayın : layerType = "software" , aksi takdirde çalışmaz.

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

Teşekkürler dostum! android:layerType="software"Aradığım şey! Şerefe!
Toochka

20

Yatay ve dikey çizgi çizgisini destekleyen özel bir çizgim var. aşağıdaki kod:

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

}
}

Bu yaklaşım xml şekline göre tercih edilebilir mi?
IgorGanapolsky

mükemmel! ne aradığım
Job M

9

Bu sınıfı kullanarak, birden çok satır metnine "kesik çizgili ve altı çizili" efekt uygulayabilirsiniz. DashPathEffect'i kullanmak için TextView'inizden hızlandırılmış donanımı kapatmanız gerekir (DashPathEffect yönteminin uzun metinle ilgili bir sorunu olsa da). örnek projemi burada bulabilirsiniz: 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);
        }
    }
}

Sonuç:

kesik çizgili alt çizgi


8

Dikey bir çizgi arıyorsanız bu çekmeceyi kullanın.

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

Negatif üst alt ve sol değerler, şeklin istenmeyen kenarlarını tek bir kesikli çizgi bırakarak kaldırır.

Böyle bir görünümde kullanın.

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

4

Aşağıdaki düzen için arka plan olarak kullandım:

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

Neden android:shape="rectangle"hat yerine?
IgorGanapolsky

4

EditText için kesikli noktalı çizgi oluşturdum. Hadi bakalım. Yeni xml'nizi oluşturun. örneğin dashed_border.xml Buraya kod verin:

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

Örneğin, EditText'inizdeki yeni xml dosyanızı kullanın:

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

Şerefe! :)



3

Noktalı Arkaplanın mükemmel çalışması için En İyi Çözüm

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

Bir Tuval üzerindeki Noktalı efekt için, bu niteliği paint nesnesine ayarlayın:

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

Ve renderiniz size uygun olarak 30 değerini değiştirin: her nokta arasındaki "mesafeyi" temsil eder.

resim açıklamasını buraya girin


2

Benim için çalışan tek şey ve bence en basit yolu böyle bir boya nesnesine sahip bir Yol kullanmaktır:

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

Sonra onDraw (): (ondraw çağrıları arasındaki bu noktaları değiştirirseniz, Yol tüm hareketleri kaydetmenize neden olursa önemli çağrı sıfırlama)

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

2

Ruidge'nin çözümünü beğendim , ancak XML üzerinde daha fazla kontrole ihtiyacım vardı. Bu yüzden Kotlin olarak değiştirdim ve nitelikler ekledim.

1) Kotlin sınıfını kopyalayın:

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) / res dizininde bir attr dosyası oluşturun ve ekleyin

 <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) Stiller dosyasına bir stil ekleyin

 <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) Artık varsayılan stili kullanabilirsiniz

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

veya XML'de nitelikleri ayarlama

<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

Bu cevapların hiçbiri benim için işe yaramadı. Bu cevapların çoğu size yarı saydam bir sınır verir. Bundan kaçınmak için, kabınızı bir kez daha tercih ettiğiniz renkle başka bir kaba sarmanız gerekir. İşte bir örnek:

Öyle görünüyor

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

Nedenini bilmiyorum ama oylanan cevaplar benim için çalışmıyor. Bu şekilde yazıyorum ve iyi çalışıyor.
Özel bir görünüm tanımlayın:

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

Sonra xml'nizde kullanabilirsiniz:

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

1

Bu sorunu çözmek için özel bir görünüme sahip bir kütüphane oluşturdum ve kullanımı çok basit olmalı. Daha fazla bilgi için https://github.com/Comcast/DahDit adresine bakın . Bunun gibi kesikli çizgiler ekleyebilirsiniz:

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

Paylaşım için teşekkürler. Kullanım durumum için hassaslaştırmak zorunda kalacağım, ancak özel görünümlere başlamak için tam da ihtiyacım olan şey bu. Şerefe.

0

Tier777'ye benzer şekilde yatay bir çizgi için bir çözüm:

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

İpucu <item android:top="-1dp">.

Eski cihazlarda kesikli çizgi göstermek için (<= API 21) ile bir görünüm oluşturmalısınız android:layerType="software"(bkz. Android kesikli çizgi çekilebilir potansiyel ICS hatası ):

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

Ayrıca olmadan aynı görünümü ekleyebilirsiniz android:layerType="software"için layout-v23daha iyi performans için, ama emin o API 23 ile tüm cihazlarda çalışacak değilim.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.