显示ListView
的屏幕,如果出现问题(连接丢失,服务器不可用等),可以用错误屏幕替换。
我需要能够在这两个屏幕之间来回切换(编程)。
主屏幕必须是片段 这是因为我的应用程序由几个部分组成,每个部分都可以从导航栏中访问。
主要的片段类名为AllQueuesFragment
:它的XML布局由FrameLayout
组成,我与FragmentManager
结合使用以在ErrorFragment
之间切换(包含错误消息)和QueuesViewFragment
(包含ListView
)。
public class AllQueuesFragment extends Fragment
{
public AllQueuesFragment()
{
super();
}
@Override
public void onStart()
{
super.onStart();
// Show the right fragment based on connectivity status
checkConnection();
}
public void checkConnection()
{
final NetworkManager netManager = NetworkManager.getInstance(this.getActivity());
if (netManager.isConnected())
showQueues();
else
showNoConnection();
}
public void showNoConnection()
{
ErrorFragment fragNoConnection = new ErrorFragment();
displayFragment(fragNoConnection);
fragNoConnection.setTitle(R.string.text_no_connection);
fragNoConnection.setIcon(R.drawable.thatfeel);
fragNoConnection.setLoaderVisibility(false);
}
public void showQueues()
{
QueuesViewFragment fragQueuesView = new QueuesViewFragment();
displayFragment(fragQueuesView);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the view
View rootView = inflater.inflate(R.layout.fragment_allqueues, container, false);
return rootView;
}
// Displays a new fragment
public void displayFragment(Fragment fragment)
{
if (fragment != null)
{
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
}
}
}
错误屏幕如下:
public class ErrorFragment extends Fragment
{
private TextView textTitle;
public ErrorFragment()
{
super();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the view
View rootView = inflater.inflate(R.layout.fragment_error, container, false);
// Get the widgets
textTitle = (TextView)rootView.findViewById( R.id.fragment_error_text );
return rootView;
}
// Set methods
public void setTitle(int id) { textTitle.setText(id); }
}
在布局准备好之前调用setTitle()
方法,结果抛出NullPointerException
。
class AllQueuesFragment
{
....
public void displayFragment(Fragment fragment)
{
if (fragment != null)
{
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
}
}
public void showNoConnection()
{
ErrorFragment fragNoConnection = new ErrorFragment();
displayFragment(fragNoConnection);
// PROBLEM HERE: Before calling setTitle(), I must be sure that ErrorFragment's
// layout is inflated!
fragNoConnection.setTitle(R.string.text_no_connection);
}
....
}
class ErrorFragment
{
....
public void setTitle(String value) { textTitle.setText(value); }
....
}
我无法直接从setTitle()
拨打ErrorFragment::onCreateView()
,因为我事先并不知道需要显示哪条消息。
如何确保fragNoConnection
完成布局?
有没有更好的方法来实现我的目标?
我能想到的唯一解决方法是使用缓冲区来推迟实际调用:
class ErrorFragment
{
// This string will hold the title until the layout is inflated
private String titleBuffer;
private TextView textTitle = null;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the view
View rootView = inflater.inflate(R.layout.fragment_error, container, false);
// Get the widgets
textTitle = (TextView)rootView.findViewById( R.id.fragment_error_text );
// Do the actual set
setTitle(titleBuffer);
return rootView;
}
....
public void setTitle(String value)
{
titleBuffer = value;
// If the layout is not inflated, defer the actual set
if (textTitle != null)
textTitle.setText(titleBuffer);
}
....
}
但我不太喜欢这个解决方案(上面的代码已经过简化; ErrorFragment
有更多属性)。
通知书?
提前致谢
答案 0 :(得分:1)
您需要在callback
中使用ErrorFragment
方法,当视图膨胀时,您可以在onViewCreated
的回调界面中调用该方法并设置标题。
样品:
ErroFragment 中的
public class ErroFragment extends Fragment
{
static interface ErrorDone{
public void doneInflating();
}
private TextView textTitle;
private ErrorDone ed;
public ErroFragment()
{
super();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// Inflate the view
View rootView = inflater.inflate(R.layout.fragment_error, container, false);
// Get the widgets
textTitle = (TextView)rootView.findViewById( R.id.fragment_error_text );
return rootView;
}
// Set methods
public void setTitle(int id) { textTitle.setText(id); }
public void setInterFace(ErrorDone er){ this.ed = er; }
}
然后在AllQueuesFragment
public class AllQueuesFragment extends Fragment implements ErroFragment.ErrorDone
它将生成方法doneInflating
你需要设置界面:
public void showNoConnection()
{
ErrorFragment fragNoConnection = new ErrorFragment();
displayFragment(fragNoConnection);
fragNoConnection.setInterFace(this);
}
在doneInflating
生成的方法(AllQueuesFragment
)中,您可以在那里设置标题:
public void doneInflating(){
fragNoConnection.setTitle(R.string.text_no_connection);
fragNoConnection.setIcon(R.drawable.thatfeel);
fragNoConnection.setLoaderVisibility(false);
}
答案 1 :(得分:1)
这正是应该用于参数的类型:
public void showNoConnection() {
ErrorFragment fragNoConnection = new ErrorFragment();
Bundle args = new Bundle();
//you can also use putInt here if you'd rather pass a string resource id, along with anything else you can stick into a Bundle
args.putString("title", "some title");
fragNoConnection.setArguments(args);
displayFragment(fragNoConnection);
}
然后在ErrorFragment
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_error, container, false);
TextView textTitle = (TextView)rootView.findViewById( R.id.fragment_error_text );
//now retrieve the argument...
textTitle.setText(getArguments().getString("title"));
return rootView;
}
Fragment甚至会在改变方向后记住它的论点。
如果您觉得自己很迂腐,可以在ErrorFragment
中创建一个静态工厂方法,将标题作为参数,然后创建Fragment并添加参数,这样就可以实现正确的封装:)< / p>
答案 2 :(得分:0)
如果您想确保FragmentTransaction
已提交且有效,您可以使用executePendingTransactions
方法:
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.frame_container, fragment).commit();
fragmentManager.executePendingTransactions();
但是,正确的方法是在实例化时将标题值发送给Fragment。这是从IDE(eclipse或Android Studio)创建片段时的默认模式