View 体系
View 体系 · androidx.core
CustomView:自定义 View 辅助Core 1.20.0-alpha01
ViewDragHelper 实现拖拽,PoolingContainer 实现 View 复用回收。
最后更新 2026-08-01
复制即用
用 ViewDragHelper 实现可拖拽子 View(含松手吸附回位):
import androidx.customview.widget.ViewDragHelper;
public class DragLayout extends FrameLayout {
private final ViewDragHelper dragHelper;
public DragLayout(Context context) {
super(context);
dragHelper = ViewDragHelper.create(this, 1f, new ViewDragHelper.Callback() {
@Override
public boolean tryCaptureView(View child, int pointerId) {
return child == draggableView;
}
@Override
public int clampViewPositionHorizontal(View child, int left, int dx) {
return Math.max(0, Math.min(getWidth() - child.getWidth(), left));
}
@Override
public int clampViewPositionVertical(View child, int top, int dy) {
return Math.max(0, Math.min(getHeight() - child.getHeight(), top));
}
@Override
public void onViewReleased(View releasedChild, float xvel, float yvel) {
// 松手后吸附回原位
dragHelper.settleCapturedViewAt(0, 0);
invalidate();
}
});
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return dragHelper.shouldInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
dragHelper.processTouchEvent(ev);
return true;
}
@Override
public void computeScroll() {
if (dragHelper.continueSettling(true)) {
invalidate();
}
}
}View 复用(PoolingContainer):
import androidx.customview.poolingcontainer.setPoolingContainerListener
// 在容器内复用 View 时,监听回收/复用事件
view.setPoolingContainerListener { isAcquired ->
if (isAcquired) resetViewState() else releaseResources()
}常见陷阱
- 忘转发触摸事件:
shouldInterceptTouchEvent/processTouchEvent不接,拖拽不生效。 - 忘 computeScroll:
settleCapturedViewAt后要computeScroll+continueSettling。 - clamp 返回越界值:
clampViewPosition*必须限制在合法范围。 - 先想 Compose:自定义 View 前确认 Compose 是否更合适。
要点
ViewDragHelper.create(parent, sensitivity, callback)封装拖拽:tryCaptureView决定可拖对象,clamp*限制范围。- 需要手动把触摸事件转发给 helper(
shouldInterceptTouchEvent/processTouchEvent)。 PoolingContainer用于 View 池场景(如列表复用),监听acquired/released重置状态。- 实现自定义 View 前先确认 Compose 是否更合适(Compose 无 View 体系负担)。