如何添加带有片段的新选项卡
How do I add a new tab with fragments
所以我想创建 3 个选项卡,每个选项卡都各不相同。 xml 我已经涵盖了。但不是如何在不使我的应用程序崩溃的情况下创建选项卡。
我已经实现了带有viewpage的滑动标签。
http://developer.android.com/training/implementing-navigation/lateral.html
http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
和一部分
http://www.java2s.com/Code/Android/UI/Demonstrateshowfragmentscanparticipateintheoptionsmenu.htm
当我尝试转到下一个选项卡时(滑动确实没问题)我收到错误消息:
07-08 22:07:57.414: E/AndroidRuntime(6865): FATAL EXCEPTION: main
07-08 22:07:57.414: E/AndroidRuntime(6865): Process: com.cyberdog.magiceasydraft, PID: 6865
07-08 22:07:57.414: E/AndroidRuntime(6865): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.view.ViewPager.setCurrentItem(int)' on a null object reference
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.cyberdog.magiceasydraft.addPlayersfragmentTab.doPositiveClick(addPlayersfragmentTab.java:113)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.cyberdog.magiceasydraft.addPlayersfragmentTab$MyAlertDialogFragment.onClick(addPlayersfragmentTab.java:165)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:160)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.os.Handler.dispatchMessage(Handler.java:102)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.os.Looper.loop(Looper.java:135)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.app.ActivityThread.main(ActivityThread.java:5274)
07-08 22:07:57.414: E/AndroidRuntime(6865): at java.lang.reflect.Method.invoke(Native Method)
07-08 22:07:57.414: E/AndroidRuntime(6865): at java.lang.reflect.Method.invoke(Method.java:372)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
所以..我做错了什么?我可以看到对我创建的圆形片段有一个空引用......但我不知道如何解决这个问题。这是我第一次使用片段和选项卡。
代码:
主要 activity:
public class CreateDraft extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private fragmentPageAdapter mAdapter;
private ActionBar actionBar;
private Fragment addPlayer, createRound,score;
private String[] tabs = { "Add players", "Create round", "Score" };
public static final String CuSToM_FRAGMENT_KEY ="ADD_PLAYER_TAB";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_draft);
viewPager = (ViewPager) findViewById(R.id.activity_viewpager_main);
actionBar = getActionBar();
mAdapter = new fragmentPageAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
if(savedInstanceState == null){
FragmentManager fm = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
addPlayer = fm.findFragmentByTag("Add Players");
if(addPlayer == null){
addPlayer = new addPlayersfragmentTab();
ft.add(addPlayer, "Add players");
}
createRound = fm.findFragmentByTag("Create round");
if(createRound == null){
createRound = new createRoundfragmentTab();
ft.add(createRound, "Create round");
}
score = fm.findFragmentByTag("Score");
if(score == null){
score = new scoreResultfragmentTab();
ft.add(score, "Score");
}
ft.commit();
}
//
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
public void passBundleToFragment(int position){
if(true){
}
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
private void hiddenKeyboard(View v) {
InputMethodManager keyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
其中一个片段(其他的还没有包含太多代码):
public class addPlayersfragmentTab extends Fragment {
private Button addPlayer, createDraft;
private EditText evAddPlayer;
private ViewPager viewPager;
private List<Player> players;
private ListView lvAddedPlayers;
ListAdapter adapter;
private boolean buttonCreateDraftPressed= false;
public boolean isButtonCreateDraftPressed() {
return buttonCreateDraftPressed;
}
public void setButtonCreateDraftPressed(boolean buttonCreateDraftPressed) {
this.buttonCreateDraftPressed = buttonCreateDraftPressed;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.draft_adding_players,
container, false);
initialiseEditAndText(rootView);
players = new ArrayList<Player>();
lvAddedPlayers = (ListView) rootView.findViewById(
R.id.lv_players_adding);
adapter = new ListAdapter(rootView.getContext(), players);
lvAddedPlayers.setAdapter(adapter);
addPlayer = (Button) rootView.findViewById(R.id.button_total_player);
createDraft = (Button) rootView.findViewById(R.id.button_create_draft);
addPlayer.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Player player = new Player(evAddPlayer.getText().toString());
players.add(player);
adapter.notifyDataSetChanged();
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
});
createDraft.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (adapter != null && players != null) {
createdraft(players.size());
} else {
Toast.makeText(getActivity(),
"Add minimal 3 players to start the draft.",
Toast.LENGTH_LONG).show();
}
}
});
return rootView;
}
public void showDialog(){
DialogFragment newFragment = new MyAlertDialogFragment().newInstance(R.string.recreate_draft);
newFragment.show(getFragmentManager(), "dialog");
}
public void doPositiveClick(){
viewPager.setCurrentItem(1);
}
public void doNegativeClick(){
}
public int getTotalPlayers() {
return players.size();
}
public List<Player> getPlayersNames() {
return players;
}
public void initialiseEditAndText(View rootView) {
evAddPlayer = (EditText) rootView.findViewById(R.id.et_player_name);
}
public void createdraft(int totalplayers) {
if (totalplayers >= 3 && totalplayers <= 16) {
showDialog();
} else {
Toast.makeText(getActivity(),
"Minimum of 3 and maximum of 16 players.",
Toast.LENGTH_LONG).show();
}
}
public class MyAlertDialogFragment extends DialogFragment{
public MyAlertDialogFragment newInstance(int title){
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.abc_ic_search)
.setTitle(title)
.setPositiveButton("R.string.alert_dialog_ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addPlayersfragmentTab.this.doPositiveClick();
}
}
)
.setNegativeButton("R.string.alert_dialog_cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addPlayersfragmentTab.this.doNegativeClick();
}
}
)
.create();
}
}
}
编辑:
页面适配器:
public fragmentPageAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new addPlayersfragmentTab();
case 1:
// Games fragment activity
return new createRoundfragmentTab();
case 2:
// Movies fragment activity
return new scoreResultfragmentTab();
}
return null;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return 3;
}
}
编辑 2:
我跟随数据传递到 activity,这确实有效,但是如果我想从 activity 传递数据(从 addPlayerTab 获取数据)我得到又是一个空引用,这次我认为是因为 id 是错误的。但我的布局文件不使用 .那我怎么找到片段呢?
代码:
addPlayerTab的接口实现:
@Override
public void onButtonClickCreateRound(int position, List<Player> players) {
viewPager.setCurrentItem(position);
this.players = players;
GetPlayer();
}
addPlayerTab 中的代码:
public interface GoToCreateRoundListener{
public void onButtonClickCreateRound(int position, List<Player> players);
}
public void onAttach(Activity activity){
super.onAttach(activity);
try{
goCreateRound = (GoToCreateRoundListener)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()+" must implement GoToRoundListener");
}
}
public void createdraft(int totalplayers) {
if (totalplayers >= 3 && totalplayers <= 16) {
goCreateRound.onButtonClickCreateRound(1, players);
} else {
Toast.makeText(getActivity(),
"Minimum of 3 and maximum of 16 players.",
Toast.LENGTH_LONG).show();
}
}
这是将数据传递给createroundtab的接口实现:
@Override
public void GetPlayer() {
createRoundfragmentTab createRoundfragmentTab = (createRoundfragmentTab)getSupportFragmentManager().findFragmentById(R.layout.create_round);
createRoundfragmentTab.makeRandomFirstRound(players);
}
createroundTab 中的代码:
public interface GetPlayersFromAddPlayersListener{
public void GetPlayer();
}
public void onAttach(Activity activity){
super.onAttach(activity);
try{
getPlayers = (GetPlayersFromAddPlayersListener)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()+" must implement GetPlayersFromAddPlayersListener");
}
}
您没有初始化片段的 viewPager
字段 (addPlayersfragmentTab.viewPager
)。这就是你得到 NullPointerException 的原因。
您可以在 activity 中执行 getViewPager()
方法,然后从片段中调用它,即 ((CreateDraft) getActivity()).getViewPager().setCurrentItem(1)
我已经在上面分享了关于 Fragment
实例化的观点,所以我将再次引用我自己的话。
That whole if (savedInstance == null)
block is not required because Fragment
instantiation is the job of your PagerAdapter
. The ViewPager
will call PagerAdapter#getItem()
when it sees fit to.
虽然,很明显 NullPointerException
是由 addPlayersfragmentTab
中未初始化的 ViewPager
引用引起的,在创建时将视图寻呼机传递给片段的整个方法或者通过 getter 访问它的片段是错误的。
原因是片段是您的 UI 一部分的独立可重用实现,因此它不应与托管它的 activity 耦合。一旦你将它与你的视图寻呼机结合起来,你就再也不能在任何其他正常的 activity 中托管这个片段了。简而言之,该片段不再保持可重用状态。
那么,片段应该如何与其宿主通信 activity?好吧,使用 回调接口 。这是来自 Android 开发者官方网站的简短教程:Communicating with Other Fragments 但它同样适用于请求 activity 代表片段执行任何操作。
在您的情况下,您会通知主要 activity 用户在警报对话框中按下了“确定”,activity 将通过使用查看寻呼机移至下一个选项卡来对此做出响应。
通常当您想再次抓住 Fragment
时,您可以使用 findFragmentById()
或它的带有 findFragmentByTag()
的自定义标签。但是,整个 ViewPager
及其 PagerAdapter
不会向我们公开这些属性。
因此,要启用片段查找,您需要在 PagerAdapter
中保存对它们的引用。大致如下。
Map<String, Fragment> mFragments = new HashMap<>(3);
...
@Override
public Fragment getItem(int index) {
...
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// super calls getItem() if fragment is not already instantiated
Fragment fragment = (Fragment) super.instantiateItem(container, position);
mFragments.put(fragment.getClass().getSimpleName(), fragment);
return fragment;
}
public Fragment getFragment(String name) {
return mFragments.get(name);
}
@Override
public int getCount() {
return 3;
}
通过上述更改,您的 GetPlayer()
实施现在将变为
@Override
public void GetPlayer() {
createRoundfragmentTab createRoundfragmentTab = (createRoundfragmentTab)
((fragmentPageAdapter) mAdapter).getFragment("createRoundfragmentTab");
createRoundfragmentTab.makeRandomFirstRound(players);
}
要更详细地了解此方法,请阅读 ViewPager and fragments — what's the right way to store fragment's state?。
顺便说一句,也请看看Oracle推荐的Java naming conventions。长话短说,您的 class 名称需要以大写字母开头,方法名称则相反。遵循这些约定将使您的代码更易于阅读,从而更易于理解。目前,您的所有 class 名称对经验丰富的 Java 开发人员都显示为变量名称。
所以我想创建 3 个选项卡,每个选项卡都各不相同。 xml 我已经涵盖了。但不是如何在不使我的应用程序崩溃的情况下创建选项卡。
我已经实现了带有viewpage的滑动标签。
http://developer.android.com/training/implementing-navigation/lateral.html http://www.androidhive.info/2013/10/android-tab-layout-with-swipeable-views-1/
和一部分 http://www.java2s.com/Code/Android/UI/Demonstrateshowfragmentscanparticipateintheoptionsmenu.htm
当我尝试转到下一个选项卡时(滑动确实没问题)我收到错误消息:
07-08 22:07:57.414: E/AndroidRuntime(6865): FATAL EXCEPTION: main
07-08 22:07:57.414: E/AndroidRuntime(6865): Process: com.cyberdog.magiceasydraft, PID: 6865
07-08 22:07:57.414: E/AndroidRuntime(6865): java.lang.NullPointerException: Attempt to invoke virtual method 'void android.support.v4.view.ViewPager.setCurrentItem(int)' on a null object reference
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.cyberdog.magiceasydraft.addPlayersfragmentTab.doPositiveClick(addPlayersfragmentTab.java:113)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.cyberdog.magiceasydraft.addPlayersfragmentTab$MyAlertDialogFragment.onClick(addPlayersfragmentTab.java:165)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.app.AlertController$ButtonHandler.handleMessage(AlertController.java:160)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.os.Handler.dispatchMessage(Handler.java:102)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.os.Looper.loop(Looper.java:135)
07-08 22:07:57.414: E/AndroidRuntime(6865): at android.app.ActivityThread.main(ActivityThread.java:5274)
07-08 22:07:57.414: E/AndroidRuntime(6865): at java.lang.reflect.Method.invoke(Native Method)
07-08 22:07:57.414: E/AndroidRuntime(6865): at java.lang.reflect.Method.invoke(Method.java:372)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909)
07-08 22:07:57.414: E/AndroidRuntime(6865): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
所以..我做错了什么?我可以看到对我创建的圆形片段有一个空引用......但我不知道如何解决这个问题。这是我第一次使用片段和选项卡。
代码: 主要 activity:
public class CreateDraft extends FragmentActivity implements
ActionBar.TabListener {
private ViewPager viewPager;
private fragmentPageAdapter mAdapter;
private ActionBar actionBar;
private Fragment addPlayer, createRound,score;
private String[] tabs = { "Add players", "Create round", "Score" };
public static final String CuSToM_FRAGMENT_KEY ="ADD_PLAYER_TAB";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_create_draft);
viewPager = (ViewPager) findViewById(R.id.activity_viewpager_main);
actionBar = getActionBar();
mAdapter = new fragmentPageAdapter(getSupportFragmentManager());
viewPager.setAdapter(mAdapter);
actionBar.setHomeButtonEnabled(false);
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
if(savedInstanceState == null){
FragmentManager fm = getSupportFragmentManager();
android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
addPlayer = fm.findFragmentByTag("Add Players");
if(addPlayer == null){
addPlayer = new addPlayersfragmentTab();
ft.add(addPlayer, "Add players");
}
createRound = fm.findFragmentByTag("Create round");
if(createRound == null){
createRound = new createRoundfragmentTab();
ft.add(createRound, "Create round");
}
score = fm.findFragmentByTag("Score");
if(score == null){
score = new scoreResultfragmentTab();
ft.add(score, "Score");
}
ft.commit();
}
//
for (String tab_name : tabs) {
actionBar.addTab(actionBar.newTab().setText(tab_name)
.setTabListener(this));
}
viewPager.setOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
public void onPageSelected(int position) {
// on changing the page
// make respected tab selected
actionBar.setSelectedNavigationItem(position);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
}
public void passBundleToFragment(int position){
if(true){
}
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
// on tab selected
// show respected fragment view
viewPager.setCurrentItem(tab.getPosition());
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
View focus = getCurrentFocus();
if (focus != null) {
hiddenKeyboard(focus);
}
}
private void hiddenKeyboard(View v) {
InputMethodManager keyboard = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
keyboard.hideSoftInputFromWindow(v.getWindowToken(), 0);
}
}
其中一个片段(其他的还没有包含太多代码):
public class addPlayersfragmentTab extends Fragment {
private Button addPlayer, createDraft;
private EditText evAddPlayer;
private ViewPager viewPager;
private List<Player> players;
private ListView lvAddedPlayers;
ListAdapter adapter;
private boolean buttonCreateDraftPressed= false;
public boolean isButtonCreateDraftPressed() {
return buttonCreateDraftPressed;
}
public void setButtonCreateDraftPressed(boolean buttonCreateDraftPressed) {
this.buttonCreateDraftPressed = buttonCreateDraftPressed;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.draft_adding_players,
container, false);
initialiseEditAndText(rootView);
players = new ArrayList<Player>();
lvAddedPlayers = (ListView) rootView.findViewById(
R.id.lv_players_adding);
adapter = new ListAdapter(rootView.getContext(), players);
lvAddedPlayers.setAdapter(adapter);
addPlayer = (Button) rootView.findViewById(R.id.button_total_player);
createDraft = (Button) rootView.findViewById(R.id.button_create_draft);
addPlayer.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Player player = new Player(evAddPlayer.getText().toString());
players.add(player);
adapter.notifyDataSetChanged();
InputMethodManager imm = (InputMethodManager) getActivity()
.getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(getView().getWindowToken(), 0);
}
});
createDraft.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (adapter != null && players != null) {
createdraft(players.size());
} else {
Toast.makeText(getActivity(),
"Add minimal 3 players to start the draft.",
Toast.LENGTH_LONG).show();
}
}
});
return rootView;
}
public void showDialog(){
DialogFragment newFragment = new MyAlertDialogFragment().newInstance(R.string.recreate_draft);
newFragment.show(getFragmentManager(), "dialog");
}
public void doPositiveClick(){
viewPager.setCurrentItem(1);
}
public void doNegativeClick(){
}
public int getTotalPlayers() {
return players.size();
}
public List<Player> getPlayersNames() {
return players;
}
public void initialiseEditAndText(View rootView) {
evAddPlayer = (EditText) rootView.findViewById(R.id.et_player_name);
}
public void createdraft(int totalplayers) {
if (totalplayers >= 3 && totalplayers <= 16) {
showDialog();
} else {
Toast.makeText(getActivity(),
"Minimum of 3 and maximum of 16 players.",
Toast.LENGTH_LONG).show();
}
}
public class MyAlertDialogFragment extends DialogFragment{
public MyAlertDialogFragment newInstance(int title){
MyAlertDialogFragment frag = new MyAlertDialogFragment();
Bundle args = new Bundle();
args.putInt("title", title);
frag.setArguments(args);
return frag;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
int title = getArguments().getInt("title");
return new AlertDialog.Builder(getActivity())
.setIcon(R.drawable.abc_ic_search)
.setTitle(title)
.setPositiveButton("R.string.alert_dialog_ok",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addPlayersfragmentTab.this.doPositiveClick();
}
}
)
.setNegativeButton("R.string.alert_dialog_cancel",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
addPlayersfragmentTab.this.doNegativeClick();
}
}
)
.create();
}
}
}
编辑:
页面适配器:
public fragmentPageAdapter(FragmentManager fm) {
super(fm);
// TODO Auto-generated constructor stub
}
@Override
public Fragment getItem(int index) {
switch (index) {
case 0:
// Top Rated fragment activity
return new addPlayersfragmentTab();
case 1:
// Games fragment activity
return new createRoundfragmentTab();
case 2:
// Movies fragment activity
return new scoreResultfragmentTab();
}
return null;
}
@Override
public int getCount() {
// TODO Auto-generated method stub
return 3;
}
}
编辑 2:
我跟随数据传递到 activity,这确实有效,但是如果我想从 activity 传递数据(从 addPlayerTab 获取数据)我得到又是一个空引用,这次我认为是因为 id 是错误的。但我的布局文件不使用 .那我怎么找到片段呢?
代码: addPlayerTab的接口实现:
@Override
public void onButtonClickCreateRound(int position, List<Player> players) {
viewPager.setCurrentItem(position);
this.players = players;
GetPlayer();
}
addPlayerTab 中的代码:
public interface GoToCreateRoundListener{
public void onButtonClickCreateRound(int position, List<Player> players);
}
public void onAttach(Activity activity){
super.onAttach(activity);
try{
goCreateRound = (GoToCreateRoundListener)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()+" must implement GoToRoundListener");
}
}
public void createdraft(int totalplayers) {
if (totalplayers >= 3 && totalplayers <= 16) {
goCreateRound.onButtonClickCreateRound(1, players);
} else {
Toast.makeText(getActivity(),
"Minimum of 3 and maximum of 16 players.",
Toast.LENGTH_LONG).show();
}
}
这是将数据传递给createroundtab的接口实现:
@Override
public void GetPlayer() {
createRoundfragmentTab createRoundfragmentTab = (createRoundfragmentTab)getSupportFragmentManager().findFragmentById(R.layout.create_round);
createRoundfragmentTab.makeRandomFirstRound(players);
}
createroundTab 中的代码:
public interface GetPlayersFromAddPlayersListener{
public void GetPlayer();
}
public void onAttach(Activity activity){
super.onAttach(activity);
try{
getPlayers = (GetPlayersFromAddPlayersListener)activity;
}catch(ClassCastException e){
throw new ClassCastException(activity.toString()+" must implement GetPlayersFromAddPlayersListener");
}
}
您没有初始化片段的 viewPager
字段 (addPlayersfragmentTab.viewPager
)。这就是你得到 NullPointerException 的原因。
您可以在 activity 中执行 getViewPager()
方法,然后从片段中调用它,即 ((CreateDraft) getActivity()).getViewPager().setCurrentItem(1)
我已经在上面分享了关于 Fragment
实例化的观点,所以我将再次引用我自己的话。
That whole
if (savedInstance == null)
block is not required becauseFragment
instantiation is the job of yourPagerAdapter
. TheViewPager
will callPagerAdapter#getItem()
when it sees fit to.
虽然,很明显 NullPointerException
是由 addPlayersfragmentTab
中未初始化的 ViewPager
引用引起的,在创建时将视图寻呼机传递给片段的整个方法或者通过 getter 访问它的片段是错误的。
原因是片段是您的 UI 一部分的独立可重用实现,因此它不应与托管它的 activity 耦合。一旦你将它与你的视图寻呼机结合起来,你就再也不能在任何其他正常的 activity 中托管这个片段了。简而言之,该片段不再保持可重用状态。
那么,片段应该如何与其宿主通信 activity?好吧,使用 回调接口 。这是来自 Android 开发者官方网站的简短教程:Communicating with Other Fragments 但它同样适用于请求 activity 代表片段执行任何操作。
在您的情况下,您会通知主要 activity 用户在警报对话框中按下了“确定”,activity 将通过使用查看寻呼机移至下一个选项卡来对此做出响应。
通常当您想再次抓住 Fragment
时,您可以使用 findFragmentById()
或它的带有 findFragmentByTag()
的自定义标签。但是,整个 ViewPager
及其 PagerAdapter
不会向我们公开这些属性。
因此,要启用片段查找,您需要在 PagerAdapter
中保存对它们的引用。大致如下。
Map<String, Fragment> mFragments = new HashMap<>(3);
...
@Override
public Fragment getItem(int index) {
...
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
// super calls getItem() if fragment is not already instantiated
Fragment fragment = (Fragment) super.instantiateItem(container, position);
mFragments.put(fragment.getClass().getSimpleName(), fragment);
return fragment;
}
public Fragment getFragment(String name) {
return mFragments.get(name);
}
@Override
public int getCount() {
return 3;
}
通过上述更改,您的 GetPlayer()
实施现在将变为
@Override
public void GetPlayer() {
createRoundfragmentTab createRoundfragmentTab = (createRoundfragmentTab)
((fragmentPageAdapter) mAdapter).getFragment("createRoundfragmentTab");
createRoundfragmentTab.makeRandomFirstRound(players);
}
要更详细地了解此方法,请阅读 ViewPager and fragments — what's the right way to store fragment's state?。
顺便说一句,也请看看Oracle推荐的Java naming conventions。长话短说,您的 class 名称需要以大写字母开头,方法名称则相反。遵循这些约定将使您的代码更易于阅读,从而更易于理解。目前,您的所有 class 名称对经验丰富的 Java 开发人员都显示为变量名称。