当前位置:网站首页>RecyclerView advanced use - to realize drag and drop function of imitation Alipay menu edit page
RecyclerView advanced use - to realize drag and drop function of imitation Alipay menu edit page
2022-04-23 16:05:00 【Senzhiqianshou】
Let's start with an effect picture

I saw Alipay's menu edit page before. , There is a similar GridView Drag sort effect , So I want to realize it myself . After a large amount of information search on the Internet , Finally, the following solutions are obtained .
1. Drag and drop control
Entire drag and drop control , You can use drag and drop on the Internet GridView Or custom RecyclerView. I've tried both myself . Find out GridView How to implement , It's not a real drag , It's about dragging item Create a mirror image , Then I'll put the original item Of Visiblity Set to invisible , When you drag , The image is actually moved . Although the effect can be achieved , But and RecyclerView Compare to , Feel just low A little bit .RecyclerView First, bring your own item Insert moving animation . adopt ItemTouchHelper An official auxiliary class of can easily realize the drag and drop effect , Fluency comparison GridView It's much better to implement fake drag and drop . In the end in Github A third party was found on the RecyclerView Powerful encapsulation class AdvancedRecyclerView,Github The address is :https://github.com/h6ah4i/android-advancedrecyclerview, This class is still relatively powerful , Support sideslip , Drag and drop ,header,footer wait . Interested children's shoes can be downloaded by themselves demo have a look .
2. Build a data model

First, the main page item It is consistent with the sub items of the edit page , Then all attributes should have
private String name;// name
private String icon;// Icon
private String desc;//item Description of
private String group;//item Subordinate to the group
among ,group Property is used to identify this item What is the grouping of ,
/* Group labels */
public static final String GROUP_FAVORITE="favorite";
public static final String GROUP_COLD_WEAPON="cold_weapon";
public static final String GROUP_MODERN_WEAPON="modern_weapon";
public static final String GROUP_MISC="misc";
public static final String GROUP_PERSON="person";
public static final String GROUP_EQUIPMENT="equipment";
According to the needs of your project , To determine the category of your own group . Please note that favorite This group of . This group is selected by other groups and then put into this group , In other words, the inside item Of group Attributes are not GROUP_FAVORITE. In fact, another function of packet tag is to obtain packet data key. for instance , You want to request from the server favorite This set of data , So pass on GROUP_FAVORITE Give it to the server and you can get the data .
Then look at the list entries . The entry in the tag page list is a compound entry , Each entry contains the title of a group and all the child elements it contains , that , We can design it as :
private String mGroup;
private String mGroupTitle;
private List<MenuItem> mMenuItemList;
mGroup It's up there Group The label of ,mGroupTitle Is to change the title to be displayed corresponding to the label ( Of course, this field is not required , You can also judge externally according to the labels you get ),mMenuItemList This is the sub list data it contains .
3. Page structure design
First of all, the structure of the home page is very simple , Just one grid Type of recyclerView That's it . The key is to edit the page .
First , The edit page as a whole should be divided into two parts . Header and list section . So the design pattern can be considered in the normal list Add a header. Or two itemViewType, Render views separately . Both options are feasible . Just the first kind of words , Native recyclerView It's not header,footer Declarative , You need to package it yourself . ad locum , I choose the first method , Self encapsulation header.
4. Data persistence
1) The data structure of the server can refer to my style (json Format ):

Here to demonstrate , I will json Put the raw data into asset Under the table of contents , Used to simulate data obtained from the server .
2) Local persistence
The most formal way is to use database . for example GreenDao perhaps Realm They are all awesome database frameworks . here , Because the menu data is relatively small , I'll just sharedPreference For data storage and reading . in addition , in consideration of json Conversion between object and entity object , I recommend you to use Alibaba's fastjson, To serialize and deserialize data , Conversion efficiency lever drops .
The following is a data operation class I wrote .
package csii.cjs.demo.com.superboy;
import android.content.Context;
import android.content.SharedPreferences;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.util.ArrayList;
import java.util.List;
import csii.cjs.demo.com.superboy.base.ContextUtil;
import csii.cjs.demo.com.superboy.entity.MenuItem;
import csii.cjs.demo.com.superboy.tools.IOKit;
/**
* describe : Menu data control assistant , Simulate local database
* <p>
* author :cjs
* Creation time :2017 year 11 month 03 Japan 15:21
* mailbox :[email protected]
*
* @version 1.0
*/
public class MenuHelper {
/* Group labels */
public static final String GROUP_FAVORITE="favorite";
public static final String GROUP_COLD_WEAPON="cold_weapon";
public static final String GROUP_MODERN_WEAPON="modern_weapon";
public static final String GROUP_MISC="misc";
public static final String GROUP_PERSON="person";
public static final String GROUP_EQUIPMENT="equipment";
private int itemCounter=0;// It is used to count the total number of children item, Give each in turn item Set up independent id
/* Cache list of grouped data , Used when initializing groups */
private List<MenuItem> favoriteList;
private List<MenuItem> coldList;
private List<MenuItem> modernList;
private List<MenuItem> miscList;
private List<MenuItem> eqtList;
private List<MenuItem> personList;
/**
* Parse raw data , Used to simulate the data obtained from the server JSON message
*/
private void parseJSONData(){
String jsonStr= IOKit.getStringFromAssets(ContextUtil.getContext(),"dummy.json");// Get assets Messages in the directory
JSONObject dataJson= JSON.parseObject(jsonStr);// Send the message string Convert to JSON
favoriteList=parseJSONList(dataJson,GROUP_FAVORITE);
coldList=parseJSONList(dataJson,GROUP_COLD_WEAPON);
modernList=parseJSONList(dataJson,GROUP_MODERN_WEAPON);
miscList=parseJSONList(dataJson,GROUP_MISC);
eqtList=parseJSONList(dataJson,GROUP_EQUIPMENT);
personList=parseJSONList(dataJson,GROUP_PERSON);
savePreferFavoriteList(favoriteList);
savePreferColdWeaponList(coldList);
savePreferEqtList(eqtList);
savePreferMiscList(miscList);
savePreferModernWeaponList(modernList);
savePreferPersonList(personList);
}
private List<MenuItem> parseJSONList(JSONObject dataJSON,String group){
List<MenuItem> list=new ArrayList<>();
JSONArray array=dataJSON.getJSONArray(group);
int size=array.size();
for(int i=0;i<size;i++,itemCounter++){
JSONObject object=array.getJSONObject(i);
// The reason why it's not in array On the first floor JSON To java Object conversion , Is to enter the internal traversal , produce id, And will id Assign a value to menuItem
MenuItem item=JSON.toJavaObject(object,MenuItem.class);
item.setItemId(itemCounter);
list.add(item);
}
return list;
}
/**
* Initialization data
*/
public static void init(){
MenuHelper helper=new MenuHelper();
helper.parseJSONData();
setInit(true);
}
/**
* The name of the file used to save the local data
*/
private static final String PREFERENCE_MENU_DATA_NAME="menu_data";
/**
* Whether the field name has been initialized
*/
private static final String PREFERENCE_HAS_EVER_INIT="has_ever_init";
/**
* Get files for local data
* @return
*/
public static SharedPreferences getMenuDataConfig(){
return ContextUtil.getContext().getSharedPreferences(PREFERENCE_MENU_DATA_NAME, Context.MODE_PRIVATE);
}
/**
* Clear the contents of the local data file
*/
public static void clearMenuDataConfig(){
getMenuDataConfig().edit().clear().commit();
}
public static boolean hasEverInit(){
return getMenuDataConfig().getBoolean(PREFERENCE_HAS_EVER_INIT,false);
}
public static void setInit(boolean isInit){
getMenuDataConfig().edit().putBoolean(PREFERENCE_HAS_EVER_INIT,isInit);
}
/*---------------------------- Original method -----------------------------------*/
/**
* take List Convert to JsonString Keep in SharedPreference
* @param group
* @param list
*/
private static void savePreferMenuListData(String group,List<MenuItem> list){
SharedPreferences.Editor editor=getMenuDataConfig().edit();
editor.putString(group,JSON.toJSONString(list));
editor.commit();
}
/**
* from SharedPreference The inside out JsonString, Re convert to List
* @param group
* @return
*/
private static List<MenuItem> getPreferMenuListData(String group){
String jsonStr=getMenuDataConfig().getString(group,"");
JSONArray array=JSONArray.parseArray(jsonStr);
return array.toJavaList(MenuItem.class);
}
/**
* Delete a from the local data cache list item
* @param group
* @param item
*/
public static void deleteItem(String group,MenuItem item){
List<MenuItem> list=getPreferMenuListData(group);
for(MenuItem i:list){
if(i.getItemId()==item.getItemId()){
list.remove(i);
break;
}
}
savePreferMenuListData(group,list);
}
/**
* Add a... From the local data element item
* @param group
* @param item
*/
public static void addItem(String group,MenuItem item){
List<MenuItem> list=getPreferMenuListData(group);
if(!contains(list,item)){
list.add(item);
savePreferMenuListData(group,list);
}
}
private static boolean contains(List<MenuItem> list,MenuItem item){
if(list!=null && list.size()>0){
for(MenuItem i:list){
if(i.getItemId()==item.getItemId()){
return true;
}
}
}
return false;
}
/*---------------------------- Original method -----------------------------------*/
/*---------------------------- Derivative methods -----------------------------------*/
public static void savePreferFavoriteList(List<MenuItem> list){
savePreferMenuListData(GROUP_FAVORITE,list);
}
public static void savePreferColdWeaponList(List<MenuItem> list){
savePreferMenuListData(GROUP_COLD_WEAPON,list);
}
public static void savePreferModernWeaponList(List<MenuItem> list){
savePreferMenuListData(GROUP_MODERN_WEAPON,list);
}
public static void savePreferMiscList(List<MenuItem> list){
savePreferMenuListData(GROUP_MISC,list);
}
public static void savePreferEqtList(List<MenuItem> list){
savePreferMenuListData(GROUP_EQUIPMENT,list);
}
public static void savePreferPersonList(List<MenuItem> list){
savePreferMenuListData(GROUP_PERSON,list);
}
public static List<MenuItem> getPreferFavoriteList(){
return getPreferMenuListData(GROUP_FAVORITE);
}
public static List<MenuItem> getPreferColdWeaponList(){
return getPreferMenuListData(GROUP_COLD_WEAPON);
}
public static List<MenuItem> getPreferModernWeaponList(){
return getPreferMenuListData(GROUP_MODERN_WEAPON);
}
public static List<MenuItem> getPreferMiscList(){
return getPreferMenuListData(GROUP_MISC);
}
public static List<MenuItem> getPreferEquipmentList(){
return getPreferMenuListData(GROUP_EQUIPMENT);
}
public static List<MenuItem> getPreferPersonList(){
return getPreferMenuListData(GROUP_PERSON);
}
public static void addPreferFavoriteItem(MenuItem item){
addItem(GROUP_FAVORITE,item);
}
public static void addPreferColdItem(MenuItem item){
addItem(GROUP_COLD_WEAPON,item);
}
public static void addPreferEqtItem(MenuItem item){
addItem(GROUP_EQUIPMENT,item);
}
public static void addPreferModernItem(MenuItem item){
addItem(GROUP_MODERN_WEAPON,item);
}
public static void addPreferMiscItem(MenuItem item){
addItem(GROUP_MISC,item);
}
public static void addPreferPersonItem(MenuItem item){
addItem(GROUP_PERSON,item);
}
public static void deletePreferFavoriteItem(MenuItem item){
deleteItem(GROUP_FAVORITE,item);
}
public static void deletePreferColdItem(MenuItem item){
deleteItem(GROUP_COLD_WEAPON,item);
}
public static void deletePreferModernItem(MenuItem item){
deleteItem(GROUP_MODERN_WEAPON,item);
}
public static void deletePreferMiscItem(MenuItem item){
deleteItem(GROUP_MISC,item);
}
public static void deletePreferEqtItem(MenuItem item){
deleteItem(GROUP_EQUIPMENT,item);
}
public static void deletePreferPersonItem(MenuItem item){
deleteItem(GROUP_PERSON,item);
}
/*---------------------------- Derivative methods -----------------------------------*/
}
5. Source code related instructions

among recyclerview The bag is my own to AdvancedRecyclerView The second encapsulation . After encapsulation , It's easier to implement .tools The bag is a tool kit , It contains some useful methods , These can be directly applied to our own projects . Then is adapter package , This is right recyclerview Specific implementation in the package . in addition MenuHelper Initialization of , stay MyApplication Inside .
Warining:
About AdvancedRecyclerView, Android is not currently supported 26 Compilation of , Please use 25+. also , If you take UniversalImageLoader There is a flickering problem when loading pictures , Please move on to this article :
http://blog.csdn.net/cjs1534717040/article/details/78285741
The code has been uploaded to Github As a free download . The new code fixes some bug, Added the most like Alipay. 5 Control of one .

Github Address :https://github.com/ChenJunsen/DragRecyclerView
At the same time, I welcome colleagues to join me in common exchange qq:1534717040
Original code http://download.csdn.net/download/cjs1534717040/10106300, need 1 Integral points , This link is only for reward points , Thank you for your support
to update (2020-07-20)
- primary Git The address source code was told by the company to get off the shelf because it contained the company's name ( speechless ), Now I set it private , All are now inaccessible .
- AS Update to 3.4 Post compiled source code , May report appCompat The error of conflict . The reason is that the main code is used 26+,AdvRecyclerView It's using 25+, Cause merge conflict , My current solution is to change the main code to 25+.
Why? AdvRecyclerView Use 25+ compile ? because AnimatorCompatHelper This class is in the 26+ Removed from the . You can also look at the time of this code , I wrote it when I worked for about two years . at that time api Not so high , There are also some deficiencies in technology . Later, it will be considered to change to AndroidX. Download address :https://download.csdn.net/download/cjs1534717040/12641844( free )- CSDN You can't set it up for free , Dial it ( Get rid of &)
link :https&&&&&/&&&&pan.baidu.com/s/1WqaDmCtPbEcGzYhGK8az5Q
Extraction code :esq8
版权声明
本文为[Senzhiqianshou]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204231405037515.html
边栏推荐
- 捡起MATLAB的第(3)天
- 多线程原理和常用方法以及Thread和Runnable的区别
- 面试题 17.10. 主要元素
- Partitionby of spark operator
- Accumulation of applet knowledge points
- 运维流程有多重要,听说一年能省下200万?
- Win11 / 10 home edition disables the edge's private browsing function
- Use bitnami PostgreSQL docker image to quickly set up stream replication clusters
- Using JSON server to create server requests locally
- [key points of final review of modern electronic assembly]
猜你喜欢

Countdown 1 day ~ 2022 online conference of cloud disaster tolerance products is about to begin

TIA botu - basic operation

Using JSON server to create server requests locally

C#,贝尔数(Bell Number)的计算方法与源程序

Import address table analysis (calculated according to the library file name: number of imported functions, function serial number and function name)

C language self compiled string processing function - string segmentation, string filling, etc

糖尿病眼底病变综述概要记录
![[open source tool sharing] MCU debugging assistant (oscillograph / modification / log) - linkscope](/img/39/4d37c381f16dbe11acc64c92d0a1e5.png)
[open source tool sharing] MCU debugging assistant (oscillograph / modification / log) - linkscope

一文掌握vscode远程gdb调试

Cloud migration practice in the financial industry Ping An financial cloud integrates hypermotion cloud migration solution to provide migration services for customers in the financial industry
随机推荐
MetaLife与ESTV建立战略合作伙伴关系并任命其首席执行官Eric Yoon为顾问
C, calculation method and source program of bell number
matplotlib教程05---操作图像
Sort by character occurrence frequency 451
Go language, condition, loop, function
Day (4) of picking up matlab
What is the experience of using prophet, an open source research tool?
Distinct use of spark operator
Leetcode-374 guess the size of the number
Grbl learning (II)
VIM specifies the line comment and reconciliation comment
C language --- string + memory function
C语言自编字符串处理函数——字符串分割、字符串填充等
捡起MATLAB的第(9)天
Function summary of drawing object arrangement in R language
[key points of final review of modern electronic assembly]
Start Oracle service on Linux
第十天 异常机制
保姆级Anaconda安装教程
GRBL学习(一)