基于模板IntelliJ Android应用程序,我试图在按下TextView时创建一个从一个片段滑动到另一个片段的活动。
但是,我的活动中的onTouch
无法找到原始片段。当我触摸相关的TextView时,应用程序崩溃,并且日志消息指示NullPointerException(见下文)。
从onTouch事件中检索现有片段的正确方法是什么?
以下是代码:
public class MainActivity extends FragmentActivity implements View.OnTouchListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
if (view.getId() == R.id.textView2) {
FragmentManager fm = getSupportFragmentManager();
Fragment originalFragment = fm.findFragmentById(R.layout.fragment_main);
System.out.println(("===============\noriginal Fragment is ") +
(originalFragment == null ? "" : "not ") +
"null\n===============");
fm.beginTransaction() // <-- line 84
.setCustomAnimations(R.animator.slide_in_right,
R.animator.slide_out_right,
R.animator.slide_in_right,
R.animator.slide_out_right)
.replace(originalFragment.getId(), Fragment
.instantiate(this, AddQuestionFragment.class.getName()),
TAG)
.addToBackStack(null).commit();
}
}
return false;
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView v = (TextView) rootView.findViewById(R.id.textView2);
TextView v1 = (TextView) rootView.findViewById(R.id.textView3);
View.OnTouchListener activityAsListener = (View.OnTouchListener) getActivity();
v.setOnTouchListener(activityAsListener);
v1.setOnTouchListener(activityAsListener);
return rootView;
}
}
public static class AddQuestionFragment extends Fragment {
public AddQuestionFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_add_question, container, false);
return rootView;
}
}
}
RES /布局/ main.xml中
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame" />
RES /布局/ fragment_main.xml
<RelativeLayout 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"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context=".MainActivity$PlaceholderFragment">
<TextView
android:text="@string/hello_world"
android:layout_width="wrap_content"
android:layout_height="wrap_content" android:id="@+id/textView"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_below="@+id/textView"
android:layout_alignParentLeft="true" android:layout_alignParentStart="true">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="@string/add_question_title"
android:id="@+id/textView2"/>
</LinearLayout>
</RelativeLayout>
和日志消息:
01-08 17:39:42.904 6555-6555/com.scubbo.lifetracker.app I/art﹕ Late-enabling -Xcheck:jni
01-08 17:40:08.125 6555-6555/com.scubbo.lifetracker.app I/System.out﹕ ===============
01-08 17:40:08.125 6555-6555/com.scubbo.lifetracker.app I/System.out﹕ original Fragment is null
01-08 17:40:08.125 6555-6555/com.scubbo.lifetracker.app I/System.out﹕ ===============
01-08 17:40:08.126 6555-6555/com.scubbo.lifetracker.app E/InputEventReceiver﹕ Exception dispatching input event.
01-08 17:40:08.126 6555-6555/com.scubbo.lifetracker.app E/MessageQueue-JNI﹕ Exception in MessageQueue callback: handleReceiveCallback
01-08 17:40:08.136 6555-6555/com.scubbo.lifetracker.app E/MessageQueue-JNI﹕ java.lang.NullPointerException: Attempt to invoke virtual method 'int android.support.v4.app.Fragment.getId()' on a null object reference
at com.scubbo.lifetracker.app.MainActivity.onTouch(MainActivity.java:84)
at android.view.View.dispatchTouchEvent(View.java:8382)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2314)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1692)
at android.app.Activity.dispatchTouchEvent(Activity.java:2739)
at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.dispatchTouchEvent(ActionBarActivityDelegateICS.java:268)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2275)
at android.view.View.dispatchPointerEvent(View.java:8578)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4021)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3887)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5701)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5675)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5646)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5791)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:143)
at android.os.Looper.loop(Looper.java:122)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
01-08 17:40:08.137 6555-6555/com.scubbo.lifetracker.app D/AndroidRuntime﹕ Shutting down VM
--------- beginning of crash
01-08 17:40:08.138 6555-6555/com.scubbo.lifetracker.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.scubbo.lifetracker.app, PID: 6555
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.support.v4.app.Fragment.getId()' on a null object reference
at com.scubbo.lifetracker.app.MainActivity.onTouch(MainActivity.java:84)
at android.view.View.dispatchTouchEvent(View.java:8382)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:2430)
at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:2119)
at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:2314)
at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1692)
at android.app.Activity.dispatchTouchEvent(Activity.java:2739)
at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.dispatchTouchEvent(ActionBarActivityDelegateICS.java:268)
at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2275)
at android.view.View.dispatchPointerEvent(View.java:8578)
at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:4021)
at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3887)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3578)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3635)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3502)
at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3468)
at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3476)
at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3449)
at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5701)
at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5675)
at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5646)
at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5791)
at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)
at android.os.MessageQueue.nativePollOnce(Native Method)
at android.os.MessageQueue.next(MessageQueue.java:143)
at android.os.Looper.loop(Looper.java:122)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
01-08 17:40:10.095 6555-6555/com.scubbo.lifetracker.app I/Process﹕ Sending signal. PID: 6555 SIG: 9
[...]
PlaceholderFragment fg = new PlaceholderFragment();
System.out.println("id of fg is " + ((Integer)fg.getId()).toString());
getSupportFragmentManager().beginTransaction()
.add(R.id.container, fg)
.commit();
[...]
FragmentManager fm = getSupportFragmentManager();
System.out.println("Searching for fragment with id " + ((Integer) R.layout.fragment_main).toString());
Fragment originalFragment = fm.findFragmentById(R.layout.fragment_main);
[...]
我得到了:
01-08 18:11:40.873 20001-20001/com.scubbo.lifetracker.app I/System.out﹕ id of fg is 0
01-08 18:12:04.395 20001-20001/com.scubbo.lifetracker.app I/System.out﹕ Searching for fragment with id 2130903066
我很惊讶地看到原始Fragment的id为0(为什么会这样?),但我想这可以解释为什么找不到它 - 0 != 2130903066
。不过,我仍然不知道如何最好地获取原始片段。
This answer建议我应该R.id.<foo>
而不是R.layout.<bar>
引用片段 - 但它也希望片段定义以<fragment
开头,而模板由IntelliJ让他们在媒体资源中启动 (例如<RelativeLayout
)。是时候进行一些修补......
答案 0 :(得分:2)
尝试调用虚方法'int 空对象引用上的android.support.v4.app.Fragment.getId()'
因为originalFragment
为空。
如果您想通过调用add(int containerViewId, Fragment fragment, String tag)
来获取Fragment的ID,请使用add
版本的findFragmentById
方法。
答案 1 :(得分:2)
您还可以使用普通的onClickListener并在其中启动新的片段替换(类似于您已在onCreate中显示PlaceholderFragment的方式)
public class MainActivity extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
public static class PlaceholderFragment extends Fragment {
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView v = (TextView) rootView.findViewById(R.id.textView2);
TextView v1 = (TextView) rootView.findViewById(R.id.textView3);
View.OnClickListener onClickListener = new View.OnClickListener() {
@Override
public void onClick(View v) {
getActivity().getSupportFragmentManager()
.beginTransaction() // <-- line 84
.setCustomAnimations(R.animator.slide_in_right,
R.animator.slide_out_right,
R.animator.slide_in_right,
R.animator.slide_out_right)
.replace(R.id.container, new AddQuestionFragment(), "TAG_AddQuestionFragment")
.addToBackStack(null).commit();
}
};
v.setOnClickListener(onClickListener);
v1.setOnClickListener(onClickListener);
return rootView;
}
}
public static class AddQuestionFragment extends Fragment {
public AddQuestionFragment() {}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_add_question, container, false);
return rootView;
}
}
}
答案 2 :(得分:0)
破解了!由于ID具有上述意外行为,我不得不通过Tag搜索。以下作品:
[...]
if (savedInstanceState == null) {
PlaceholderFragment fg = new PlaceholderFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.container, fg, MAIN_FRAGMENT_TAG)
.commit();
}
[...]
Fragment originalFragment = fm.findFragmentByTag(MAIN_FRAGMENT_TAG);
Fragment f = fm.findFragmentByTag(TAG);
fm.beginTransaction()
.setCustomAnimations(R.animator.slide_in_right,
R.animator.slide_out_left,
R.animator.slide_in_left,
R.animator.slide_out_right)
.replace(originalFragment.getId(),
Fragment.instantiate(this, AddQuestionFragment.class.getName()),
TAG)
.addToBackStack(null).commit();