Android Studio使用Fragments分派触摸事件自定义视图

时间:2018-10-01 10:32:48

标签: android android-layout android-fragments android-touch-event

您好,我正在使用自定义视图。此类有效,您可以用它来滑动在此布局中设置的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);
    }
}

0 个答案:

没有答案