当前位置:网站首页>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
边栏推荐
- Accumulation of applet knowledge points
- Filter usage of spark operator
- 建设星际计算网络的愿景
- Pgpool II 4.3 Chinese Manual - introductory tutorial
- [section 5 if and for]
- Use bitnami PostgreSQL docker image to quickly set up stream replication clusters
- 299. Number guessing game
- gps北斗高精度卫星时间同步系统应用案例
- 【开源工具分享】单片机调试助手(示波/改值/日志) - LinkScope
- 新动态:SmartMesh和MeshBox的合作新动向
猜你喜欢
Vision of building interstellar computing network
Using JSON server to create server requests locally
MySQL - MySQL查询语句的执行过程
[open source tool sharing] MCU debugging assistant (oscillograph / modification / log) - linkscope
Website pressure measurement tools Apache AB, webbench, Apache jemeter
Large factory technology implementation | industry solution series tutorials
捡起MATLAB的第(7)天
C语言自编字符串处理函数——字符串分割、字符串填充等
Spark 算子之sortBy使用
新动态:SmartMesh和MeshBox的合作新动向
随机推荐
Win11/10家庭版禁用Edge的inprivate浏览功能
面试题 17.10. 主要元素
Unity shader learning
保姆级Anaconda安装教程
linux上启动oracle服务
vim指定行注释和解注释
Accumulation of applet knowledge points
OAK-D树莓派点云项目【附详细代码】
shell_ two
MySQL - execution process of MySQL query statement
Grbl learning (II)
The system research problem that has plagued for many years has automatic collection tools, which are open source and free
VIM uses vundle to install the code completion plug-in (youcompleteme)
C language --- string + memory function
捡起MATLAB的第(3)天
捡起MATLAB的第(5)天
Day (2) of picking up matlab
utils. Deprecated in35 may be cancelled due to upgrade. What should I do
Spark 算子之distinct使用
捡起MATLAB的第(8)天