Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reference one control from another during inflation?

I am trying to reference a sibling control through XML.

To declare an attribute to reference an id from MyTextView:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="MyTextView">
        <attr name="valueTextViewId" format="reference" />
    </declare-styleable>
</resources>

fragment_example.xml - How to use custom attribute:

<!-- Declare a "Title" text view that references a "Value" -->
<com.example.MyTextView
    android:id="@+id/foo"
    example:valueTextViewId="@id/bar"
    ... />

<!-- Depending on the "text" attribute of this "Value" textview -->
<!-- Do something within "Title" textview -->
<com.example.MyTextView android:id="@+id/bar" />

MyFragment.java - Inflating the controls

public View onCreateView(LayoutInflater inflater, ViewGroup container, 
        Bundle savedInstanceState) {
        // calls MyTextView Ctor
    View v = inflater.inflate(R.layout.fragment_example, container, false);
}

MyTextView class constructor - During inflation do something with referenced textview:

public TextView(Context context, AttributeSet attrs) {
    super(context, attrs);

    TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.MyTextView);
    int refId = a.getResourceId(R.styleable.MyTextView_valueTextViewId);

    // Updated to use context
    if (refId > -1 && context instanceof Activity) {
        Activity a = (Activity)context;
        View v = a.findViewById(refId);

        // THE PROBLEM: v is null
        if (v != null) {
            // In my case, I want to check if the "Value" textview
            // is empty. If so I will set "this" textColor to gray
        }
    }
}

in this example v is always null. I assume because during Layout Inflation, the controls are not added yet. Another thing to note is that this is in a Fragment, therefore that might be the reason I cant find the view in the parent activity.

Is it possible to reference a control from another like this?

like image 414
Tom Fobear Avatar asked May 23 '13 03:05

Tom Fobear


People also ask

How can control the control of inflation?

One significant monetary way to curb Inflation is to control the money supply in the economy. If the money supply goes down, the demand for goods will reduce, causing a price fall. Another way to curb the money supply is when the government withdraws specific paper notes or coins from circulation.

What is inflation references?

A general increase in prices in an economy and consequent fall in the purchasing value of money. See also core inflation; hyperinflation; stagflation.

How can inflation be controlled explain briefly?

There are four basic strategies that central banks have used to control and reduce inflation: exchange-rate pegging; monetary targeting; inflation targeting; and.

Who is responsible for the control of inflation?

The Fed's No. 1 mandate is to control inflation, and the most influential player in the fight against inflation is the Federal Reserve chair. Their most powerful tool is to raise interest rates.


2 Answers

Is it possible to reference a control from another like this?

It is possible to reference another View from a View.

But to do property checking in the constructor of a View is not advised.
There is no guarantee that any particular View is instantiated before any other during View inflation.

Compare these two layouts:
first_layout.xml

<com.example.MyTextView
    ...
    android:id="@+id/foo"
    example:valueTextViewId="@+id/bar" />

<com.example.MyTextView
    ...
    android:id="@+id/bar" />

second_layout.xml

<com.example.MyTextView
    ...
    android:id="@+id/bar" />

<com.example.MyTextView
    ...
    android:id="@+id/foo"
    example:valueTextViewId="@+id/bar" />

In this example, it's clear that property checking from the constructor will not work in one of these layouts.

I agree that it is possible to store the reference to another View within a View:

public MyTextView(Context context, AttributeSet attrs) {
    super(context, attrs);
    TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
    mReferenceId = a.getResourceId(R.styleable.MyTextView_valueTextViewId);
    ...
}

private int mReferenceId;

public View getReferenceViewFromActivity() {
    if (getContext() instanceof Activity) {
        return ((Activity)getContext()).findViewById(mReferenceId);
    return null;
}

public View getReferenceView(View view) {
    return view.findViewById(mReferenceId);
}

But you should definitely do any and all property checking within the Activity or Fragment:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    MyTextView myTextView = (MyTextView)view.findViewById(R.id.foo);
    MyReferenceView refView = (MyReferenceView)myTextView.getReferenceView(view);
    //
    // do property checking
    //
}
like image 64
EricRobertBrewer Avatar answered Sep 23 '22 17:09

EricRobertBrewer


if a textview with the id of bar is available within the id of bar, you can do something like this.

<com.example.MyTextView
    android:id="@+id/foo"
    ...
    android:tag="bar" />

<com.example.MyTextView android:id="@+id/bar" />

and

public TextView(Context context, AttributeSet attrs) {
    super(context, attrs);

      int barId = getResources().getIdentifier(getTag(), "id", packageName);
      TextView bar = mActivity.findViewById(barId);

    if (bar.getText() == "") {
        // Gray out this "title" textview
        setColor(android.R.color.gray);
    }

    // maybe set a text change listener to bar to make it future-proof
}

i would just pass the id as a tag on your MyTextView so you dont need to create a new attribute.

like image 23
r2DoesInc Avatar answered Sep 20 '22 17:09

r2DoesInc