Access attrs in AttributeSet for custom components

I have a custom component containing two text elements that have a customizable method for adjusting the size (two text representations are proportional to 1: 2). Since this is a subclass of RelativeLayout, it does not have the textSize attribute, but I wonder if it is still possible to set the android:textSize in the XML instance for this component, and then grab the textSize attribute from AttributeSet for use with my custom setSize() method in the constructor.

I saw a technique for this with custom attributes, but what if I want to grab an attribute already in the Android lexicon?

+20
java android xml android-textview relativelayout android-relativelayout
Nov 28 '11 at 20:59
source share
2 answers

Yes it is possible;

Suppose your RelativeLayout declaration (in xml) has textSize defined with 14sp:

 android:textSize="14sp" 

In the constructor of your custom view (the one that takes in the AttributeSet), you can get attributes from the Android namespace as such:

 String xmlProvidedSize = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "textSize"); 

The value of xmlProvidedSize will be something like this "14.0sp" and perhaps with a little editing of String you can just extract the numbers.




Another option for declaring your own attribute set will be small, but it is also possible.

So, you have your own custom view, and your TextViews declared something like this:

 public class MyCustomView extends RelativeLayout{ private TextView myTextView1; private TextView myTextView2; // rest of your class here 

big...

Now you also need to make sure that your custom view overrides the constructor, which takes an attribute set as follows:

 public MyCustomView(Context context, AttributeSet attrs){ super(context, attrs); init(attrs, context); //nice, clean method to instantiate your TextViews// } 

ok, let's see what the init () method is now:

 private void init(AttributeSet attrs, Context context){ // do your other View related stuff here // TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.MyCustomView); int xmlProvidedText1Size = a.int(R.styleable.MyCustomView_text1Size); int xmlProvidedText2Size = a.int(R.styleable.MyCustomView_text2Size); myTextView1.setTextSize(xmlProvidedText1Size); myTextView2.setTextSize(xmlProvidedText2Size); // and other stuff here // } 

You are probably wondering where R.styleable.MyCustomView, R.styleable.MyCustomView_text1Size and R.styleable.MyCustomView_text2Size come from; let me dwell on them in detail.

You must declare the attribute names in the attrs.xml file (in the values ​​directory) so that wherever you can use your custom view, the values ​​obtained from these attributes will be passed to your constructor.

So, let's see how you declare these user attributes as you requested: Here is my whole attrs.xml

 <?xml version="1.0" encoding="utf-8"?> <resources> <declare-styleable name="MyCustomView"> <attr name="text1Size" format="integer"/> <attr name="text2Size" format="integer"/> </declare-styleable> </resources> 

Now you can set the size of your TextViews in your XML, but NOT without declaring a namespace in your layout, here's how:

 <com.my.app.package.MyCustomView xmlns:josh="http://schemas.android.com/apk/res-auto" android:id="@+id/my_custom_view_id" android:layout_width="fill_parent" android:layout_height="wrap_content" josh:text1Size="15" josh:text2Size="30" /> 

Notice how I declared the “josh” namespace as the first line in your CustomView attribute set.

Hope this helps Josh

+70
Nov 28 2018-11-21T00:
source share

The accepted answer is a bit long. Here is a concise version that I hope will be easy to follow. To add the textSize attribute (or anything that uses dp / sp ) to your custom view, follow these steps:

1. Create your own attribute

Create (or add the following section) in attrs.xml. Pay attention to the dimension format.

 <resources> <declare-styleable name="CustomView"> <attr name="textSize" format="dimension" /> </declare-styleable> </resources> 

2. Set the attribute in the xml layout.

Pay attention to the user namespace app .

 <RelativeLayout 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"> <com.example.myproject.CustomView android:layout_width="wrap_content" android:layout_height="wrap_content" app:textSize="20sp" /> </RelativeLayout> 

3. Get the attribute value in your custom view

Note the use of getDimensionPixelSize . In your custom view, just work with pixels. See this answer if you need to convert to another dimension.

 public class CustomView extends View { private float mTextSize; // pixels public CustomView(Context context, AttributeSet attrs) { super(context, attrs); TypedArray a = context.getTheme().obtainStyledAttributes( attrs, R.styleable.CustomView, 0, 0); try { mTextSize = a.getDimensionPixelSize(R.styleable.CustomView_textSize, 0); } finally { a.recycle(); } } /** * @param size in SP units */ public void setTextSize(int size) { mTextSize = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, size, getResources().getDisplayMetrics()); mTextPaint.setTextSize(mTextSize); invalidate(); requestLayout(); } // ... } 

Notes

0
Feb 08 '17 at 9:46 on
source share



All Articles