Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to obtain the value for a reference attribute

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.

like image 220
Torsten Robitzki Avatar asked Jan 18 '16 17:01

Torsten Robitzki


People also ask

How to get the attribute value in c#?

First, declare an instance of the attribute you want to retrieve. Then, use the Attribute. GetCustomAttribute method to initialize the new attribute to the value of the attribute you want to retrieve. Once the new attribute is initialized, you can use its properties to get the values.

What is attribute reference?

Attribute references are attributes that derive their primitive type, default value, immutable flag and attribute rules from another preexisting attribute definition.


1 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.

like image 159
The Goat Avatar answered Nov 15 '22 17:11

The Goat