programing

XML을 사용하여 사용자 정의 Android UI 요소 선언

itmemos 2023. 7. 6. 21:51
반응형

XML을 사용하여 사용자 정의 Android UI 요소 선언

XML을 사용하여 Android UI 요소를 선언하려면 어떻게 해야 합니까?

Android Developer Guide에는 Building Custom Components 섹션이 있습니다.안타깝게도 XML 특성에 대한 논의는 레이아웃 파일 내에서 제어를 선언하고 클래스 초기화 내부의 값을 실제로 처리하지 않는 것만 다룹니다.단계는 다음과 같습니다.

에서 특성 선언values\attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyCustomView">
        <attr name="android:text"/>
        <attr name="android:textColor"/>            
        <attr name="extraInformation" format="string" />
    </declare-styleable>
</resources>

서정화되지않사용다니합름이을은에규에서 하는 것에 하세요.declare-styleable태그. 다음과 같은 비표준 안드로이드 속성extraInformation그들의 유형을 신고해야 합니다.수퍼 클래스에서 선언된 태그는 다시 선언할 필요 없이 하위 클래스에서 사용할 수 있습니다.

생성자 작성

다음을 사용하는 두 개의 생성자가 있기 때문입니다.AttributeSet초기화의 경우, 생성자가 호출할 수 있는 별도의 초기화 방법을 만드는 것이 편리합니다.

private void init(AttributeSet attrs) { 
    TypedArray a=getContext().obtainStyledAttributes(
         attrs,
         R.styleable.MyCustomView);

    //Use a
    Log.i("test",a.getString(
         R.styleable.MyCustomView_android_text));
    Log.i("test",""+a.getColor(
         R.styleable.MyCustomView_android_textColor, Color.BLACK));
    Log.i("test",a.getString(
         R.styleable.MyCustomView_extraInformation));

    //Don't forget this
    a.recycle();
}

R.styleable.MyCustomView 생성된 자생됨입니다.int[]리소스. 여기서 각 요소는 속성의 ID입니다.XML의 각 속성에 대한 속성은 요소 이름에 속성 이름을 추가하여 생성됩니다.를 들면, 들면를예,R.styleable.MyCustomView_android_text에는 를포니다가 되어 있습니다.android_text 성속한의 .MyCustomView 러면다서속검수있다니습에서 할 수 .TypedArray다양한 양한사법을 get된 에 되어 있지 XML에 정의되어 있지 않습니다.null반환니다됩. 이 경우 두 번째 물론 반환 형식이 원시인 경우를 제외하고, 이 경우 두 번째 인수가 반환됩니다.

모든 특성을 검색하지 않으려는 경우 이 배열을 수동으로 만들 수 있습니다.는 표 Android 의는 ID 에포어있습에 포함되어 .android.R.attr은 이프젝속있동안에 .R.attr.

int attrsWanted[]=new int[]{android.R.attr.text, R.attr.textColor};

에 아무 것도 사용해서는 안 됩니다.android.R.styleable 스레드에 따라 미래에 변경될 수 있습니다.이 모든 상수를 한 곳에서 보는 것이 유용하기 때문에 설명서에는 여전히 나와 있습니다.

다음과 같은 레이아웃 파일에서 사용layout\main.xml

선언 포함xmlns:app="http://schemas.android.com/apk/res-auto"최상위 수준 xml 요소입니다.네임스페이스는 서로 다른 스키마가 동일한 요소 이름을 사용할 때 발생하는 충돌을 방지하는 방법을 제공합니다(자세한 내용은 이 문서 참조).URL은 스키마를 고유하게 식별하는 방법일 뿐 실제로는 해당 URL에서 호스팅할 필요가 없습니다.이 작업이 아무 작업도 수행하지 않는 것 같으면 충돌을 해결할 필요가 없는 한 네임스페이스 접두사를 추가할 필요가 없기 때문입니다.

<com.mycompany.projectname.MyCustomView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="@android:color/transparent"
    android:text="Test text"
    android:textColor="#FFFFFF"
    app:extraInformation="My extra information"
/> 

정규화된 이름을 사용하여 사용자 정의 보기를 참조합니다.

Android Label 보기 샘플

전체 예를 보려면 Android 레이블 보기 샘플을 보십시오.

LabelView.java

 TypedArray a=context.obtainStyledAttributes(attrs, R.styleable.LabelView);
 CharSequences=a.getString(R.styleable.LabelView_text);

attrs.xml

<declare-styleable name="LabelView">
    <attr name="text"format="string"/>
    <attr name="textColor"format="color"/>
    <attr name="textSize"format="dimension"/>
</declare-styleable>

custom_view_1.xml

<com.example.android.apis.view.LabelView
    android:background="@drawable/blue"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    app:text="Blue" app:textSize="20dp"/>

이 내용은 다음에 포함되어 있습니다.LinearLayout특성이 과 같은 :xmlns:app="http://schemas.android.com/apk/res-auto"

링크

좋은 참고 자료입니다.감사합니다!추가 기능:

사용자 정의 뷰에 대한 사용자 지정 특성을 선언한 라이브러리 프로젝트가 포함된 경우에는 라이브러리가 아닌 프로젝트 네임스페이스를 선언해야 합니다.예:

라이브러리에 "com.example.library.customview" 패키지가 있고 작업 프로젝트에 "com.example.customview" 패키지가 있다고 가정하면 다음과 같습니다.

작동하지 않음(오류 표시 ": 'com.example.library.customview' 패키지에서 'newAttr' 특성에 대한 리소스 식별자를 찾을 수 없음):

<com.library.CustomView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.example.library.customview"
        android:id="@+id/myView"
        app:newAttr="value" />

작동 예정:

<com.library.CustomView
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res/com.example.customview"
        android:id="@+id/myView"
        app:newAttr="value" />

가장 많이 투표된 답변에 추가합니다.

스타일 특성 가져오기()

안드로이드:xxx 미리 정의된 속성을 사용하여 사용자 정의 보기를 만들 때 styledAttributes() 사용에 대한 몇 가지 단어를 추가하고 싶습니다.특히 텍스트 어피아란스를 사용할 때는 더욱 그렇습니다.
2"에 처럼, "2.2"에서 한 것처럼.생성자를 만드는 중", 사용자 지정 보기는 생성 시 AttributeSet을 가져옵니다.TextView 소스 코드(API 16)에서 볼 수 있는 주요 용도입니다.

final Resources.Theme theme = context.getTheme();

// TextAppearance is inspected first, but let observe it later

TypedArray a = theme.obtainStyledAttributes(
            attrs, com.android.internal.R.styleable.TextView, defStyle, 0);

int n = a.getIndexCount();
for (int i = 0; i < n; i++) 
{
    int attr = a.getIndex(i);
    // huge switch with pattern value=a.getXXX(attr) <=> a.getXXX(a.getIndex(i))
}
a.recycle();

여기 뭐가 있죠?
obtainStyledAttributes(AttributeSet set, int[] attrs, int defStyleAttr, int defStyleRes)
속성 세트는 설명서에 따라 테마별로 처리됩니다.속성 값은 단계별로 컴파일됩니다.처음에는 테마에서 속성이 채워지고, 다음에는 스타일의 값으로 값이 대체되며, 마지막으로 특수 뷰 인스턴스(instance)에 대한 XML의 정확한 값이 다른 값으로 대체됩니다.
속성 - 요된특배열성 -com.android.internal.R.styleable.TextView
이것은 일반적인 상수 배열입니다.표준 특성을 요청하는 경우 이 어레이를 수동으로 구축할 수 있습니다.

설명서에 언급되지 않은 내용 - 결과 순서 TypedArray 요소.
사용자 정의 뷰가 attrs.xml로 선언되면 속성 인덱스에 대한 특수 상수가 생성됩니다.다음과 같은 방법으로 가치를 추출할 수 있습니다.a.getString(R.styleable.MyCustomView_android_text) 수동의 int[]상수가 없습니다.정상적으로 getXXXValue(arrayIndex)는 다음과 .

또 다른 질문은 "내부 상수를 대체하고 표준 속성을 요청할 수 있는 방법"입니다.우리는 안드로이드를 사용할 수 있습니다.R.attr.* 값입니다.

따라서 사용자 정의 보기에서 표준 TextApearance 특성을 사용하고 생성자에서 해당 값을 읽으려면 TextView에서 다음과 같은 방법으로 코드를 수정할 수 있습니다.

ColorStateList textColorApp = null;
int textSize = 15;
int typefaceIndex = -1;
int styleIndex = -1;

Resources.Theme theme = context.getTheme();

TypedArray a = theme.obtainStyledAttributes(attrs, R.styleable.CustomLabel, defStyle, 0);
TypedArray appearance = null;
int apResourceId = a.getResourceId(R.styleable.CustomLabel_android_textAppearance, -1);
a.recycle();
if (apResourceId != -1)
{
    appearance = 
        theme.obtainStyledAttributes(apResourceId, new int[] { android.R.attr.textColor, android.R.attr.textSize, 
            android.R.attr.typeface, android.R.attr.textStyle });
}
if (appearance != null)
{
    textColorApp = appearance.getColorStateList(0);
    textSize = appearance.getDimensionPixelSize(1, textSize);
    typefaceIndex = appearance.getInt(2, -1);
    styleIndex = appearance.getInt(3, -1);

    appearance.recycle();
}

사용자 지정 레이블이 정의된 위치:

<declare-styleable name="CustomLabel">
    <!-- Label text. -->
    <attr name="android:text" />
    <!-- Label text color. -->
    <attr name="android:textColor" />
    <!-- Combined text appearance properties. -->
    <attr name="android:textAppearance" />
</declare-styleable>

어쩌면 제가 착각하고 있을지도 모르지만, getStyledAttributes()에 대한 Android 문서는 매우 빈약합니다.

표준 UI 구성 요소 확장

동시에 선언된 모든 속성을 사용하여 표준 UI 구성 요소를 확장할 수 있습니다.예를 들어 TextView는 많은 속성을 선언하기 때문에 이 접근 방식은 그다지 좋지 않습니다.또한 Measure() 및 Draw()에서 오버라이드된 모든 기능을 구현하는 것은 불가능합니다.

그러나 사용자 지정 구성요소의 이론적인 광범위한 재사용을 희생할 수 있습니다."사용할 기능을 정확히 알고 있습니다."라고 말하고 다른 사람과 코드를 공유하지 마십시오.

컨스트럭터 그런다생를구수있현다습니할자성음▁constructor다▁implement▁then를 구현할 수 있습니다.CustomComponent(Context, AttributeSet, defStyle)에 전화한 에.super(...)모든 속성을 구문 분석하여 getter 메서드를 통해 사용할 수 있습니다.

구글은 개발자 페이지를 업데이트하고 거기에 다양한 교육을 추가한 것으로 보입니다.

그 중 하나는 사용자 정의 뷰 생성에 관한 것으로 여기에서 확인할 수 있습니다.

첫 번째 답변 정말 감사합니다.

저는 단지 한 가지 문제가 있었습니다.뷰를 부풀릴 때 java.lang이라는 버그가 있었습니다.NoSuch 메서드 예외 : MyView(컨텍스트, 속성)

새 생성자를 생성하여 해결했습니다.

public MyView(Context context, AttributeSet attrs) {
     super(context, attrs);
     // some code
}

이것이 도움이 되기를 바랍니다!

다른 레이아웃 파일에 다음과 같이 레이아웃 파일을 포함할 수 있습니다.

             <RelativeLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginLeft="10dp"
                android:layout_marginRight="30dp" >

                <include
                    android:id="@+id/frnd_img_file"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    layout="@layout/include_imagefile"/>

                <include
                    android:id="@+id/frnd_video_file"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    layout="@layout/include_video_lay" />

                <ImageView
                    android:id="@+id/downloadbtn"
                    android:layout_width="30dp"
                    android:layout_height="30dp"
                    android:layout_centerInParent="true"
                    android:src="@drawable/plus"/>
            </RelativeLayout>

여기서 include 태그의 레이아웃 파일은 동일한 res 폴더에 있는 다른 .xml 레이아웃 파일입니다.

언급URL : https://stackoverflow.com/questions/2695646/declaring-a-custom-android-ui-element-using-xml

반응형