Home » Android » android – How to obtain the value for a reference attribute

android – How to obtain the value for a reference attribute

Posted by: admin June 16, 2020 Leave a comment

Questions:

I want to implement a SeekBar that automatically updates a TextView, for the actual value, the maximum value and a minimum value. I derive from SeekBar and define 3 named attributes with the format being reference.

In the constructor, I get a TypedArray by calling obtainStyledAttributes(). TypedArray contains a lot of getters for every kind of attribute types. What I am missing is some kind of Object getReference() or int getReferenceId().

How do I obtain the value for a reference attribute?

Edit:

I have an attribute definition for a class MinMaxSlider, that looks like this:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MinMaxSlider">
        <attr name="min" format="integer" />
        <attr name="valueView" format="reference" />
    </declare-styleable>
</resources>

a snipped out of the layout definition looks like this:

    <LinearLayout
        style="@style/ParameterLabelLayout"
        android:orientation="horizontal">
        <TextView
            style="@style/ParameterSliderLabel"
            android:text="min. Interval" />
        <TextView
            android:id="@+id/min_connection_interval_slider_value"
            style="@style/ParameterSliderValue"/>
    </LinearLayout>

    <com.roche.rcpclient.MinMaxSlider
        style="@style/ParameterSlider"
        android:id="@+id/min_connection_interval_slider"
        android:max="3200"
        custom:valueView="@id/min_connection_interval_slider_value"
        custom:min="1"/>

Here, the MinMaxSlider should reference one of the TextViews above to display its current value there.

From within the constructor of MinMaxSlider, I can lookup the min attributes value.

If I try to lookup the valueView attribute as an integer, I always get the default value (0), not R.id.min_connection_interval_slider as I would expect.

Edit: the right function to lookup a reference seems to be getResourceId. The obtained integer id can be used to use findViewById later, when the overall object hierarchy is constructed.

In my case, I register an OnSeekBarChangeListener() and lookup the View in the callback, when the callback is fired.

How to&Answers:

You can’t receive reference via findViewById in constructor. Because it is not attached to layout yet.
Reference: https://developer.android.com/training/custom-views/create-view.html#applyattr

When a view is created from an XML layout, all of the attributes in
the XML tag are read from the resource bundle and passed into the
view’s constructor as an AttributeSet. Although it’s possible to read
values from the AttributeSet directly, doing so has some
disadvantages:

Resource references within attribute values are not resolved Styles
are not applied Instead, pass the AttributeSet to
obtainStyledAttributes(). This method passes back a TypedArray array
of values that have already been dereferenced and styled.

You can receive in another methods.
For example:

attrs.xml

 <declare-styleable name="CustomTextView">
    <attr name="viewPart" format="reference"></attr>
 </declare-styleable>

yourLayout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:baselineAligned="false"
    android:gravity="center_vertical"
    android:orientation="horizontal">

  <tr.com.ui.utils.CustomTextView
                        android:id="@+id/chat_msg"                           
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_gravity="right|bottom"
                        android:focusableInTouchMode="false"
                        android:gravity="left"                          
                        android:text="test"
                        app:viewPart="@id/date_view" />



                    <TextView
                        android:id="@+id/date_view"                         
                        android:layout_alignParentBottom="true"
                        android:layout_alignParentRight="true"                          
                        android:gravity="right" />

</LinearLayout>

CustomTextView.java

   public class CustomTextView extends TextView {
    private View viewPart;
    private int viewPartRef;

    public CustomTextView(Context context) {
        super(context);
    }

    public CustomTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView, 0, 0);

        try {
            viewPartRef = a.getResourceId(R.styleable.CustomTextView_viewPart, -1);
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        viewPart = ((View) this.getParent()).findViewById(viewPartRef);
    }    

    public View getViewPart() {
        return viewPart;
    }

    public void setViewPart(View viewPart) {
        this.viewPart = viewPart;
    }}

You can decide your scenario and modify this code.