java - 查看 Drag Helper 助手

标签 java android viewdraghelper

我正在尝试让 ViewDragHelper 与垂直 LinearLayout 一起使用, - 容器 - 具有

A ---- List View
B ---- horizontal linear layout 
C ---- Support Map Fragment

作为 child 的观点。

A 具有 layout_height="0dp"。向下拉 B,应按比例增加 A 的高度,从而显示 ListView 上的内容,从而在此过程中自动重新定位 B 并调整 C 的大小。

以下是容器LinearLayout的代码。

public class MyLinearLayout extends LinearLayout {

private LinearLayout headerLayout;
private ListView filtersListView;

private ViewDragHelper viewDragHelper;
private int MARGIN;

public MyLinearLayout (Context context) {
    super(context);
    init();
}

public MyLinearLayout (Context context, AttributeSet attrs) {
    super(context, attrs);
    init();
}

public MyLinearLayout (Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
    init();
}

private void init() {
    viewDragHelper = ViewDragHelper.create(this, 1, new DragHelperCallback());
    float GESTURE_THRESHOLD_DP = 10.0f;
    float scale = getResources().getDisplayMetrics().density;

    MARGIN = (int) (GESTURE_THRESHOLD_DP * scale + 0.5f);
}

@Override
protected void onFinishInflate() {
    Log.i("Places", "onFinishInflate");
    super.onFinishInflate();

    headerLayout = (LinearLayout) findViewById(R.id.header);
    filtersListView = (ListView) findViewById(R.id.filters_list);
}

@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
    Log.i("Places", "onInterceptTouchEvent");
    return viewDragHelper.shouldInterceptTouchEvent(ev);
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    Log.i("Places", "onTouchEvent");
    viewDragHelper.processTouchEvent(event);

    LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, (int) event.getRawY());
    layoutParams.setMargins(MARGIN, MARGIN, MARGIN, MARGIN);
    filtersListView.setLayoutParams(layoutParams);

    return true;
}

private class DragHelperCallback extends ViewDragHelper.Callback {

    @Override
    public boolean tryCaptureView(View child, int pointerId) {
        Log.i("Places", "tryCaptureView " + (child == headerLayout));
        return child == headerLayout;
    }

    @Override
    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
        Log.i("Places", "onViewPositionChanged " + changedView.getClass().getName());
        super.onViewPositionChanged(changedView, left, top, dx, dy);
    }

    @Override
    public void onViewReleased(View releasedChild, float xvel, float yvel) {
        Log.i("Places", "onViewReleased " + releasedChild.getClass().getName());
        super.onViewReleased(releasedChild, xvel, yvel);
    }
}
}

我查看了以下内容。

ViewDragHelper: how to use it?

最佳答案

你的ViewDragHelper有点不对劲。具体来说,您缺少 clampViewPositionVertical() 覆盖,这是启用 View 拖动所必需的。现在,您的 ViewDragHelper 实际上没有执行任何操作。您可能会收到一些 Action ,因为您直接为每个 onTouchEvent() 操作 LayoutParams,这也会导致一些问题。

您可能希望回调代码看起来更像这样:

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

@Override
public boolean onTouchEvent(MotionEvent event) {
    viewDragHelper.processTouchEvent(event);

    return true;
}

private class DragHelperCallback extends ViewDragHelper.Callback {

    @Override
    public int clampViewPositionVertical(View child, int top, int dy) {
        //Never go below fully visible
        final int bottomBound = getHeight() - child.getHeight();
        //Never go above the top
        final int topBound = 0;

        return Math.max(Math.min(top, bottomBound), topBound);
    }

    @Override
    public boolean tryCaptureView(View child, int pointerId) {
        //Capture touches to the header view
        return child == headerLayout;
    }

    @Override
    public void onViewPositionChanged(View changedView, int left, int top, int dx, int dy) {
        if (dy == 0) return;

        //React to the position change of the header by modifying layout
        LinearLayout.LayoutParams layoutParams = (LayoutParams) filtersListView.getLayoutParams();
        layoutParams.height += dy;
        filtersListView.setLayoutParams(layoutParams);
    }
}

这将设置“标题 View ”的拖动范围,以便在容器 View 的顶部和底部之间自由移动(夹紧它,这样它就不会离开屏幕)。就其本身而言,这只会移动标题 View 。将 LayoutParams 代码移至 onViewPositionChanged() 中,让您的顶部/底部 View 对精确的拖动距离使用react。

两个警告:

  1. 不要向 LayoutParams 添加边距。您使用它们不断修改比例的方式将导致拖动跳跃。如果您需要插入 ListView 内容,请使用 padding 或其他嵌套容器。
  2. 像这样连续更改整个 View 的布局可能会非常昂贵(布局传递并不便宜,每次修改 LayoutParams 时都会触发一次)。这可能适用于非常简单的布局,但如果您的 View 变得更加复杂,您可能会发现旧硬件上的性能受到影响。

关于java - 查看 Drag Helper 助手,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34986752/

相关文章:

Android 搜索栏自定义拇指卡在开始

android - 在微调器上设置初始文本

android - 通知栏上的蓝牙配对请求?

android - 为什么使用 ViewDragHelper 拖动的 View 会重置到其在 layout() 上的原始位置?

java - 无法访问我的好友的好友计数

java - 返回二叉搜索树的高度

java - Spring 上的 Apache Shiro session 管理

java - 在类中创建和更改的类会更改原始类