Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass view reference to android custom view?

Tags:

I did as follows

1) Creating a styleable

<declare-styleable name="Viewee">     <attr name="linkedView" format="reference"/> </declare-styleable> 

2) defining custom view layout

<LinearLayout         xmlns:android="http://schemas.android.com/apk/res/android"         android:layout_width="fill_parent"         android:layout_height="wrap_content"         android:background="#ffc0">     <TextView             android:id="@+id/custom_text"             android:layout_width="fill_parent"             android:layout_height="wrap_content"             android:text="[text]"             /> </LinearLayout> 

3) Creating required class

public class Viewee extends LinearLayout { public Viewee(Context context, AttributeSet attributeSet) {     super(context, attributeSet);     View.inflate(context, R.layout.viewee, this);     TextView textView = (TextView) findViewById(R.id.custom_text);     TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.Viewee);     int id = typedArray.getResourceId(R.styleable.Viewee_linkedView, 0);     if (id != 0)     {         View view = findViewById(id);         textView.setText(((TextView) view).getText().toString());     }      typedArray.recycle(); } } 

and finally in an activity like below

<LinearLayout         xmlns:android="http://schemas.android.com/apk/res/android"         xmlns:app="http://schemas.android.com/apk/res/com.ns"         android:layout_width="fill_parent"         android:layout_height="fill_parent"         android:orientation="vertical">     <TextView             android:id="@+id/tvTest"             android:layout_width="fill_parent"             android:layout_height="wrap_content"             android:text="android"/>     <com.ns.Viewee             android:layout_width="fill_parent"             android:layout_height="fill_parent"             app:linkedView="@+id/tvTest"             /> </LinearLayout> 

now although I recieve a non zero id in Viewee constractor, findViewById(id) retuns null and NullPointerException occures.

what am I missing?

I did it as described here

like image 586
anonim Avatar asked Jun 14 '12 19:06

anonim


People also ask

What is a ViewGroup in Android?

ViewGroup is a collection of Views(TextView, EditText, ListView, etc..), somewhat like a container. A View object is a component of the user interface (UI) like a button or a text box, and it's also called a widget.

Can you a create custom view how Android?

Creating custom views. By extending the View class or one of its subclasses you can create your custom view. For drawing view use the onDraw() method. In this method you receive a Canvas object which allows you to perform drawing operations on it, e.g. draw lines, circle, text or bitmaps.

Can you create custom views How?

Go to View > Workbook Views > Custom Views > Add. In the Name box, type a name for the view. Tip: To make a view easier to identify, you can include the name of the active worksheet in the name of a view. Under Include in view, select the check boxes of the settings that you want to include.

What is customized view?

A well-designed custom view is much like any other well-designed class. It encapsulates a specific set of functionality with an easy to use interface, it uses CPU and memory efficiently, and so on. In addition to being a well-designed class, though, a custom view should: Conform to Android standards.


2 Answers

I found the answer!

The issue was with findViewById(id) and where I called it. findViewById only looks for a child view not a view exist on upper hierarchy level as documentation says . So I have to call something like getRootView().findViewById(id) but that also returns null becase where I called it was not corrent.

In Viewee constractor Viewee itself has not attached to its root yet so that call causes NullPointerException.

So If I call to getRootView().findViewById(id) somewhere else after constraction, it works fine and both "@+id/tvTest" and "@id/tvTest" are correct. I've tested it!

the answer is as follows

public class Viewee extends LinearLayout {     public Viewee(Context context, AttributeSet a)     {         super(context, attributeSet);         View.inflate(context, R.layout.main6, this);         TextView textView = (TextView) findViewById(R.id.custom_text);         TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);         int id = t.getResourceId(R.styleable.Viewee_linkedView, 0);         if (id != 0)         {             _id = id;         }          t.recycle();     }      private int _id;      public void Foo()     {         TextView textView = (TextView) findViewById(R.id.custom_text);         View view = getRootView().findViewById(_id);         textView.setText(((TextView) view).getText().toString());     } } 

and Foo is called when it is required to process the attached view via its reference id somewhere else in your activity and the like.

The credit completely goes to those guys contributed in this post. I had not seen that post before submitting the question.

like image 151
anonim Avatar answered Sep 20 '22 09:09

anonim


I know this is an old question, but I thought I would add another way of doing this as I wanted to encapsulate everything into my custom view.

Instead of calling from the outside, another way of getting a view higher up in the hierarchy, I've hooked into onAttachedToWindow() instead:

public class MyCustomView extends LinearLayout {     private int siblingResourceId;     private View siblingView;      public MyCustomView(Context context, AttributeSet a) {         super(context, attributeSet);         inflate(context, R.layout.main6, this);         TextView textView = (TextView) findViewById(R.id.custom_text);         TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);         siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, NO_ID);         t.recycle();     }      @Override     public void onAttachedToWindow() {         super.onAttachedToWindow();         if (siblingResourceId != NO_ID) {             siblingView = ((View) getParent()).findViewById(siblingResourceId);         }     } } 

onAttachedToWindow is called quite early, but apparently late enough for the whole view hierarchy to have settled. It works flawless for my needs at least and is a little bit more controlled and doesn't need interaction from outside to work ;-)

EDIT: Kotlin code added

class MyCustomView(context: Context, attributeSet: AttributeSet) : LinearLayout(context, attributeSet) {     private val siblingResourceId: Int     private lateinit var siblingView: View      // All other constructors left out for brevity.      init {         inflate(context, R.layout.main6, this)         val textView = findViewById<TextView>(R.id.custom_text)         val t = context.obtainStyledAttributes(a, R.styleable.Viewee)         siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, NO_ID)         t.recycle()     }      override fun onAttachedToWindow() {         super.onAttachedToWindow()         if (siblingResourceId != NO_ID) {             siblingView = (parent as View).findViewById(siblingResourceId)          }     } } 

Note: We assume that the parent of this custom View is a View itself.

like image 41
Darwind Avatar answered Sep 22 '22 09:09

Darwind