查看Drag Helper帮助器

时间:2016-01-25 06:59:01

标签: java android viewdraghelper

我正在尝试让ViewDragHelper使用垂直LinearLayout, - 容器 - 其中

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

作为儿童的观点。

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

以下是Container 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?

1 个答案:

答案 0 :(得分:1)

你的ViewDragHelper有点偏。具体来说,您错过了clampViewPositionVertical()覆盖,这是完全拖动视图所必需的。现在,你的ViewDragHelper实际上没有工作。您可能正在进行一些动作,因为您正在为每个LayoutParams直接操纵onTouchEvent(),这也会导致一些问题。

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

@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);
    }
}

这会将“标题视图”的拖动范围设置为在容器视图的顶部和底部之间自由移动(将其夹紧以使其不会离开屏幕)。它本身只会移动标题视图。将LayoutParams代码移至onViewPositionChanged()可让您的上/下视图对确切的拖动距离作出反应。

两个警告:

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