【问题标题】:findViewById fails in onViewCreated of a PreferenceFragment, AndroidfindViewById 在 PreferenceFragment 的 onViewCreated 中失败,Android
【发布时间】:2019-02-27 10:37:48
【问题描述】:

我有两个片段:
- 扩展片段的 HomeFragment
- 扩展 PreferenceFragment 的 SettingsFragment

每个都包含一个TextView,我希望在Java 代码中访问和修改它的内容。我通过调用findViewByIdonViewCreated 中进行此修改,然后在TextView 上使用setText
这适用于HomeFragment,但不适用于SettingsFragment
有关信息,SettingsFragmentTextView 在与首选项关联的布局中定义。奇怪的是,PreferenceFragment 类型的视图层次结构似乎在 onViewCreated 中还没有完全准备好!为了更进一步,我尝试在一些延迟后(使用postDelay)放置修改TextView的代码,并且成功了!

下面,我放了所有必要的代码来测试我刚刚提出的问题。

MainActivity.java

public class MainActivity extends AppCompatActivity {

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

        final HomeFragment homeFragment = new HomeFragment();
        final SettingsFragment settingsFragment = new SettingsFragment();

        getFragmentManager().beginTransaction()
                .add(R.id.fragmentContainer, homeFragment).commit();

        // Just a simple button to switch between the two fragments
        Button button = findViewById(R.id.activityButton);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if(homeFragment.isAdded()) {
                    getFragmentManager().beginTransaction()
                            .replace(R.id.fragmentContainer, settingsFragment).commit();
                } else {
                    getFragmentManager().beginTransaction()
                            .replace(R.id.fragmentContainer, homeFragment).commit();
                }
            }
        });
    }
}

HomeFragment.java

public class HomeFragment extends Fragment {

    public HomeFragment() {
        // Required empty public constructor
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_home, container, false);
    }

    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        TextView textView = view.findViewById(R.id.homeText);
        if(textView != null) {
            textView.setText("Home fragment text (modified)");
        }
    }
}

SettingsFragment.java

public class SettingsFragment extends PreferenceFragment {


    public SettingsFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        addPreferencesFromResource(R.xml.fragment_settings);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        return super.onCreateView(inflater, container, savedInstanceState);
    }

    @Override
    public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);

        // ---- BLOCK 1 -----
        TextView textView = view.findViewById(R.id.settingsText);
        if (textView != null) {
            textView.setText("Preference 1 (modified)");
        }

        // ---- BLOCK 2 -----
//        view.post(new Runnable() {
//            @Override
//            public void run() {
//                TextView textView = view.findViewById(R.id.settingsText);
//                if (textView != null) {
//                    textView.setText("Preference 1 (modified)");
//                }
//            }
//        });

        // ---- BLOCK 3 -----
//        view.postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                TextView textView = view.findViewById(R.id.settingsText);
//                if (textView != null) {
//                    textView.setText("Preference 1 (modified)");
//                }
//            }
//        }, 100);
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/activityText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:gravity="center_horizontal"
        android:text="MainActivity" />

    <Button
        android:id="@+id/activityButton"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/activityText"
        android:text="Change fragment"/>

    <FrameLayout
        android:id="@+id/fragmentContainer"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintTop_toBottomOf="@id/activityButton"
        app:layout_constraintBottom_toBottomOf="parent">

    </FrameLayout>

</android.support.constraint.ConstraintLayout>

fragment_home.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    tools:context=".HomeFragment">

    <TextView
        android:id="@+id/homeText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        android:text="Home fragment text" />

</android.support.constraint.ConstraintLayout>

fragment_settings.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
    <PreferenceCategory
        android:layout="@layout/preference_layout_category">

        <Preference
            android:enabled="true"
            android:layout="@layout/preference_layout" />

    </PreferenceCategory>
</PreferenceScreen>

preference_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/settingsText"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:textAllCaps="true"
        android:text="Preference 1"/>

</android.support.constraint.ConstraintLayout>

preference_layout_category.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <TextView
        android:id="@+id/settingsTextContainer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:textAllCaps="true"
        android:background="@android:color/background_dark"
        android:textColor="@android:color/background_light"
        android:text="Category 1"/>

</android.support.constraint.ConstraintLayout>

【问题讨论】:

    标签: android android-fragments fragment preference preferencefragment


    【解决方案1】:

    前几天我也有类似的事情。 在片段的 onCreateView 中使用 findViewById() 而不是 onViewCreated 方法。 祝你好运。

    【讨论】:

    • 我开始使用 onCreateView 但它不起作用。我故意使用 onViewCreated 因为它是在 onCreateView 之后触发的
    • 然后使用自定义首选项。请点击此链接:stackoverflow.com/questions/34548731/…
    • 当我开始使用这种技术时,我注意到了一些奇怪的行为:onBindView 被调用了很多次,而我只有一个自定义首选项的实例?任何想法为什么?
    【解决方案2】:

    像这样在 onCreateView() 中绑定你的视图

    View view= inflater.inflate(R.layout.your_fragment, container, false);
    TextView textView = view.findViewById(R.id.settingsText);
    return view;
    

    【讨论】:

    • PreferenceFragment 的 onCreateView 与普通的 Fragment 略有不同。实际上就是调用 super.onCreateView(inflater, container, savedInstanceState); 另外,我们不能对布局进行充气,因为它关联的 XML 文件应该放在 xml 资源文件夹中
    猜你喜欢
    • 2021-06-10
    • 2016-03-09
    • 1970-01-01
    • 2011-03-23
    • 1970-01-01
    • 1970-01-01
    • 2017-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多