android在fragment中实现onTouchEvent办法出现的java.lang.NullPointerException

来源:互联网 发布:淘宝店是怎么进货的 编辑:程序博客网 时间:2024/05/21 14:55
编译出现下面错误:
11-01 09:58:41.630: E/AndroidRuntime(5532): FATAL EXCEPTION: main11-01 09:58:41.630: E/AndroidRuntime(5532): Process: com.lynhsp, PID: 553211-01 09:58:41.630: E/AndroidRuntime(5532): java.lang.NullPointerException11-01 09:58:41.630: E/AndroidRuntime(5532): at com.lynhsp.ui.FragmentSearch$1.onTouchEvent(FragmentSearch.java:71)11-01 09:58:41.630: E/AndroidRuntime(5532): at com.lynhsp.ui.HspDeviceList.dispatchTouchEvent(HspDeviceList.java:243)11-01 09:58:41.630: E/AndroidRuntime(5532): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:2016)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.View.dispatchPointerEvent(View.java:7886)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$ViewPostImeInputStage.processPointerEvent(ViewRootImpl.java:3954)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$ViewPostImeInputStage.onProcess(ViewRootImpl.java:3833)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$AsyncInputStage.forward(ViewRootImpl.java:3525)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$AsyncInputStage.apply(ViewRootImpl.java:3582)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.onDeliverToNext(ViewRootImpl.java:3449)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.forward(ViewRootImpl.java:3418)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.apply(ViewRootImpl.java:3426)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$InputStage.deliver(ViewRootImpl.java:3399)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:5602)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:5582)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:5553)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:5682)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:185)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.os.MessageQueue.nativePollOnce(Native Method)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.os.MessageQueue.next(MessageQueue.java:138)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.os.Looper.loop(Looper.java:123)11-01 09:58:41.630: E/AndroidRuntime(5532): at android.app.ActivityThread.main(ActivityThread.java:5017)11-01 09:58:41.630: E/AndroidRuntime(5532): at java.lang.reflect.Method.invokeNative(Native Method)11-01 09:58:41.630: E/AndroidRuntime(5532): at java.lang.reflect.Method.invoke(Method.java:515)11-01 09:58:41.630: E/AndroidRuntime(5532): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)11-01 09:58:41.630: E/AndroidRuntime(5532): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)11-01 09:58:41.630: E/AndroidRuntime(5532): at dalvik.system.NativeStart.main(Native Method)

原因其实就是在onTouchEvent调用了:


imm.hideSoftInputFromWindow(getActivity().getWindowToken(), InputMethodManager.HIDE_NOT_ALWAYS);
上面第一个参数是fragment关联的activity的令牌,而我们当前显示的不是fragment,并非activity。所以,才会出现上面的异常。但是解决办法,并不是把getActivity改为this,原因是fragment不是一个activity,所以,无法调用getWindowToken()方法。
下面是我的解决办法:

当然,首先你要在fragment中实现onTouchEvent方法:

1.在关联的Activity中写一个接口如下:

 public interface MyTouchListener  {          public void onTouchEvent(MotionEvent event);  }  /**   * 提供给Fragment通过getActivity()方法来注册自己的触摸事件的方法   * @param listener   */  public void registerMyTouchListener(MyTouchListener listener)  {          myTouchListeners.add( listener );  }  public void unRegisterMyTouchListener(MyTouchListener listener)  {          myTouchListeners.remove( listener );  }  /**   * 分发触摸事件给所有注册了MyTouchListener的接口   */  @Override  public boolean dispatchTouchEvent(MotionEvent ev) {          // TODO Auto-generated method stub          for (MyTouchListener listener : myTouchListeners) {                         listener.onTouchEvent(ev);          }          return super.dispatchTouchEvent(ev);  }
2.然后在你的fragment中,定义如下
private MyTouchListener mTouchListener = new MyTouchListener() {        @Override        public void onTouchEvent(MotionEvent event) {                // TODO Auto-generated method stub                if(event.getAction() == MotionEvent.ACTION_UP){                        //逻辑处理                if(fragflag){                InputMethodManager imm=(InputMethodManager)                 getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);                //View view = getActivity().getWindow().peekDecorView();                System.out.println(imm.hideSoftInputFromWindow(searchtext.getWindowToken(), 0));                imm.hideSoftInputFromWindow(searchtext.getWindowToken(), 0);                                 }                }        }};

注意上面有个fragflag标志位,因为你的一个Activity中可能含有多个fragment。所以,为了避免所有fragment调用它,我通过在需要实现触摸的地方的onCreateView将其置为true。如下:
                @Overridepublic View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {                       fragflag=true;}
但是,一定要记得当该fragment销毁的时候,记得要fragflag设为false,否则其他fragment又可以继续用。

                   @Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();fragflag=false;}
当然还有记得你要注册一下你的OntouchEvent事件:
((HspDevice)this.getactivity()).registerMyTouchListener(mTouchListener);

其中HspDevice是你的关联的Activity的类名。

方法二:上面的方法中,其实不设置标志位也是可以的。直接调用unRegisterMyTouchListener(MyTouchListener listener),一样可以实现上面功能
@Overridepublic void onDestroy() {// TODO Auto-generated method stubsuper.onDestroy();//fragflag=false;((HspDeviceList)this.getActivity()).unRegisterMyTouchListener(mTouchListener);   Log.e("onDestroy", "unbindService");}


0 0