基于坐标设置子视图的最佳布局及Relative/FrameLayout实现方案
1. Layout Supporting (x,y) Coordinate Placement
You’re correct that AbsoluteLayout was deprecated starting from API 3, but it’s still fully functional if your specific use case demands it—there’s no technical barrier stopping you from using it, even though Android recommends avoiding it due to poor cross-screen adaptability.
The official deprecation reasoning matches what you noted:
AbsoluteLayout相较于其他布局更难适配不同移动设备屏幕尺寸,因为它通过精确的x(顶部)、y(左侧)坐标设置子视图(或组件)的位置,这种定位方式在多分辨率、多屏幕宽高比的环境中实用性较低。
If you want to avoid deprecated APIs but still need fixed coordinate control, FrameLayout can mimic this behavior by manually setting each child’s layout_marginLeft and layout_marginTop to your desired x and y values. It’s not as direct as AbsoluteLayout, but it achieves the same fixed-position effect without using deprecated tools.
2. Efficient Drag-and-Drop with RelativeLayout or FrameLayout
Between the two options, FrameLayout is the more efficient choice—it’s a lightweight container with minimal overhead, unlike RelativeLayout which handles complex relative positioning logic you won’t need here.
Here’s the most streamlined approach to implement draggable views:
Core Principles
- Use
translationXandtranslationYduring drag for smooth, high-performance movement (these properties adjust the view’s visual position without triggering expensive layout recalculations). - On drag release, update the view’s margins to lock in the final position (so the layout maintains the correct placement during screen rotations or remeasures).
Step-by-Step Implementation
- Set up the FrameLayout in your XML:
<FrameLayout android:id="@+id/container" android:layout_width="match_parent" android:layout_height="match_parent"> <!-- Example draggable view --> <TextView android:id="@+id/draggable_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Drag Me" android:background="#FF4081" android:padding="16dp"/> </FrameLayout>
- Implement the touch listener for drag handling:
val draggableView = findViewById<TextView>(R.id.draggable_view) val container = findViewById<FrameLayout>(R.id.container) var initialTouchX = 0f var initialTouchY = 0f var initialMarginLeft = 0 var initialMarginTop = 0 draggableView.setOnTouchListener { view, event -> when (event.action) { MotionEvent.ACTION_DOWN -> { // Record initial touch position relative to the view initialTouchX = event.rawX - view.translationX initialTouchY = event.rawY - view.translationY // Save initial margins to calculate final position val params = view.layoutParams as FrameLayout.LayoutParams initialMarginLeft = params.leftMargin initialMarginTop = params.topMargin return@setOnTouchListener true } MotionEvent.ACTION_MOVE -> { // Update translation for smooth drag movement view.translationX = event.rawX - initialTouchX view.translationY = event.rawY - initialTouchY return@setOnTouchListener true } MotionEvent.ACTION_UP -> { // Persist the final position by updating margins val params = view.layoutParams as FrameLayout.LayoutParams params.leftMargin = initialMarginLeft + view.translationX.toInt() params.topMargin = initialMarginTop + view.translationY.toInt() view.layoutParams = params // Reset translation to avoid double offset in future interactions view.translationX = 0f view.translationY = 0f return@setOnTouchListener true } else -> return@setOnTouchListener false } }
Why This Works
- Performance: Using
translationX/Yduring drag skips frequent layout recalculations, which is far smoother than updating margins on every move (each margin change triggers arequestLayout()call). - Persistence: Updating margins on release ensures the view stays in its new position even after the layout is remeasured (e.g., screen rotation).
- Simplicity: FrameLayout’s minimal design means less overhead compared to RelativeLayout, which would add unnecessary complexity for this use case.
If you had to use RelativeLayout instead, the approach is nearly identical—just replace FrameLayout.LayoutParams with RelativeLayout.LayoutParams (since RelativeLayout also uses margins for positioning). But FrameLayout remains the better choice for efficiency.
内容的提问来源于stack exchange,提问作者Jack

