Как заставить ViewDragHelper работать над активностью со скрытой навигационной панелью

#android

Вопрос:

У меня проблема. Я пытаюсь научиться использовать ViewDragHelper, но у меня возникают проблемы с тем, чтобы заставить его работать над действием, в котором навигационная панель скрыта с помощью:

 final int uiOptions = View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_STABLE;
getWindow().getDecorView().setSystemUiVisibility(uiOptions);
 

Если я не установлю

 WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
 

Панель навигации появится при касании события.

Мой драглайут выглядит так:

 public class DragLayout extends FrameLayout {
    private ViewDragHelper viewDragHelper;
    private final Activity activity;
    private final View view;

    public DragLayout(@NonNull final Context context, final Activity activity) {
        super(context);
        init();
        this.activity = activity;
        final ViewGroup decor = (ViewGroup) activity.getWindow().getDecorView();
        final View content = decor.getChildAt(0);
        decor.removeView(content);
        this.view = content;
        addView(content);
        decor.addView(this);
    }

    private void init() {
        this.viewDragHelper = ViewDragHelper.create(this, 1.0f, new ViewDragHelper.Callback() {
            @Override
            public boolean tryCaptureView(final View child, final int pointerId) {
                return false;
            }

            @Override
            public int clampViewPositionVertical(final View child, final int top, final int dy) {
                return Math.max(0, top);
            }

            @Override
            public void onViewReleased(final View releasedChild, final float xvel, final float yvel) {
                final int top = releasedChild.getTop();
                if (top > getHeight() / 2) {
                    if (DragLayout.this.activity != null) {
                        DragLayout.this.activity.finish();
                    }
                } else {
                    // resets the view
                    DragLayout.this.viewDragHelper.settleCapturedViewAt(0, 0);
                }
                invalidate();
            }

            @Override
            public void onEdgeDragStarted(final int edgeFlags, final int pointerId) {
                DragLayout.this.viewDragHelper.captureChildView(DragLayout.this.view, pointerId);
            }
        });
        this.viewDragHelper.setEdgeTrackingEnabled(ViewDragHelper.EDGE_ALL);
    }


    @Override
    public boolean onInterceptTouchEvent(final MotionEvent ev) {
        return this.viewDragHelper.shouldInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(final MotionEvent event) {
        this.viewDragHelper.processTouchEvent(event);
        return true;
    }

    @Override
    public void computeScroll() {
        if (this.viewDragHelper.continueSettling(true)) {
            invalidate();
        }
    }

}
 

Как вы можете видеть, я включил отслеживание на EDGE_ALL. Он работает с левым и правым краем, но не сверху и снизу! Если я позволю навигационной панели отображаться, она будет работать от края между навигационной панелью и содержимым.

В чем моя ошибка? Нужно ли мне скрывать навигационную панель другим способом?

Ошибка:

     @Override
    public int clampViewPositionVertical(final View child, final int top, final int dy) {
        return Math.min(top, 0);
    }
 

Это позволяет перетаскивать изображение снизу вверх, не прерываясь навигационной панелью.

Ответ №1:

Попробуйте : https://developer.android.com/training/system-ui/immersive.html

Класс деятельности:

 private int currentApiVersion;

@Override
@SuppressLint("NewApi")
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);

    currentApiVersion = android.os.Build.VERSION.SDK_INT;

    final int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
        | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
        | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
        | View.SYSTEM_UI_FLAG_FULLSCREEN
        | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;

    // This work only for android 4.4 
    if(currentApiVersion >= Build.VERSION_CODES.KITKAT)
    {

        getWindow().getDecorView().setSystemUiVisibility(flags);

        // Code below is to handle presses of Volume up or Volume down.
        // Without this, after pressing volume buttons, the navigation bar will
        // show up and won't hide
        final View decorView = getWindow().getDecorView();
        decorView
            .setOnSystemUiVisibilityChangeListener(new View.OnSystemUiVisibilityChangeListener()
            {

                @Override
                public void onSystemUiVisibilityChange(int visibility)
                {
                    if((visibility amp; View.SYSTEM_UI_FLAG_FULLSCREEN) == 0)
                    {
                        decorView.setSystemUiVisibility(flags);
                    }
                }
            });
    }

}


@SuppressLint("NewApi")
@Override
public void onWindowFocusChanged(boolean hasFocus)
{
    super.onWindowFocusChanged(hasFocus);
    if(currentApiVersion >= Build.VERSION_CODES.KITKAT amp;amp; hasFocus)
    {
        getWindow().getDecorView().setSystemUiVisibility(
            View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                | View.SYSTEM_UI_FLAG_FULLSCREEN
                | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
    }
}
 

Вы можете попробовать это и удачи 😉

Комментарии:

1. Я мог бы понять это через пару часов. Проблема была не в пользовательском интерфейсе, а в clampViewPositionVertical.