Implementing a Multi‑Type RecyclerView Adapter with Drag‑And‑Drop and Scale Features on Android
This article demonstrates how to implement a multi-type RecyclerView adapter on Android that supports cross‑RecyclerView item dragging, scaling, and custom drag controls, providing code examples, interface definitions, and a step‑by‑step explanation of the underlying processes.
Wei Zixiang, a developer at Qunar.com since 2017, introduces a library called MultiItem that helps build a multi‑type RecyclerView adapter for Android. The article focuses on implementing cross‑RecyclerView item dragging with optional scaling, a feature often needed in office‑style panel applications.
Effect Screenshots
Usage
Drag Functionality
Dragging is handled through an ItemDragHelper that forwards touch events to a listener ( ItemDragListener ). The helper is instantiated, a listener is set, and dispatchTouchEvent calls dragHelper.onTouch(ev) to consume the event when appropriate.
@Override
protected void onCreate(Bundle savedInstanceState){ ... }
// ItemDragHelper needs the outer horizontal RecyclerView
dragHelper = new ItemDragHelper(horizontalRecycler);
dragHelper.setOnItemDragListener(new OnBaseDragListener());
@Override
public boolean dispatchTouchEvent(MotionEvent ev){
return dragHelper.onTouch(ev) || super.dispatchTouchEvent(ev);
}For a vertical list, the data source must implement the ItemData interface and be registered with the adapter:
baseItemAdapter.register(TextDragBean.class, new TextViewDragManager());To start a drag operation:
dragHelper.startDrag(viewHolder);General Item Drag Control
The data source should also implement the ItemDrag interface, which defines three boolean methods that control whether an item can move within its own RecyclerView, switch to another RecyclerView, or be dragged at all.
public interface ItemDrag {
/** Whether the item can be moved inside its own RecyclerView */
boolean isCanMove();
/** Whether the item can be transferred to another RecyclerView */
boolean isCanChangeRecycler();
/** Whether dragging is allowed */
boolean isCanDrag();
}Double‑Tap Zoom Functionality
A ViewScaleHelper is used to manage scaling of the outer content view and the horizontal RecyclerView. The helper can be toggled on or off, and the current scale can be queried from the drag listener.
// Instantiate the scale helper
scaleHelper = new ViewScaleHelper();
// Set the root content view
scaleHelper.setContentView(contentView);
// Set the horizontal RecyclerView
scaleHelper.setHorizontalView(horizontalRecycler);
// Add the vertical view for unified scaling
scaleHelper.addVerticalView(verticalView);
// Toggle scaling mode
scaleHelper.toggleScaleModel(); // or startScaleModel() / stopScaleModel()Other Customizations
Custom business logic can be added by overriding methods in ItemDragListener . Examples include retrieving the current scale via getScale() , controlling item selection and movement, adjusting maximum scroll speeds, defining scroll limits, handling floating‑view drawing, and setting move boundaries.
Main Process Analysis
Generating the Floating View
The dragged item view is made invisible and a floating view is created using WindowManager + ImageView that displays a bitmap of the original item.
Calculating Horizontal and Vertical Scrolling
The implementation heavily references ItemTouchHelper . It calculates whether scrolling is needed based on the touch position, determines direction and distance, and uses a periodic Runnable to keep scrolling smoothly.
Item Position Swapping
When the touch point is over a horizontal RecyclerView, findChildViewUnder locates the target position. If the item needs to move to another RecyclerView, it is removed from the source and added to the destination. Subsequent calls to findChildViewUnder on the vertical RecyclerView determine whether the item view itself should be repositioned.
View Scaling
Scaling enlarges the outer container and the horizontal list by applying setScaleX and setScaleY . The scaled width is stored to avoid layout issues, and the original scale is restored when scaling stops.
Conclusion
The feature was implemented quickly as a beta version without extensive polishing. The article provides usage instructions and a brief flow analysis; readers are encouraged to explore the source code for deeper understanding and to suggest improvements.
Qunar Tech Salon
Qunar Tech Salon is a learning and exchange platform for Qunar engineers and industry peers. We share cutting-edge technology trends and topics, providing a free platform for mid-to-senior technical professionals to exchange and learn.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.