片段中的onTouchEvent方法

问题描述

@H_502_0@我尝试在我的应用程序中的特定片段中实现Common Gestures检测机制。

@H_502_0@我已经实现了所有必需的onDown,onShowPress等方法。 手势检测器类已在onCreateView中启用。

@H_502_0@当用户执行这些手势之一时,应用程序应从也在此片段中实现的viewmodel实例调用转换方法

@H_502_0@问题在于重写onTouchEvent。 AndroidStudio向我发送错误消息,指出onTouchEvent不会覆盖任何方法

@H_502_0@我该如何解决这个问题?

@H_502_0@代码在这里

@H_502_0@片段:

public class SecondFragment extends Fragment  implements GestureDetector.OnGestureListener{

private Secondviewmodel mviewmodel;
private GestureDetectorCompat gDetector;
private final float rate = 3.14f;



public static SecondFragment newInstance() {
    return new SecondFragment();
}

@Override
public View onCreateView(@NonNull LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {
    gDetector = new GestureDetectorCompat(getActivity(),this);
    return inflater.inflate(R.layout.second_fragment,container,false);
}


@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mviewmodel = new viewmodelProvider(this).get(Secondviewmodel.class);




    TextView euroView = getView().findViewById(R.id.inEuro);
    TextView valueView = getView().findViewById(R.id.textView);
    Switch mSwitch = getView().findViewById(R.id.mySwitch);


    mSwitch.setonCheckedchangelistener(new CompoundButton.OnCheckedchangelistener() {
        @Override
        public void onCheckedChanged(CompoundButton compoundButton,boolean isChecked) {
            if (isChecked) {
                Navigation.findNavController(mSwitch).navigate(R.id.movetoMain);
            }
        }
    });

    final Observer<Float> valueObserver = new Observer<Float>() {
        @Override
        public void onChanged(@Nullable final Float myValue) {
            valueView.setText(myValue.toString());
        }
    };

    final Observer<Float> eurovalueObserver = new Observer<Float>() {
        @Override
        public void onChanged(Float myValue) {
            euroView.setText(myValue.toString());
        }
    };

    mviewmodel.getValue().observe(getViewLifecycleOwner(),valueObserver);
    mviewmodel.getEuroV().observe(getViewLifecycleOwner(),eurovalueObserver);
}


@Override
public void onStart(){
    super.onStart();
        mviewmodel.setValue(SecondFragmentArgs.fromBundle(getArguments()).getVal());
}

@Override
public boolean onDown(MotionEvent motionEvent) {

   mviewmodel.convertion();

    return false;
}

@Override
public void onShowPress(MotionEvent motionEvent) {

}

@Override
public boolean onSingleTapUp(MotionEvent motionEvent) {
    mviewmodel.convertion();
    return false;
}

@Override
public boolean onScroll(MotionEvent motionEvent,MotionEvent motionEvent1,float v,float v1) {
    mviewmodel.convertion();
    return false;
}

@Override
public void onLongPress(MotionEvent motionEvent) {

}

@Override
public boolean onFling(MotionEvent motionEvent,float v1) {
    mviewmodel.convertion();
    return false;
}
@Override
public boolean onTouchEvent(MotionEvent event) {
    this.gDetector.onTouchEvent(event);
    return getActivity().onTouchEvent(event);
}
@H_502_0@}

@H_502_0@ 更新

@H_502_0@ 具有onTouch方法解决方

@SuppressLint("ClickableViewAccessibility")
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mviewmodel = new viewmodelProvider(this).get(Secondviewmodel.class);
    secondFrag = getView().findViewById(R.id.ConstraintLayout);
    euroView = getView().findViewById(R.id.inEuro);
    valueView = getView().findViewById(R.id.textView);
    mSwitch = getView().findViewById(R.id.mySwitch);
    mSwitch.setonCheckedchangelistener(new CompoundButton.OnCheckedchangelistener() {

        @Override
        public void onCheckedChanged(CompoundButton compoundButton,boolean isChecked) {
            if (isChecked) {
                Navigation.findNavController(mSwitch).navigate(R.id.movetoMain);
            }
        }
    });
    secondFrag.setonTouchListener(new View.OnTouchListener() {
        GestureDetectorCompat gDetector = new GestureDetectorCompat(getActivity(),new GestureDetector.OnGestureListener() {

            @Override
            public boolean onDown(MotionEvent p1) {

                euroView.setText("true");

                return true;
            }

            @Override
            public void onShowPress(MotionEvent p1) {
                // Todo: Implement this method
            }

            @Override
            public boolean onSingleTapUp(MotionEvent p1) {
                euroView.setText("true");
                return true;
            }

            @Override
            public boolean onScroll(MotionEvent p1,MotionEvent p2,float p3,float p4) {
                euroView.setText("true");
                return true;
            }

            @Override
            public void onLongPress(MotionEvent p1) {
                // Todo: Implement this method
            }
            @Override
            public boolean onFling(MotionEvent p1,float p4) {
                // Todo: Implement this method
                return false;
            }
        });


        @Override
        public boolean onTouch(View view,MotionEvent motionEvent) {
            secondFrag.onTouchEvent(motionEvent);
            return true;
        }

    });
@H_502_0@主机活动的XML文件

<?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<fragment
    android:id="@+id/nav_host"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/nav_graph" />
    </androidx.constraintlayout.widget.ConstraintLayout>
@H_502_0@片段XML

<?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout 
 xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ConstraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondFragment">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="2ndFragmentWithviewmodel"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.497"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.456" />

<Switch
    android:id="@+id/mySwitch"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Switch"
    app:layout_constraintBottom_toTopOf="@+id/textView"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/inEuro"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="67dp"
    android:text="MyTextView"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/textView"
    app:layout_constraintVertical_bias="0.17000002" />

    </androidx.constraintlayout.widget.ConstraintLayout>

解决方法

首先,初始化您的父视图:

private FrameLayout parentView;
parentView = getView().findViewById(R.id.parent_view);

然后为其设置一个触摸侦听器:

parentView.setOnTouchListener( new View.OnTouchListener() {
                GestureDetectorCompat gDetector = new GestureDetectorCompat(getActivity(),new GestureDetector.OnGestureListener() {

                        @Override
                        public boolean onDown(MotionEvent p1) {
                            // TODO: Implement this method
                            return false;
                        }

                        @Override
                        public void onShowPress(MotionEvent p1) {
                            // TODO: Implement this method
                        }

                        @Override
                        public boolean onSingleTapUp(MotionEvent p1) {
                            // TODO: Implement this method
                            return false;
                        }

                        @Override
                        public boolean onScroll(MotionEvent p1,MotionEvent p2,float p3,float p4) {
                            // TODO: Implement this method
                            return false;
                        }

                        @Override
                        public void onLongPress(MotionEvent p1) {
                            // TODO: Implement this method
                        }

                        @Override
                        public boolean onFling(MotionEvent p1,float p4) {
                            // TODO: Implement this method
                            return false;
                        }
                        
                
            });
                @Override
                public boolean onTouch(View p1,MotionEvent p2) {
                    // TODO: Implement this method
                    return false;
                }
                
            
        });

主机活动的XML文件:

<?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout 
  xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/constraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<fragment
    android:id="@+id/nav_host"
    android:name="androidx.navigation.fragment.NavHostFragment"
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:defaultNavHost="true"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:navGraph="@navigation/nav_graph" />
    </androidx.constraintlayout.widget.ConstraintLayout>

片段XML

<?xml version="1.0" encoding="utf-8"?>
 <androidx.constraintlayout.widget.ConstraintLayout 
 xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/ConstraintLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".SecondFragment">

<TextView
    android:id="@+id/textView"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="2ndFragmentWithViewModel"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintHorizontal_bias="0.497"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintVertical_bias="0.456" />

<Switch
    android:id="@+id/mySwitch"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="Switch"
    app:layout_constraintBottom_toTopOf="@+id/textView"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<TextView
    android:id="@+id/inEuro"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="67dp"
    android:text="MyTextView"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/textView"
    app:layout_constraintVertical_bias="0.17000002" />

    </androidx.constraintlayout.widget.ConstraintLayout>
,

所以,最后我想出了一个解决方案。

为了实现特定的片段手势检测,例如向右,向左滑动等。我们大概不能使用GesturDetectorCompat类。作为替代,我发现编写了自己的CommonGestureDetector类。 内容如下:

  public class OnSwipeListener  implements View.OnTouchListener{

    private final GestureDetector gestureDetector;

    public OnSwipeListener(Context context){
        gestureDetector = new GestureDetector(context,new GestureListener());
    }

    @SuppressLint("ClickableViewAccessibility")
    @Override
    public boolean onTouch(View view,MotionEvent motionEvent) {
        return  gestureDetector.onTouchEvent(motionEvent);
    }

    private final class GestureListener extends  GestureDetector.SimpleOnGestureListener{

        private static final int SWIPE_VELOCITY_THRESHOLD = 100;
        private static final int SWIPE_THRESHOLD = 100;

        @Override
        public boolean onDown(MotionEvent e){return  true;}

    @Override
    public boolean onFling(MotionEvent e1,MotionEvent e2,float velocityX,float velocityY) {
        float diffY = e2.getY() - e1.getY();
        float diffX = e2.getX() - e1.getX();
        if (Math.abs(diffX) > Math.abs(diffY)) {
            if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
                if (diffX > 0) {
                    onSwipeRight();
                } else {
                    onSwipeLeft();
                }
            }
        } else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
            if (diffY > 0) {
                onSwipeBottom();
            } else {
                onSwipeTop();
            }
        }
        return true;
    }
   }
  public void onSwipeRight() {
     }

    public void onSwipeLeft() {
    }

    public void onSwipeTop() {
    }

    public void onSwipeBottom() {
    }

     }

它的来源来自这里:https://riptutorial.com/android/example/16543/swipe-detection

这是我们自己的GestureDetectorCompat实现,完全适合Fragments,并且我们仍保持项目类代码“干净整洁”。

它在我的应用中的外观:

public class MainFragment extends Fragment {

private MainViewModel mViewModel;

public static MainFragment newInstance() {
    return new MainFragment();
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,@Nullable ViewGroup container,@Nullable Bundle savedInstanceState) {


    View view =  inflater.inflate(R.layout.main_fragment,container,false);
    TextView textView = view.findViewById(R.id.testView);
   view.setOnTouchListener(new OnSwipeListener(getContext()){
   public void onSwipeTop()
    {
        textView.setText("top");
    }
   public void onSwipeRight()
    {textView.setText("right");}
    public void onSwipeLeft(){textView.setText("left");}
    public void onSwipeBottom(){textView.setText("bottom");}
});
    return view;


}

@SuppressLint("ClickableViewAccessibility")
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    mViewModel = new ViewModelProvider(this).get(MainViewModel.class);


    // TODO: Use the ViewModel
}

}

因此,如您所见,前面提到的类作为参数传递给我们的片段的OnActivityCreated方法中的setOnTouchListener,而花费最少的精力来编写它:)

我希望有一天能对某人有所帮助:)

非常感谢@AliEid对我的问题感兴趣。