当前位置:网站首页>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
边栏推荐
- ESP32_ Arduino
- Cloudy data flow? Disaster recovery on cloud? Last value content sharing years ago
- 如何进行应用安全测试(AST)
- What is the experience of using prophet, an open source research tool?
- 保姆级Anaconda安装教程
- VIM specifies the line comment and reconciliation comment
- 安装Redis并部署Redis高可用集群
- Start Oracle service on Linux
- Win11/10家庭版禁用Edge的inprivate浏览功能
- Spark 算子之filter使用
猜你喜欢
Day (4) of picking up matlab
451. 根据字符出现频率排序
Gartner predicts that the scale of cloud migration will increase significantly; What are the advantages of cloud migration?
糖尿病眼底病变综述概要记录
Spark 算子之sortBy使用
MetaLife与ESTV建立战略合作伙伴关系并任命其首席执行官Eric Yoon为顾问
volatile的含义以及用法
Distinct use of spark operator
Merging of Shanzhai version [i]
R语言中实现作图对象排列的函数总结
随机推荐
Unity shader learning
Day (5) of picking up matlab
建设星际计算网络的愿景
C语言自编字符串处理函数——字符串分割、字符串填充等
Grbl learning (I)
VIM uses vundle to install the code completion plug-in (youcompleteme)
Gartner predicts that the scale of cloud migration will increase significantly; What are the advantages of cloud migration?
dlopen/dlsym/dlclose的简单用法
Filter usage of spark operator
299. 猜数字游戏
Metalife established a strategic partnership with ESTV and appointed its CEO Eric Yoon as a consultant
Accumulation of applet knowledge points
第十天 异常机制
捡起MATLAB的第(10)天
R语言中实现作图对象排列的函数总结
Passing header request header information between services through feign
Leetcode-396 rotation function
安装Redis并部署Redis高可用集群
pywintypes. com_ Error: (- 2147221020, 'invalid syntax', none, none)
运维流程有多重要,听说一年能省下200万?