user2574853
user2574853

Reputation: 31

calling findViewById outside of Activity return null

In order to dynamically show loading view in the runtime, I created a self_pro_bar.xml and created a normal java class ShyProgressBar. Append custom view into main view in the code, then, if call findViewById inside Activity class, it can find added custom view, but it call findViewById from normal java class, it always returns null.

self_pro_bar.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/selfprogressbar"
    android:gravity="center_horizontal"
    android:layout_marginTop="20dp"
    android:layout_width="100dp"
    android:layout_height="30dp"
    android:orientation="horizontal" 
    android:background="#eee">

    <TextView 
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="loading..."
        />

</LinearLayout>

ShyProgressBar class

public class ShyProgressBar {
        private Context context;
        public ShyProgressBar(Context context) {
            this.context = context;
        }

        public View get() {
            LayoutInflater inflater = (LayoutInflater) 
                    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

            return inflater.inflate(R.layout.self_pro_bar, null);
        }

        public boolean exist(Activity activity) {
            return activity.findViewById(R.layout.self_pro_bar) != null;
        }
 }

Main activity xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:onClick="load_data"
        android:text="@string/click_me" />

    <LinearLayout
        android:id="@+id/dataview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical" >
    </LinearLayout>

</RelativeLayout>

Main Activity

    public class MainActivity extends Activity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
        public void load_data(View v) {
            ShyProgressBar ins = new ShyProgressBar(this);
            View p_b = ins.get();
            if(!ins.exist(MainActivity.this)) {
                LinearLayout rl = (LinearLayout) findViewById(R.id.dataview);
                rl.addView(p_b);
                Object c = ins.exist(MainActivity.this) // this code still returns null!
            }
        }
}
  1. Not work - Object c value is still null when calling findViewById inside ShyProgressBar.
  2. Works if use below statement to judge if the view exists in load_data method of Activity class. View p_b_v = findViewById(R.id.selfprogressbar); It works fine and the value is not null.

Not sure why findViewById works in the Activity, but not works in non-activity class.

Upvotes: 2

Views: 4196

Answers (3)

Amsheer
Amsheer

Reputation: 7131

You can not use findViewById method outside of Activity but if you want to use that TextView, Button or whatever just declare in Activity oncreate and set it to an static method. Call the components from that static method.

UPDATE Step 1:

Inside of Activity onCreate method()

Button b= (Button) findViewById(R.id.yourComponentID);

Step 2:

Create a class :

public class xyz{
Button x ;
public static void save_Button(Button b){
x = b;
}
public static Button get_button(){
 return x;
}
}

Step 3 : in your activity call this save_Button method e.g

save_Button(b);

Step 4:

You can call get_button() from anywhere of your app.

Upvotes: 0

Utpal Sharma
Utpal Sharma

Reputation: 326

Because findViewById(R.id.dataview) is a method of Activity class.

And it will come when you extend your class with Activity. If you want in non-activity class then using method parameter you can pass it. example:-

void methodName(Activity activity){
}

and while passing use YourActivity.this

Upvotes: 0

Okas
Okas

Reputation: 2664

Your exists method is not correct. There you inflate your Main_activity.xml once again and then check if R.layout.self_pro_bar is present. It is of course not there as this item is not a part of Main_activity layout. Once this check is done you throw away layout you just inflated - you are not attaching it to anywhere.

Method 'exists' is not needed, instead in your activity code you can check if self_pro_bar has already added to main layout with following code:

public void load_data(View v) {
    ShyProgressBar ins = new ShyProgressBar(this);
    if(findViewById(R.id.selfprogressbar) == null) {
       LinearLayout rl = (LinearLayout) findViewById(R.id.dataview);
       View p_b = ins.get();
       rl.addView(p_b);
       }
    }

Upvotes: 1

Related Questions