programing

사용자 지정 특성 정의

javajsp 2023. 6. 3. 08:14

사용자 지정 특성 정의

다음과 같이 나만의 특성을 구현해야 합니다.com.android.R.attr

공식 문서에서 찾을 수 있는 내용이 없으므로 이러한 특성을 정의하는 방법과 내 코드에서 사용하는 방법에 대한 정보가 필요합니다.

현재 최상의 문서는 원본입니다.여기(attrs.xml)에서 확인할 수 있습니다.

의 위속정수을있에 속성을 할 수 .<resources>의 요소 <declare-styleable>例의원 을 둘 할 경우 .둘 이상의 위치에서 특성을 사용할 경우 루트 요소에 특성을 넣습니다.모든 특성은 동일한 글로벌 네임스페이스를 공유합니다.즉, 시스템 내부에 새 속성을 생성하더라도<declare-styleable>요소 외부에서 사용할 수 있으며 다른 유형의 동일한 이름을 가진 다른 특성을 만들 수 없습니다.

안 안<attr>에는 두 특성이 .name그리고.format.name당신이 그것을 무엇이라고 부를 수 있게 하고 이것이 당신이 코드에서 그것을 언급하게 되는 방법입니다. 예를 들어,R.attr.my_attribute.format속성은 원하는 속성의 '유형'에 따라 다른 값을 가질 수 있습니다.

  • reference - 다른 리소스 ID를 참조하는 경우(예: "@color/my_color", "@color/my_color"
  • 색.
  • 부울의
  • 치수
  • 흘러가다
  • 정수의
  • 분수
  • enum - 일반적으로 암묵적으로 정의됩니다.
  • flag - 일반적으로 암묵적으로 정의됨

▁using를 사용하여 형식을 여러 할 수 .|를 들어, , , .format="reference|color".

enum속성은 다음과 같이 정의할 수 있습니다.

<attr name="my_enum_attr">
  <enum name="value1" value="1" />
  <enum name="value2" value="2" />
</attr>

flag속성은 함께 비트링할 수 있도록 값을 정의해야 한다는 점을 제외하고는 유사합니다.

<attr name="my_flag_attr">
  <flag name="fuzzy" value="0x01" />
  <flag name="cold" value="0x02" />
</attr>

에도 속성외다있습다니음이에가 .<declare-styleable>사용할 수 할 수 .사용자 정의 보기에서 사용할 수 있는 특성을 정의할 수 있습니다.다음을 지정하여 이 작업을 수행합니다.<attr>에는 요소, 이정전경다우음지않을습다니지정하의를 .format들어와 같은 을 재사용하려면 :gravity, Android 및 Android에서 재사용할 수 있습니다.name아래와 같이

정의 보기 용사 예의<declare-styleable>:

<declare-styleable name="MyCustomView">
  <attr name="my_custom_attribute" />
  <attr name="android:gravity" />
</declare-styleable>

사용자 정의 보기에서 XML로 사용자 정의 특성을 정의할 때 몇 가지 작업을 수행해야 합니다.먼저 속성을 찾으려면 네임스페이스를 선언해야 합니다.루트 레이아웃 요소에서 이 작업을 수행합니다.일반적으로 다음 항목만 있습니다.xmlns:android="http://schemas.android.com/apk/res/android" 이추가야합다도 .xmlns:whatever="http://schemas.android.com/apk/res-auto".

예:

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

    <org.example.mypackage.MyCustomView
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:gravity="center"
      whatever:my_custom_attribute="Hello, world!" />
</LinearLayout>

마지막으로 사용자 정의 특성에 액세스하려면 일반적으로 사용자 정의 보기의 생성자에서 다음과 같이 액세스합니다.

public MyCustomView(Context context, AttributeSet attrs, int defStyle) {
  super(context, attrs, defStyle);

  TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView, defStyle, 0);

  String str = a.getString(R.styleable.MyCustomView_my_custom_attribute);

  //do something with str

  a.recycle();
}

끝.:)

Qberticus의 대답은 좋지만, 한 가지 유용한 세부 사항이 누락되었습니다.라이브러리에서 이러한 기능을 구현하는 경우 다음을 대체합니다.

xmlns:whatever="http://schemas.android.com/apk/res/org.example.mypackage"

포함:

xmlns:whatever="http://schemas.android.com/apk/res-auto"

그렇지 않으면 라이브러리를 사용하는 응용프로그램에 런타임 오류가 발생합니다.

위의 답변은 몇 가지를 제외하고 모든 것을 매우 상세하게 다룹니다.

만약에 스타일이 , 그 에 먼저, 스일이없, 에다음면, 다그타약.(Context context, AttributeSet attrs)메서드 서명은 기본 설정을 인스턴스화하는 데 사용됩니다.이 경우에는 다음을 사용합니다.context.obtainStyledAttributes(attrs, R.styleable.MyCustomView)TypedArray 가 옵져 다니를.

둘째로, 그것은 플라우랄 자원(수량 문자열)을 다루는 방법을 다루지 않습니다.TypedArray를 사용하여 처리할 수 없습니다.다음은 기본 설정 값에 따라 값 형식을 지정하는 기본 설정 요약을 설정하는 내 SeekBarPreference의 코드 조각입니다.기본 설정에 대한 xml이 Android:summary를 텍스트 문자열 또는 문자열 리소스로 설정하면 기본 설정 값이 문자열 형식으로 지정됩니다(값을 선택하려면 %d이(가) 포함되어야 함).rodroid:summary가 plaurals 리소스로 설정되어 있으면 결과 형식을 지정하는 데 사용됩니다.

// Use your own name space if not using an android resource.
final static private String ANDROID_NS = 
    "http://schemas.android.com/apk/res/android";
private int pluralResource;
private Resources resources;
private String summary;

public SeekBarPreference(Context context, AttributeSet attrs) {
    // ...
    TypedArray attributes = context.obtainStyledAttributes(
        attrs, R.styleable.SeekBarPreference);
    pluralResource =  attrs.getAttributeResourceValue(ANDROID_NS, "summary", 0);
    if (pluralResource !=  0) {
        if (! resources.getResourceTypeName(pluralResource).equals("plurals")) {
            pluralResource = 0;
        }
    }
    if (pluralResource ==  0) {
        summary = attributes.getString(
            R.styleable.SeekBarPreference_android_summary);
    }
    attributes.recycle();
}

@Override
public CharSequence getSummary() {
    int value = getPersistedInt(defaultValue);
    if (pluralResource != 0) {
        return resources.getQuantityString(pluralResource, value, value);
    }
    return (summary == null) ? null : String.format(summary, value);
}

  • 이는 예로 제시된 것일 뿐이지만, 기본 설정 화면에서 요약을 설정하려면 다음을 호출해야 합니다.notifyChanged()에.onDialogClosed방법.

전통적인 접근 방식은 상용 코드와 서투른 리소스 처리로 가득합니다.그래서 제가 스파이글래스 프레임워크를 만든 겁니다.작동 방식을 설명하기 위해 다음은 문자열 제목을 표시하는 사용자 정의 보기를 만드는 방법을 참조하십시오.

1단계: 사용자 정의 보기 클래스를 만듭니다.

public class CustomView extends FrameLayout {
    private TextView titleView;

    public CustomView(Context context) {
        super(context);
        init(null, 0, 0);
    }

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

    public CustomView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init(attrs, defStyleAttr, 0);
    }

    @RequiresApi(21)
    public CustomView(
            Context context, 
            AttributeSet attrs,
            int defStyleAttr,
            int defStyleRes) {

        super(context, attrs, defStyleAttr, defStyleRes);
        init(attrs, defStyleAttr, defStyleRes);
    }

    public void setTitle(String title) {
        titleView.setText(title);
    }

    private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        inflate(getContext(), R.layout.custom_view, this);

        titleView = findViewById(R.id.title_view);
    }
}

2단계: " " " "에서합니다.values/attrs.xml리소스 파일:

<resources>
    <declare-styleable name="CustomView">
        <attr name="title" format="string"/>
    </declare-styleable>
</resources>

3단계를 합니다.@StringHandler에대주석의 .setTitle보기가 부풀려질 때 속성 값을 이 메서드로 라우팅하도록 Spyglass 프레임워크에 지시하는 메서드입니다.

@HandlesString(attributeId = R.styleable.CustomView_title)
public void setTitle(String title) {
    titleView.setText(title);
}

시 이를 으로 Spyglass 주석을 합니다.CustomView_SpyglassCompanion학생들

의 4단계: 생성된 클래스를 합니다.init방법:

private void init(AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    inflate(getContext(), R.layout.custom_view, this);

    titleView = findViewById(R.id.title_view);

    CustomView_SpyglassCompanion
            .builder()
            .withTarget(this)
            .withContext(getContext())
            .withAttributeSet(attrs)
            .withDefaultStyleAttribute(defStyleAttr)
            .withDefaultStyleResource(defStyleRes)
            .build()
            .callTargetMethodsNow();
}

바로 그겁니다.이제 XML에서 클래스를 인스턴스화하면 Spyglass 동반자가 속성을 해석하고 필요한 메서드를 호출합니다.예를 들어, 다음 레이아웃을 부풀린 경우setTitle로호됩다니와 함께 됩니다."Hello, World!"의론대로

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:width="match_parent"
    android:height="match_parent">

    <com.example.CustomView
        android:width="match_parent"
        android:height="match_parent"
        app:title="Hello, World!"/>
</FrameLayout>

프레임워크는 문자열 리소스에 제한되지 않으며 다른 리소스 유형을 처리하기 위한 다양한 주석을 가지고 있습니다.또한 메소드에 여러 매개변수가 있는 경우 기본값을 정의하고 자리 표시자 값을 전달하기 위한 주석이 있습니다.

자세한 정보와 예제는 Github repo를 참조하십시오.

formatattr요소를 사용하여 XML 레이아웃의 클래스를 참조할 수 있습니다.

  • attrs.xml의 예입니다.
  • Android Studio는 클래스가 XML에서 참조되고 있음을 이해합니다.
    • 예.
      • Refactor > Rename작동하다
      • Find Usages작동하다
      • 등등...

format.../src/main/res/values/attrs.xml의 속성

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <declare-styleable name="MyCustomView">
        ....
        <attr name="give_me_a_class"/>
        ....
    </declare-styleable>

</resources>

일부 레이아웃 파일에 사용... /src/main/res/sys/activity__main_main.xml

<?xml version="1.0" encoding="utf-8"?>
<SomeLayout
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <!-- make sure to use $ dollar signs for nested classes -->
    <MyCustomView
        app:give_me_a_class="class.type.name.Outer$Nested/>

    <MyCustomView
        app:give_me_a_class="class.type.name.AnotherClass/>

</SomeLayout>

보기 초기화 코드의 클래스를 구문 분석합니다... /src/main/main/syslog/.../MyCustomView.kt

class MyCustomView(
        context:Context,
        attrs:AttributeSet)
    :View(context,attrs)
{
    // parse XML attributes
    ....
    private val giveMeAClass:SomeCustomInterface
    init
    {
        context.theme.obtainStyledAttributes(attrs,R.styleable.ColorPreference,0,0).apply()
        {
            try
            {
                // very important to use the class loader from the passed-in context
                giveMeAClass = context::class.java.classLoader!!
                        .loadClass(getString(R.styleable.MyCustomView_give_me_a_class))
                        .newInstance() // instantiate using 0-args constructor
                        .let {it as SomeCustomInterface}
            }
            finally
            {
                recycle()
            }
        }
    }
  • 다음은 사용자 지정 특성 및 보기 생성에 대한 공식 문서입니다.

언급URL : https://stackoverflow.com/questions/3441396/defining-custom-attrs