方法findViewById无法正常工作

时间:2019-06-10 16:23:10

标签: java android android-layout

我正在尝试更改NavigationView子级的文本。我正在使用findViewById直接获取TextView。它可以在MainActivity中使用,但在其他所有Activity中,findViewById都返回空引用。

顺便说一句,这是我第一个提交的问题,希望我能遵守指南。

我似乎无法弄清楚这一点,所以我不知道从哪里开始。

这是每个活动布局中的NavigationView

<android.support.design.widget.NavigationView
       android:id="@+id/nav_view"
       android:layout_width="wrap_content"
       android:layout_height="match_parent"
       android:layout_gravity="start"
       android:visibility="visible"
       app:headerLayout="@layout/nav_header_main"
       app:menu="@menu/activity_main_drawer"/>

nav_header_main是具有上述TextView的组件,在上面的代码中被引用。这是nav_header_main:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/nav_header"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">
    <TextView
        android:id="@+id/nav_header_textView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:gravity="center"
        android:text="Angheluta Filip"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1"
        android:textColor="@android:color/white" />
</LinearLayout>

此代码来自MainActivity,在其中找到所述文本视图不会返回空引用

    NavigationManager navigationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //Downloads the database and than proceeds to setup the Activity
        //onDataChange gets called when the download is finished and dataSnapshot is the downloaded
        //data

        final AppCompatActivity context = this;
        FirebaseHandler.getFirebaseHandler().getReference().addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {

                FirebaseHandler.getFirebaseHandler().setData(dataSnapshot);
                DataSnapshot userSnapshot = dataSnapshot.child("Users").child(FirebaseHandler.getFirebaseHandler().getAuth().getUid());
                User.initializeCurrentUser(userSnapshot);

                //Add side bar to this activity
                navigationManager = new NavigationManager(context);
                navigationManager.createNavBar();

                //Recycler view setup
                RecyclerManager recyclerManager = new RecyclerManager();
                recyclerManager.createRecyclerWithLargeElements(context, Voluntariat.getDataSet());

                //Sort spinner setup
                SortSpinnerManager sortSpinnerManager = new SortSpinnerManager();
                sortSpinnerManager.createSortSpinnerManager(context, recyclerManager);

                //Search bar setup
                SearchBarManager searchBarManager = new SearchBarManager();
                searchBarManager.createSearchBar(context, recyclerManager, Voluntariat.getDataSet());

                TextView textViewHeader = findViewById(R.id.nav_header_textView);
                Log.d("textHeader", textViewHeader.getText().toString());
                textViewHeader.setText(User.currentUser.lastName + " " + User.currentUser.firstName);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });



    }

但这来自onCreate方法中的任何其他活动


    RecyclerManager recyclerManager;
    NavigationManager navigationManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_toate_vol);

        //Add side bar to this activity
        navigationManager = new NavigationManager(this);
        navigationManager.createNavBar();

        //RECYCLERVIEW SETUP
        recyclerManager = new RecyclerManager();
        recyclerManager.createRecyclerWithSmallElements(this, Voluntariat.getDataSet());

        //Search bar managing
        SearchBarManager searchBarManager = new SearchBarManager();
        searchBarManager.createSearchBar(this, recyclerManager, Voluntariat.getDataSet());

        TextView textViewHeader = findViewById(R.id.nav_header_textView);
        Log.d("textHeader", textViewHeader.getText().toString());
        textViewHeader.setText(User.currentUser.lastName + " " + User.currentUser.firstName);
    }

当我访问MainActivity以外的任何活动时,在textViewHeader上会收到NullPointerException。

编辑:我添加了更多代码,并对其进行了更改,因此直接从Activity文件而不是从NavigationManager文件中调用findViewById。错误是一样的。

EDIT2:从activity_toate_vol.xml添加了更多代码:

此布局似乎没有带问题ID的任何视图,但该ID位于nav_header_main.xml文件中,该文件是在具有headerLayout属性的activity_toate_vol.xml文件中设置的:

 app:headerLayout="@layout/nav_header_main"

此NavigationView是根布局的直接子级,其余代码无关。在MainActivity中也可以找到相同的导航视图。

<android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        android:visibility="visible"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/activity_main_drawer">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:layout_gravity="bottom"
            android:gravity="bottom"
            android:orientation="vertical"
            android:padding="16dp">

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:gravity="bottom"
                android:orientation="horizontal">

                <ImageView
                    android:id="@+id/imgdeconctare"
                    android:layout_width="27dp"
                    android:layout_height="27dp"
                    android:alpha=".6"
                    android:src="@drawable/ic_logout"
                    app:srcCompat="@drawable/ic_logout"
                    tools:srcCompat="@drawable/ic_logout" />

                <TextView
                    android:id="@+id/logout"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginLeft="20dp"
                    android:gravity="center|start"
                    android:text="Deconectare"
                    android:textColor="@android:color/black" />
            </LinearLayout>

        </LinearLayout>

    </android.support.design.widget.NavigationView>

编辑3:我想出了一种解决方法,并且也确定了问题所在。事实证明,在更新文本之前,我必须以某种方式等待NavigationView膨胀。谁能帮助我以适当的方式做到这一点?因为我对此不满意。

        new Handler().postDelayed(new Runnable() {
            @Override
            public void run() {
                try {
                    wait(150);
                }
                catch(Exception e){
                }
                TextView textViewHeader = findViewById(R.id.nav_header_textView);
                Log.d("textHeader", textViewHeader.getText().toString());
                textViewHeader.setText(User.currentUser.lastName + " " + User.currentUser.firstName);
            }
        }, 100);

1 个答案:

答案 0 :(得分:0)

欢迎光临!当findViewById返回null时,可能意味着两件事。

1)您传递给'setContentView'的布局没有具有该ID的视图...

2)布局确实具有该视图,但是视图本身尚未完全膨胀。要等到视图完全膨胀后,可以使用GlobalLayoutListener

在Java中:

setContentView(R.layout.activity_other);
final NavigationView navigationView = findViewById(R.id.nav_view);

navigationView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        TextView text = navigationView.findViewById(R.id.nav_header_textView);
        text.setText("Hello StackOverflow");
  navigationView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
    }
});

以及当您切换到Kotlin时:

setContentView(R.layout.activity_main)
val view = findViewById<NavigationView>(R.id.nav_view)
view?.viewTreeObserver?.addOnGlobalLayoutListener(object: ViewTreeObserver.OnGlobalLayoutListener{
    override fun onGlobalLayout() {
        val header = findViewById<TextView>(R.id.nav_header_textView)
        header.text= "Hallo Main"
        view.viewTreeObserver.removeOnGlobalLayoutListener(this)
    }
})