所以我想创建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$1.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)
那么......我在这里做错了什么?我可以看到我的创建圆片段有一个空引用...但我不知道如何解决这个问题。这是我第一次使用片段和标签。
代码: 主要活动:
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();
}
}
}
编辑:
pageadpter:
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:
我跟着将数据传递给活动,这确实有效,但是如果我想从活动传递数据(从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);
}
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");
}
}
答案 0 :(得分:1)
您没有初始化片段的viewPager
字段(addPlayersfragmentTab.viewPager
)。这就是你得到NullPointerException的原因。
您可以在活动中执行getViewPager()
方法,然后在片段中调用它,即((CreateDraft) getActivity()).getViewPager().setCurrentItem(1)
答案 1 :(得分:1)
我已经在上面的Fragment
实例中分享了我的观点,所以我再次引用自己。
不需要整个
if (savedInstance == null)
块,因为Fragment
实例化是PagerAdapter
的工作。如果ViewPager
认为合适,PagerAdapter#getItem()
会调用NullPointerException
。
尽管ViewPager
是由addPlayersfragmentTab
中未初始化的Fragment
引用引起的,但是将视图寻呼机传递给片段的整个方法相当明显在创建或通过getter访问它的片段是错误的。
原因是片段是UI的一部分的自包含可重用实现,因此它不应该与托管它的活动结合起来。将视图寻呼机与视图寻呼机耦合后,您再也无法在任何其他正常活动中托管此片段。简而言之,片段不再可以重复使用。
那么,一个片段应该如何与其主机活动进行通信?好吧,使用回调接口。以下是来自官方Android开发者网站的简短教程:Communicating with Other Fragments但是它可以用于请求活动代表片段执行任何操作。
在您的情况下,您会通知主要活动,用户在警告对话框中按了OK,活动将通过使用视图寻呼机移动到下一个选项卡来响应。
通常,当您想再次抓住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);
}
实施现在将变为
ALTER TABLE tblName AUTO_INCREMENT = 1000;
要详细了解此方法,请阅读ViewPager and fragments — what's the right way to store fragment's state?。
另外,请同时查看Oracle推荐的Java naming conventions。简而言之,您需要使用大写字母开始您的类名,并使用您的方法名称执行相反的操作。遵循这些约定将使您的代码更容易阅读,从而更容易理解。目前,所有类名都显示为经验丰富的Java开发人员的变量名。