How to use standard attribute android:text in my custom view?

22,038

Solution 1

use this:

public YourView(Context context, AttributeSet attrs) {
    super(context, attrs);
    int[] set = {
        android.R.attr.background, // idx 0
        android.R.attr.text        // idx 1
    };
    TypedArray a = context.obtainStyledAttributes(attrs, set);
    Drawable d = a.getDrawable(0);
    CharSequence t = a.getText(1);
    Log.d(TAG, "attrs " + d + " " + t);
    a.recycle();
}

i hope you got an idea

Solution 2

EDIT

Another way to do it (with specifying a declare-styleable but not having to declare a custom namespace) is as follows:

attrs.xml:

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

MyCustomView.java:

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyCustomView);
CharSequence t = a.getText(R.styleable.MyCustomView_android_text);
a.recycle();

This seems to be the generic Android way of extracting standard attributes from custom views.

Within the Android API, they use an internal R.styleable class to extract the standard attributes and don't seem to offer other alternatives of using R.styleable to extract standard attributes.

Original Post

To ensure that you get all the attributes from the standard component, you should use the following:

TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TextView);
CharSequence t = a.getText(R.styleable.TextView_text);
int color = a.getColor(R.styleable.TextView_textColor, context.getResources().getColor(android.R.color.darker_gray)); // or other default color
a.recycle();

If you want attributes from another standard component just create another TypedArray.

See http://developer.android.com/reference/android/R.styleable.html for details of available TypedArrays for standard components.

Share:
22,038
Seraphim's
Author by

Seraphim's

On Android and .NET, Azure

Updated on July 07, 2022

Comments

  • Seraphim's
    Seraphim's almost 2 years

    I wrote a custom view that extends RelativeLayout. My view has text, so I want to use the standard android:text without the need to specify a <declare-styleable> and without using a custom namespace xmlns:xxx every time I use my custom view.

    this is the xml where I use my custom view:

    <my.app.StatusBar
        android:id="@+id/statusBar"
        android:text="this is the title"/>
    

    How can I get the attribute value? I think I can get the android:text attribute with

    TypedArray a = context.obtainStyledAttributes(attrs,  ???);
    

    but what is ??? in this case (without a styleable in attr.xml)?

  • eluleci
    eluleci over 10 years
    i used same thing but it seems like not working for some attributes like 'textColor'. do you have any idea?
  • AlexKorovyansky
    AlexKorovyansky almost 10 years
    @pskink what's you thoughts about stackoverflow.com/questions/24650879/… ?
  • vir us
    vir us about 9 years
    One question. Since that reused attribute doesn't belong to a custom view (in this case android:text doesn't belong to RelativeLayout) it is not showing in 'suggestions' in IDE (Android Studio in my case) when declaring the custom view in XML. Is there a way to make android:text appear in suggestions as well so user knows this is also available attribute in the view?
  • Oleksandr Nos
    Oleksandr Nos over 8 years
    ':' is not a valid resource name character. damn it.
  • J. Beck
    J. Beck over 8 years
    @SashaNos. The ':' is used in XML but for the resource name in code use '_' in place of it. See the difference in the post. I'll delete the original post if it is confusing or unhelpful
  • Oleksandr Nos
    Oleksandr Nos over 8 years
    yes, I understand the difference. Android Studio just doesn't accept this name <attr name="android:text" /> because of colon :(
  • J. Beck
    J. Beck over 8 years
    It does. I am using android:orientation in one of my projects now. However, you may need to ensure that you are using the correct attribute name. The list of valid names is listed in the attribute reference.
  • Christopher Rucinski
    Christopher Rucinski over 8 years
    @J.Beck I get the same error as your do with the colon
  • J. Beck
    J. Beck over 8 years
    This is weird... Maybe it's a bug? What platform are you guys using? I use Windows 10 with the latest version of Android Studio.
  • sebkur
    sebkur about 7 years
    This does not work anymore, at least in my version of Android Studio (2.2). When trying to call getText(1) on the TypedArray with a plain int, the inspection complains: "Expected resource of type styleable". Using getText() with something like R.styleable.MyCustomView_android_text works however. I guess Android Studio became "smarter"
  • pskink
    pskink about 7 years
    @sebkur did you actually run the code? if so, what does getText() return?
  • sebkur
    sebkur about 7 years
    Ah, I see, it does compile even though Android Studio underlines it with a snaky red line. Mistook this for an actual compile error.
  • Goltsev Eugene
    Goltsev Eugene about 6 years
    This is great idea, but if I need to obtain both marginTop and marginBottom, for example - it would take only first-indexed value correctly, other will be 0.
  • Weekend
    Weekend almost 6 years
    I used <attr name="android:text" format="string" /> and it always went to compile error "android:text is already defined". Changing to <attr name="android:text" /> works, OMG.
  • Weekend
    Weekend almost 6 years
    Finally, I found the reason why I can't specify format="string". It's a limitation of old version gradle plugin. On classpath 'com.android.tools.build:gradle:2.3.3', it will end up with a compile error; On classpath 'com.android.tools.build:gradle:3.1.3', it compiles well.
  • Melllvar
    Melllvar about 5 years
    This should be the accepted answer. It requires minimal change to existing code and reads a lot cleaner.