레이아웃을 확장하여 사용자 지정보기를 만드시겠습니까?


107

여러 위치에서 사용하는 특정 레이아웃을 대체 할 사용자 지정보기를 만들려고하는데 그렇게하는 데 어려움을 겪고 있습니다.

기본적으로 이것을 바꾸고 싶습니다.

<RelativeLayout
 android:id="@+id/dolphinLine"
 android:layout_width="fill_parent"
 android:layout_height="wrap_content"
    android:layout_centerInParent="true"
 android:background="@drawable/background_box_light_blue"
 android:padding="10dip"
 android:layout_margin="10dip">
  <TextView
   android:id="@+id/dolphinTitle"
   android:layout_width="200dip"
   android:layout_height="100dip"
   android:layout_alignParentLeft="true"
   android:layout_marginLeft="10dip"
   android:text="@string/my_title"
   android:textSize="30dip"
   android:textStyle="bold"
   android:textColor="#2E4C71"
   android:gravity="center"/>
  <Button
   android:id="@+id/dolphinMinusButton"
   android:layout_width="100dip"
   android:layout_height="100dip"
   android:layout_toRightOf="@+id/dolphinTitle"
   android:layout_marginLeft="30dip"
   android:text="@string/minus_button"
   android:textSize="70dip"
   android:textStyle="bold"
   android:gravity="center"
   android:layout_marginTop="1dip"
   android:background="@drawable/button_blue_square_selector"
   android:textColor="#FFFFFF"
   android:onClick="onClick"/>
  <TextView
   android:id="@+id/dolphinValue"
   android:layout_width="100dip"
   android:layout_height="100dip"
   android:layout_marginLeft="15dip"
   android:background="@android:drawable/editbox_background"
   android:layout_toRightOf="@+id/dolphinMinusButton"
   android:text="0"
   android:textColor="#2E4C71"
   android:textSize="50dip"
   android:gravity="center"
   android:textStyle="bold"
   android:inputType="none"/>
  <Button
   android:id="@+id/dolphinPlusButton"
   android:layout_width="100dip"
   android:layout_height="100dip"
   android:layout_toRightOf="@+id/dolphinValue"
   android:layout_marginLeft="15dip"
   android:text="@string/plus_button"
   android:textSize="70dip"
   android:textStyle="bold"
   android:gravity="center"
   android:layout_marginTop="1dip"
   android:background="@drawable/button_blue_square_selector"
   android:textColor="#FFFFFF"
   android:onClick="onClick"/>
</RelativeLayout>

이로 인해:

<view class="com.example.MyQuantityBox"
    android:id="@+id/dolphinBox"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:myCustomAttribute="@string/my_title"/>

따라서 사용자 지정 레이아웃을 원하지 않고 사용자 지정보기를 원합니다 (이보기에 자식이있을 수 없음).

MyQuantityBox의 한 인스턴스에서 다른 인스턴스로 변경할 수있는 유일한 것은 제목입니다. (마지막 XML 줄에서와 같이) XML에서 이것을 지정할 수 있기를 매우 원합니다.

어떻게 할 수 있습니까? / res / layout의 XML 파일에 RelativeLayout을 넣고 MyBoxQuantity 클래스에서 부풀려 야합니까? 그렇다면 어떻게해야합니까?

감사!


Android의 "Compound Controls"및 다음 링크를 참조하십시오. stackoverflow.com/questions/1476371/…
greg7gkb

답변:


27

예, 할 수 있습니다. RelativeLayout, LinearLayout 등은보기이므로 사용자 지정 레이아웃은 사용자 지정보기입니다. 사용자 지정 레이아웃을 만들고 싶다면 할 수 있기 때문에 고려해야 할 사항입니다.

원하는 것은 복합 컨트롤을 만드는 것입니다. RelativeLayout의 하위 클래스를 만들고 코드 (TextView 등)에 모든 구성 요소를 추가하고 생성자에서 XML에서 전달 된 속성을 읽을 수 있습니다. 그런 다음 해당 속성을 제목 TextView에 전달할 수 있습니다.

http://developer.android.com/guide/topics/ui/custom-components.html


130

조금 오래되었지만 chubbsondubs의 대답에 따라 어떻게 할 것인지를 공유하려고 생각 했습니다. 단일 뷰를 포함하는 데 사용되기 때문에 FrameLayout( 문서 참조 ) 사용하고 xml의 뷰를 팽창시킵니다.

다음 코드 :

public class MyView extends FrameLayout {
    public MyView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        initView();
    }

    public MyView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initView();
    }

    public MyView(Context context) {
        super(context);
        initView();
    }

    private void initView() {
        inflate(getContext(), R.layout.my_view_layout, this);
    }
}

13
보기 클래스는 정적 부풀려을 가지고 있기 때문에 () 메소드는 LayoutInflater.from ()에 대한 필요가 없습니다
외곽

1
이것은 단지 여기에있는 Johannes의 해결책이 아닙니까 : stackoverflow.com/questions/17836695/… 그래도 이것은 내부의 다른 레이아웃을 부풀립니다. 그래서 그것은 내가 생각하는 최선의 해결책이 아닙니다.
Tobias Reich

3
하지만 Johannes 솔루션은 7.24.13에서, 마음은 7.1.13에서 ... 또한 내 솔루션은 하나의 뷰만 포함해야하는 FrameLayout을 사용합니다 (솔루션에서 참조 된 문서에 기록됨). 따라서 실제로 뷰의 자리 표시 자로 사용됩니다. 부풀려진 뷰에 자리 표시자를 사용하지 않는 솔루션을 모릅니다.
Fox

이해가 안 돼요. 이 메서드 (팽창)는 무시되는 뷰를 반환합니다. 현재보기에 추가해야하는 것 같습니다.
Jeffrey Blattman

1
@Jeffrey Blattman은 View.inflate 메소드 를 확인하세요. 이 메소드를 사용합니다 (루트를 this, 세 번째 매개 변수 로 지정 )
V1raNi

36

다음은 xml에서 확장하여 customview (compoundview)를 만드는 간단한 데모입니다.

attrs.xml

<resources>

    <declare-styleable name="CustomView">
        <attr format="string" name="text"/>
        <attr format="reference" name="image"/>
    </declare-styleable>
</resources>

CustomView.kt

class CustomView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) :
        ConstraintLayout(context, attrs, defStyleAttr) {

    init {
        init(attrs)
    }

    private fun init(attrs: AttributeSet?) {
        View.inflate(context, R.layout.custom_layout, this)

        val ta = context.obtainStyledAttributes(attrs, R.styleable.CustomView)
        try {
            val text = ta.getString(R.styleable.CustomView_text)
            val drawableId = ta.getResourceId(R.styleable.CustomView_image, 0)
            if (drawableId != 0) {
                val drawable = AppCompatResources.getDrawable(context, drawableId)
                image_thumb.setImageDrawable(drawable)
            }
            text_title.text = text
        } finally {
            ta.recycle()
        }
    }
}

custom_layout.xml

우리는 해야 사용 merge대신에 여기에 ConstraintLayout있기 때문에

ConstraintLayout여기서 사용 하면 레이아웃 계층 구조는 ConstraintLayout-> ConstraintLayout-> ImageView+ TextView=> 1 개 중복 ConstraintLayout=> 성능에 좋지 않습니다.

<?xml version="1.0" encoding="utf-8"?>
<merge 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"
    tools:parentTag="android.support.constraint.ConstraintLayout">

    <ImageView
        android:id="@+id/image_thumb"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        tools:ignore="ContentDescription"
        tools:src="@mipmap/ic_launcher" />

    <TextView
        android:id="@+id/text_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintEnd_toEndOf="@id/image_thumb"
        app:layout_constraintStart_toStartOf="@id/image_thumb"
        app:layout_constraintTop_toBottomOf="@id/image_thumb"
        tools:text="Text" />

</merge>

activity_main.xml 사용

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

    <your_package.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#f00"
        app:image="@drawable/ic_android"
        app:text="Android" />

    <your_package.CustomView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#0f0"
        app:image="@drawable/ic_adb"
        app:text="ADB" />

</LinearLayout>

결과

여기에 이미지 설명 입력

Github 데모


4
이것은 불필요한 레이아웃 계층 구조를 언급하기 때문에이 스레드에서 허용되거나 가장 많이 투표 된 답변이어야합니다.
Farid 2011

15

아래에 표시된대로 LayoutInflater를 사용하십시오.

    public View myView() {
        View v; // Creating an instance for View Object
        LayoutInflater inflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
        v = inflater.inflate(R.layout.myview, null);

        TextView text1 = v.findViewById(R.id.dolphinTitle);
        Button btn1 = v.findViewById(R.id.dolphinMinusButton);
        TextView text2 = v.findViewById(R.id.dolphinValue);
        Button btn2 = v.findViewById(R.id.dolphinPlusButton);

        return v;
    }

나는 똑같이 시도했다. 잘 작동합니다. 하지만 btn1을 클릭하면 웹 서비스를 호출하고 서버에서 응답을받은 후 특정 위치에있는 일부 텍스트를 업데이트하고 싶습니다. text2 .. 어떤 도움말 pls?
harikrishnan

7

실제로는 특히 약간의 xml을 반복적으로 사용하는 경우 약간 조심해야한다는 것을 알았습니다. 예를 들어 목록의 각 항목에 대해 테이블 ​​행을 만들려는 테이블이 있다고 가정합니다. 일부 xml을 설정했습니다.

에서 my_table_row.xml:

<?xml version="1.0" encoding="utf-8"?>
<TableRow xmlns:android="http://schemas.android.com/apk/res/android" 
  android:orientation="vertical"
  android:layout_width="match_parent"
  android:layout_height="match_parent" android:id="@+id/myTableRow">
    <ImageButton android:src="@android:drawable/ic_menu_delete" android:layout_width="wrap_content" android:layout_height="wrap_content" android:id="@+id/rowButton"/>
    <TextView android:layout_height="wrap_content" android:layout_width="wrap_content" android:textAppearance="?android:attr/textAppearanceMedium" android:text="TextView" android:id="@+id/rowText"></TextView>
</TableRow>

그런 다음 일부 코드를 사용하여 행당 한 번 생성하려고합니다. 행을 첨부 할 상위 TableLayout myTable을 정의했다고 가정합니다.

for (int i=0; i<numRows; i++) {
    /*
     * 1. Make the row and attach it to myTable. For some reason this doesn't seem
     * to return the TableRow as you might expect from the xml, so you need to
     * receive the View it returns and then find the TableRow and other items, as
     * per step 2.
     */
    LayoutInflater inflater = (LayoutInflater)getBaseContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    View v =  inflater.inflate(R.layout.my_table_row, myTable, true);

    // 2. Get all the things that we need to refer to to alter in any way.
    TableRow    tr        = (TableRow)    v.findViewById(R.id.profileTableRow);
    ImageButton rowButton = (ImageButton) v.findViewById(R.id.rowButton);
    TextView    rowText   = (TextView)    v.findViewById(R.id.rowText);

    // 3. Configure them out as you need to
    rowText.setText("Text for this row");
    rowButton.setId(i); // So that when it is clicked we know which one has been clicked!
    rowButton.setOnClickListener(this); // See note below ...           

    /*
     * To ensure that when finding views by id on the next time round this
     * loop (or later) gie lots of spurious, unique, ids.
     */
    rowText.setId(1000+i);
    tr.setId(3000+i);
}

rowButton.setOnClickListener (this) 처리에 대한 명확하고 간단한 예제 는 프로그래밍 방식으로 생성 된 버튼에 대한 Onclicklistener를 참조 하세요 .


안녕하세요 Neil, 나도 똑같이 시도했습니다. 잘 작동합니다. 하지만 rowButton을 클릭하면 웹 서비스를 호출하고 서버에서 응답을받은 후 특정 위치에서 일부 텍스트를 업데이트하고 싶습니다. rowText..any help pls?
harikrishnan

내 질문도 참조하십시오. stackoverflow.com/questions/48719970/…
harikrishnan
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.