findViewById 在 PreferenceFragment 的 onViewCreated 中失败,Android
findViewById fails in onViewCreated of a PreferenceFragment, Android
我有两个片段:
- 扩展 Fragment
的 HomeFragment
- 扩展 PreferenceFragment
的 SettingsFragment
每个都包含一个 TextView
,我希望在 Java 代码中访问和修改其内容。我通过调用 findViewById
在 onViewCreated
中进行此修改,然后在 TextView
.
上使用 setText
这适用于 HomeFragment
,但不适用于 SettingsFragment
。
有关信息,SettingsFragment
的 TextView
在与首选项关联的布局中定义。奇怪的是,似乎 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>
前几天我也有类似的事情。
在片段的 onCreateView 中使用 findViewById() 而不是 onViewCreated 方法。
祝你好运。
像这样在 onCreateView() 中绑定您的视图
View view= inflater.inflate(R.layout.your_fragment, container, false);
TextView textView = view.findViewById(R.id.settingsText);
return view;
我有两个片段:
- 扩展 Fragment
的 HomeFragment
- 扩展 PreferenceFragment
每个都包含一个 TextView
,我希望在 Java 代码中访问和修改其内容。我通过调用 findViewById
在 onViewCreated
中进行此修改,然后在 TextView
.
上使用 setText
这适用于 HomeFragment
,但不适用于 SettingsFragment
。
有关信息,SettingsFragment
的 TextView
在与首选项关联的布局中定义。奇怪的是,似乎 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>
前几天我也有类似的事情。 在片段的 onCreateView 中使用 findViewById() 而不是 onViewCreated 方法。 祝你好运。
像这样在 onCreateView() 中绑定您的视图
View view= inflater.inflate(R.layout.your_fragment, container, false);
TextView textView = view.findViewById(R.id.settingsText);
return view;