我正在尝试让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);
}
}
}
我看过以下内容。
答案 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()
可让您的上/下视图对确切的拖动距离作出反应。
两个警告:
LayoutParams
添加边距。您使用它们不断修改比例的方式将导致拖动跳跃。如果您需要插入ListView
内容,请使用填充或其他嵌套容器。LayoutParams
时都会触发一次)。这可能适用于非常简单的布局,但如果您的视图变得更加复杂,您可能会看到旧硬件的性能受损。