我已按照developer.android.com/guide/topics/ui/action.bar.html上的指南操作了操作栏中的标签。
在我的主要活动中,我添加了三个标签:
public class ToDoActivity extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
actionBar.setDisplayShowTitleEnabled(false);
Tab tab = actionBar.newTab().setText("Task List")
.setTabListener(new TabListener<TaskListFragment>(
this, "task list", TaskListFragment.class));
actionBar.addTab(tab);
tab = actionBar.newTab().setText("Pie Chart")
.setTabListener(new TabListener<TaskPieChartFragment>(
this, "pie chart", TaskPieChartFragment.class));
actionBar.addTab(tab);
tab = actionBar.newTab().setText("Task Map")
.setTabListener(new TabListener<TaskMapFragment>(
this, "task map", TaskMapFragment.class));
actionBar.addTab(tab);
}
}
第一个标签的片段执行得很好。它可以查找视图并访问活动。单击导航中的第二个选项卡可显示片段(按预期),但不执行该片段的生命周期功能(onActivityCreated(),onStart(),onResume()等)。此外,每次从该片段调用getActivity()都会返回一个null对象。
public class TaskPieChartFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_task_pie_chart, container, false);
}
public void updatePieChart() {
TextView textView = (TextView) getActivity().findViewById(R.id.some_text);
textView.setText("something something");
}
}
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/some_text"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
从TabListener中调用updatePieChart()函数:
public class TabListener<T extends Fragment> implements ActionBar.TabListener {
public void onTabSelected(Tab tab, FragmentTransaction ft) {
if (mFragment == null) {
mFragment = Fragment.instantiate(mActivity, mClass.getName());
ft.add(android.R.id.content, mFragment, mTag);
} else {
ft.attach(mFragment);
}
try {
TaskPieChartFragment pieChartFragment = (TaskPieChartFragment) mFragment;
pieChartFragment.updatePieChart();
} catch (ClassCastException e) {
// not the fragment we were looking for
}
}
}
每当我选择带有TaskPieChartFragment的标签时,我都会在updatePieChart()的第一行发出一个NullPointerException。为什么第二个片段与第一个片段的行为完全不同,我似乎无法获得对该活动的引用?
PS
我也试过传递TabListener中保存的活动。然后NullPointerException不是源于updatePieChart()中的第一行,而是第二行,因此活动无法找到该视图。
答案 0 :(得分:0)
活动不拥有视图,所以它无法找到它并不奇怪。将getActivity()
替换为getView()
,您应该很高兴。 getView()
为您提供此Fragment的根视图,并且应该能够找到您正在查找的视图,因为它是视图的祖先之一。您只能找到一个包含其祖先的视图,因为findViewWithId()
会递归查看所有子项以查找视图。
答案 1 :(得分:0)
它崩溃的原因是因为FragmentTransaction
尚未完成。
方法getActivity()
仅返回片段回调onAttach()
和onDetach()
之间的活动,而这只会在事务ft
完成且框架通过所有事件后才会发生回调。
你可能应该在onResume()
或其他一些Fragment生命周期回调中更新你的饼图。
修改强>
重新阅读代码,在您调用updatePieChart()
时,尚未创建视图。所以也是这样。
作为一般规则,片段的视图应在实际片段内更新。
可能是这样的:
公共类TaskPieChartFragment扩展Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_task_pie_chart, container, false);
}
public void onResume(){
super.onResume();
updatePieChart();
}
private void updatePieChart() {
TextView textView = (TextView) getView().findViewById(R.id.some_text);
textView.setText("something something");
}
}
这个想法是片段应该是自包含的实体,而不是依赖于调用它们进行更新的活动。