您好,我正在使用自定义视图。此类有效,您可以用它来滑动在此布局中设置的Fragment,向下将其关闭。 这是我做过的第一个自定义视图。我真的不知道是否应该这样做,但是我面临一个问题。当framelayout包含一个片段,并且此片段也包含此framelayout时。我需要一种方法来正确地将事件分发给用户当前可见的视图。现在调用了两个dispatchTouchEvents()方法。但这不是我想要的。它应该只是从当前可见片段到用户的方法。因此,您将不得不滑动2次,才能同时关闭两次和一次,同时关闭两次。而且我认为我以错误的方式使用了android触摸系统。
public class DragableViewFragment extends FrameLayout
{
private AppCompatActivity activity;
private FragmentManager fragmentManager;
private static final float KILL_WEIGHT = 0.50f;
private static final float SENSITIVITY = 1.5f;
private static float IGNORED_CASE; //Pixels
public DragableViewFragment(Context context) {
super(context);
initDimensions(context);
}
public DragableViewFragment(Context context, AttributeSet attrs) {
super(context, attrs);
initDimensions(context);
}
public DragableViewFragment(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initDimensions(context);
}
@RequiresApi(21)
public DragableViewFragment(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
initDimensions(context);
}
private float max_height;
private float down_WeightPercent;
private void initDimensions(Context context)
{
if(context instanceof AppCompatActivity)
{
this.activity = (AppCompatActivity) context;
this.fragmentManager = this.activity.getSupportFragmentManager();
}
else
{
throw new IllegalArgumentException("View is not used in a Activity context.");
}
final ViewConfiguration configuration = ViewConfiguration.get(context);
DragableViewFragment.IGNORED_CASE = configuration.getScaledPagingTouchSlop();
WindowManager wm = (WindowManager) getContext().getSystemService(Context.WINDOW_SERVICE);
if(wm != null)
{
Display defaultDisplay = wm.getDefaultDisplay();
Point point = new Point();
defaultDisplay.getSize(point);
max_height = point.y;
down_WeightPercent = (float) (max_height - (max_height * DragableViewFragment.KILL_WEIGHT));
}
else
{
throw new NullPointerException("WindowManager_service NULL");
}
}
private boolean isDragging = false;
private float lastRawY = -1;
private float lastRawX = -1;
private float lastDragDistance;
private float firstTouchPos;
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
if(this.getChildCount() <= 0)
{
Log.i(getClass().getName(), "View is not moving: " + this.getId());
return super.dispatchTouchEvent(event);
}
if(event.getAction() == MotionEvent.ACTION_DOWN)
{
firstTouchPos = event.getRawY();
}
else if(event.getAction() == MotionEvent.ACTION_MOVE)
{
float dx = event.getRawX() - lastRawX;
float dy = event.getRawY() - lastRawY;
lastRawX = event.getRawX();
lastRawY = event.getRawY();
if (Math.abs(dx) > Math.abs(dy)) {
// Scrolling horizontally, so ignore
return super.dispatchTouchEvent(event);
}
float rawY = event.getRawY();
float dragDistance = (rawY - firstTouchPos) * DragableViewFragment.SENSITIVITY;
if(rawY > lastRawY) //Dragging up, set scale factor.
{
System.out.println("DRAGING DOWN: " + dragDistance);
}
else
{
System.out.println("DRAGING UP: " + dragDistance);
}
lastDragDistance = dragDistance;
if(dragDistance > IGNORED_CASE || isDragging)
{
if(!isDragging)
{
isDragging = true;
event.setAction(MotionEvent.ACTION_CANCEL);
super.dispatchTouchEvent(event);
}
if(dragDistance >= 0)
{
this.setTranslationY(dragDistance);
return true;
}
}
}
else if(event.getAction() == MotionEvent.ACTION_UP)
{
isDragging = false;
float calculatedPecentage = (max_height - (lastDragDistance));
if(calculatedPecentage <= down_WeightPercent)
{
if(fragmentManager != null)
{
this.animate().translationY(max_height).setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animation) {
}
@Override
public void onAnimationEnd(Animator animation) {
resetView();
}
@Override
public void onAnimationCancel(Animator animation) {
resetView();
}
@Override
public void onAnimationRepeat(Animator animation) {
}
});
fragmentManager.popBackStack();
}
else
{
throw new NullPointerException("FragmentManager not set in dragable view.");
}
}
else
{
this.animate().translationY(0);
}
}
return super.dispatchTouchEvent(event);
}
private void resetView()
{
this.setTranslationY(0f);
}
}