Creating horizontal and vertical dotted lines in android

I found the solution

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="90"
    android:toDegrees="90" >

    <shape android:shape="line" >
        <stroke
            android:dashGap="6px"
            android:dashWidth="6px"
            android:color="#C7B299" />
    </shape>

</rotate>

OR

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromDegrees="90"
    android:toDegrees="90"
    android:drawable="@drawable/horizontal_line"/>

If the View has 1dp width then just rotating your horizontal line is not enough. The vertical line’s length will be 1dp as it is drawn horizontally first, then rotated. Here is a trick to solve this problem:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:left="-300dp"
        android:right="-300dp">
        <rotate
            android:drawable="@drawable/dash_line_divider_horizontal"
            android:fromDegrees="90"
            android:toDegrees="90"/>
    </item>
</layer-list>

enter image description here

To achieve this, You should create 2 different drawable,

1. Horizontal Line: res/drawable/bg_horizontal_dotted_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="0.8dp"
    android:color="@color/text_grey"
    android:dashWidth="4dp"
    android:dashGap="3dp" />
</shape>

2. Vertical Drawable: res/drawable/bg_dotted_line_vertical.xml

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
  <item
    android:left="-600dp"
    android:right="-600dp">
    <rotate
      android:drawable="@drawable/bg_horizontal_dotted_line"
      android:fromDegrees="90"
      android:visible="true" />
  </item>
</layer-list>

Now, All you need to do is apply the above vertical XML into the view,

<View
            android:id="@+id/imageView7"
            android:layout_width="1dp"
            android:layout_height="0dp"
            android:background="@drawable/bg_dotted_line_vertical"
            android:layerType="software"/>

Complete Code:

<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
      android:id="@+id/ll_task_expanded"
      android:layout_width="match_parent"
      android:layout_height="200dp"
      android:orientation="vertical"
      app:canExpand="false"
      app:expanded="true">


      <ImageView
        android:id="@+id/imageView5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        app:layout_constraintBottom_toBottomOf="@+id/textView3"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="@+id/textView3"
        app:srcCompat="@drawable/ic_circle" />

      <ImageView
        android:id="@+id/imageView6"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toBottomOf="@+id/textView4"
        app:layout_constraintEnd_toEndOf="@+id/imageView5"
        app:layout_constraintStart_toStartOf="@+id/imageView5"
        app:layout_constraintTop_toTopOf="@+id/textView4"
        app:srcCompat="@drawable/ic_circle" />

      <View
        android:id="@+id/imageView7"
        android:layout_width="1dp"
        android:layout_height="0dp"
        android:background="@drawable/bg_dotted_line_vertical"
        android:layerType="software"
        app:layout_constraintBottom_toTopOf="@+id/imageView6"
        app:layout_constraintEnd_toEndOf="@+id/imageView5"
        app:layout_constraintStart_toStartOf="@+id/imageView5"
        app:layout_constraintTop_toBottomOf="@+id/imageView5" />

      <TextView
        android:id="@+id/textView3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="16dp"
        android:layout_marginTop="16dp"
        android:text="TextView"
        app:layout_constraintStart_toEndOf="@+id/imageView5"
        app:layout_constraintTop_toTopOf="parent" />

      <TextView
        android:id="@+id/textView4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50dp"
        android:text="TextView"
        app:layout_constraintEnd_toEndOf="@+id/textView3"
        app:layout_constraintStart_toStartOf="@+id/textView3"
        app:layout_constraintTop_toBottomOf="@+id/textView3" />
    </androidx.constraintlayout.widget.ConstraintLayout>

I think I've found a "cleaner" solution for this problem by creating a custom view containing specific code to draw the dashed lines (in both vertical and horizontal orientations), and a bunch of attributes to make it very easy to use it from XML layouts. The main advantage of this approach over the "rotated line" method is that you can set the size of the dashed line view the way you would normally do, without having to worry about how the view is going to behave after the rotation (once the rotation applies to the entire dashed line view and not only to the line being drawn).

So here is the step by step solution:

  1. Create the file "/res/values/attrs.xml" with the following contents:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
    
    <declare-styleable name="DividerView">
        <attr name="color" format="color" />
        <attr name="dashLength" format="dimension" />
        <attr name="dashGap" format="dimension" />
        <attr name="dashThickness" format="dimension" />
        <attr name="orientation" format="enum">
            <enum name="horizontal" value="0" />
            <enum name="vertical" value="1" />
        </attr>
    </declare-styleable>
    
    </resources>
    

This creates the attributes to control the custom view. Note: If the file above already exists in your project, just copy/paste the "declare-stylable" block inside the existing "resources" block.

  1. Create the class DividerView and paste the contents below:

    public class DividerView extends View {
    static public int ORIENTATION_HORIZONTAL = 0;
    static public int ORIENTATION_VERTICAL = 1;
    private Paint mPaint;
    private int orientation;
    
    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_color, 0xff000000);
            orientation = a.getInt(R.styleable.DividerView_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[] { dashLength, dashGap, }, 0));
    }
    
    public DividerView(Context context) {
        this(context, null);
    }
    
    @Override
    protected void onDraw(Canvas canvas) {
        if (orientation == ORIENTATION_HORIZONTAL) {
            float center = getHeight() * .5f; 
            canvas.drawLine(0, center, getWidth(), center, mPaint);
        } else {
            float center = getWidth() * .5f; 
            canvas.drawLine(center, 0, center, getHeight(), mPaint);
        }
    }
    }
    
  2. In order to use auto-complete of attributes on your layout files, add the following name space definition on the topmost container:

    xmlns:custom="http://schemas.android.com/apk/res/com.example"
    

Replace com.example by the name of your package. You can also change custom by any prefix that better suits your needs. Note: You may need to restart Eclipse to get the auto-complete working after changes on attrs.xml file.

  1. And finally create your dashed lines by inserting the following element on your layout, like any other view:

    <com.example.DividerView
        android:layout_width="1dp"
        android:layout_height="fill_parent"
        android:layerType="software" 
        custom:color="@color/grey"
        custom:orientation="vertical"
        custom:dashLength="1dp"
        custom:dashGap="1dp"
        custom:dashThickness="1dp" />
    

I hope it helps!