将自定义 RelativeLayout 与 Android 中的属性合并

Merge custom RelativeLayout with attributes in Android

我正在使用 RelativeLayout 创建自定义视图。经过几天的尝试,我不知道该怎么做。

我需要时间轴之类的东西。线,圈子就是这样。我在一个地方创建了所有内容 XML 只是为了在一个地方看到所有内容并且它正在运行。

这就是我想要实现的:

并且正在工作 XML timeline_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/test1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true">

        <RelativeLayout
            android:id="@+id/draw1"
            android:layout_width="20dp"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/testText"
            android:layout_alignParentStart="true"
            android:layout_alignTop="@+id/testText"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp">

            <View
                android:id="@+id/lineUpDraw1"
                android:layout_width="1dp"
                android:layout_height="wrap_content"
                android:layout_above="@+id/circleDraw1"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:background="@color/primary"
                android:visibility="gone"/>

            <View
                android:id="@+id/circleDraw1"
                android:layout_width="10dp"
                android:layout_height="10dp"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:background="@drawable/circle"/>

            <View
                android:id="@+id/lineDownDraw1"
                android:layout_width="1dp"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_below="@+id/circleDraw1"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:background="@color/primary"/>
        </RelativeLayout>

        <TextView
            android:id="@+id/testText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginStart="4dp"
            android:layout_toEndOf="@+id/draw1"
            android:text="TEST1"
            android:textSize="16sp"/>

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/test2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/test1">

        <RelativeLayout
            android:id="@+id/draw2"
            android:layout_width="20dp"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/testText2"
            android:layout_alignParentStart="true"
            android:layout_alignTop="@+id/testText2"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp">

            <View
                android:id="@+id/lineUpDraw2"
                android:layout_width="1dp"
                android:layout_height="wrap_content"
                android:layout_above="@+id/circleDraw2"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:background="@color/primary"/>

            <View
                android:id="@+id/circleDraw2"
                android:layout_width="10dp"
                android:layout_height="10dp"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:background="@drawable/circle"/>

            <View
                android:id="@+id/lineDownDraw2"
                android:layout_width="1dp"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_below="@+id/circleDraw2"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:background="@color/primary"/>
        </RelativeLayout>

        <TextView
            android:id="@+id/testText2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginStart="4dp"
            android:layout_toEndOf="@+id/draw2"
            android:text="TEST2"
            android:textSize="16sp"/>

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/test3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/test2">

        <RelativeLayout
            android:id="@+id/draw3"
            android:layout_width="20dp"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/testText3"
            android:layout_alignParentStart="true"
            android:layout_alignTop="@+id/testText3"
            android:layout_marginEnd="8dp"
            android:layout_marginStart="8dp">

            <View
                android:id="@+id/lineUpDraw3"
                android:layout_width="1dp"
                android:layout_height="wrap_content"
                android:layout_above="@+id/circleDraw3"
                android:layout_alignParentTop="true"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:background="@color/primary"/>

            <View
                android:id="@+id/circleDraw3"
                android:layout_width="10dp"
                android:layout_height="10dp"
                android:layout_centerHorizontal="true"
                android:layout_centerVertical="true"
                android:background="@drawable/circle"/>

            <View
                android:id="@+id/lineDownDraw3"
                android:layout_width="1dp"
                android:layout_height="wrap_content"
                android:layout_alignParentBottom="true"
                android:layout_below="@+id/circleDraw3"
                android:layout_centerHorizontal="true"
                android:layout_gravity="center"
                android:background="@color/primary"
                android:visibility="gone"/>
        </RelativeLayout>

        <TextView
            android:id="@+id/testText3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginStart="4dp"
            android:layout_toEndOf="@+id/draw3"
            android:text="TEST3"
            android:textSize="16sp"/>
    </RelativeLayout>

</RelativeLayout>

可绘制circle.xml

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid android:color="@color/primary"/>
</shape>

效果不错,但我想获得通用性,并有可能重新使用此线-圆-线元素。这是我试过的

timeline_element.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="match_parent">

    <View
        android:id="@+id/lineUp"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_above="@+id/circle"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:background="@color/primary"/>

    <View
        android:id="@+id/circle"
        android:layout_width="10dp"
        android:layout_height="10dp"
        android:layout_centerHorizontal="true"
        android:layout_centerVertical="true"
        android:background="@drawable/circle"/>

    <View
        android:id="@+id/lineDown"
        android:layout_width="1dp"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:layout_below="@+id/circle"
        android:layout_centerHorizontal="true"
        android:layout_gravity="center"
        android:background="@color/primary"/>

</RelativeLayout >

TimelineElement.java

package com.example;

import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.RelativeLayout;

import com.example.R;

public class TimelineElement extends RelativeLayout{

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

    private void init(AttributeSet attrs) {
        View view = View.inflate(getContext(), R.layout.element_timeline, this);
        View lineUp = view.findViewById(R.id.lineUp);
        View circle = view.findViewById(R.id.circle);
        View lineDown = view.findViewById(R.id.lineDown);
        TypedArray a = getContext().getTheme().obtainStyledAttributes(
                attrs,
                R.styleable.TimelineElement,
                0, 0);

        try {
            int overallWidth = a.getDimensionPixelSize(R.styleable.TimelineElement_overallWidth, 0);
            setLayoutParams(new LayoutParams(overallWidth, ViewGroup.LayoutParams.WRAP_CONTENT));

            int shape = a.getResourceId(R.styleable.TimelineElement_circle, R.drawable.circle);
            int circleSize = a.getDimensionPixelSize(R.styleable.TimelineElement_circleSize, 0);
            circle.setLayoutParams(new LayoutParams(circleSize, circleSize));
            circle.setBackground(getContext().getResources().getDrawable(shape));

            int lineColor = a.getColor(R.styleable.TimelineElement_lineColor, R.color.primary);
            lineUp.setBackgroundColor(lineColor);
            lineDown.setBackgroundColor(lineColor);

            int type = a.getInt(R.styleable.TimelineElement_linesType, 0);
            if(type == 1)
                lineDown.setVisibility(View.GONE);
            if(type == 2)
                lineUp.setVisibility(View.GONE);

        } finally {
            a.recycle();
        }
    }
}

attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="TimelineElement">
        <attr name="lineColor" format="color" />
        <attr name="circle" format="reference" />
        <attr name="circleSize" format="dimension" />
        <attr name="overallWidth" format="dimension" />
        <attr name="linesType" format="enum">
            <enum name="both" value="0"/>
            <enum name="up" value="1"/>
            <enum name="down" value="2"/>
        </attr>
    </declare-styleable>
</resources>

timeline_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:timeline="http://schemas.android.com/apk/res-auto"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

    <RelativeLayout
        android:id="@+id/test1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true">

        <com.example.TimelineElement
            style="@style/TimelineElementStyle"
            android:id="@+id/draw1"
            android:layout_alignBottom="@+id/testText"
            android:layout_alignParentStart="true"
            android:layout_alignTop="@+id/testText"
            timeline:linesType="down"/>

        <TextView
            android:id="@+id/testText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginStart="4dp"
            android:layout_toEndOf="@+id/draw1"
            android:text="TEST1"
            android:textSize="16sp"/>

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/test2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/test1">

        <com.example.TimelineElement
            style="@style/TimelineElementStyle"
            android:id="@+id/draw2"
            android:layout_alignBottom="@+id/testText2"
            android:layout_alignParentStart="true"
            android:layout_alignTop="@+id/testText2"/>

        <TextView
            android:id="@+id/testText2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginStart="4dp"
            android:layout_toEndOf="@+id/draw2"
            android:text="TEST2"
            android:textSize="16sp"/>

    </RelativeLayout>

    <RelativeLayout
        android:id="@+id/test3"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/test2">

        <com.example.TimelineElement
            style="@style/TimelineElementStyle"
            android:id="@+id/draw3"
            android:layout_alignBottom="@+id/testText3"
            android:layout_alignParentStart="true"
            android:layout_alignTop="@+id/testText3"
            timeline:linesType="up"/>

        <TextView
            android:id="@+id/testText3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginEnd="4dp"
            android:layout_marginStart="4dp"
            android:layout_toEndOf="@+id/draw3"
            android:text="TEST3"
            android:textSize="16sp"/>
    </RelativeLayout>

</RelativeLayout>

styles.xml

<style name="TimelineElementStyle">
    <item name="android:layout_width">20dp</item>
    <item name="android:layout_height">wrap_content</item>
    <item name="android:layout_marginEnd">8dp</item>
    <item name="android:layout_marginStart">8dp</item>
    <item name="circle">@drawable/circle</item>
    <item name="circleSize">10dp</item>
    <item name="lineColor">@color/primary</item>
    <item name="linesType">both</item>
</style>

不幸的是结果并不如我所愿

我不知道哪里出了问题:(我也想在另一个上下文中使用它,这就是为什么我真的需要在没有 textview 的情况下用圆圈提取这一行(在另一个上下文中它可以是任何其他内容)。

希望你能帮帮我!谢谢

我的建议是因为在这里 circle.setLayoutParams(new LayoutParams(circleSize, circleSize)); 你为圆圈定义了新的布局参数,它失去了它的 layout_centerHorizontal 属性。

您可以 return 以编程方式恢复它: layoutparams.addRule(RelativeLayout.CENTER_HORIZONTAL);

编辑

另一种方式:

RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) circle.getLayoutParams();
params.height = ...;
params.width = ...;
circle.setLayoutParams(params);