项目接入实现复杂布局的vlayout
前言
- V- Layout 是阿里出品的基礎 UI 框架,用于快速實現頁面的復雜布局,在手機天貓 Android版 內廣泛使用
- 讓人激動的是,在上個月V- Layout終于在Github上開源!
Github - alibaba - vlayout
Github- 在五一假期我對V- Layout進行了詳細分析,我將獻上一份 V- Layout的使用攻略 & 源碼分析,希望你們會喜歡。
閱讀本文前請先看:
Android Tangram模型:連淘寶、天貓都在用的UI框架模型你一定要懂
目錄
目錄1. 為什么要使用 V - Layout
在講解 V - Layout 前,我們先來搞懂一個問題:為什么要使用 V - Layout
1.1 背景
- Android中 UI 性能消耗主要來自于兩個方面:
- 為了解決上述問題,現有的解決方式是:
- 少用嵌套布局
- 使用 ListView/GirdView/RecyclerView等基礎空間來處理View的回收與復用。
但是,很多時候我們需要在一個長列表下做多種類型的布局來分配各種元素,,特別是電商平臺首頁等頁面,布局元素結構更加復雜多樣。如下圖:
此時的解決方案有所變化:不采用子View的復用,只采用一個主要的復用容器(如ListView 或 RecyclerView+LinearLayoutManager),然后在其中使用嵌套方式直接用各個組件進行拼接,減少了復用的能力
1.2 問題
這種做法還是會損失Android應用的性能。
1.3 解決方案
- 通過自定義 LayoutManager 管理所有的布局類型
- 即阿里出品的基礎 UI 框架項目 VirtualLayout就是采用該方式來解決上述問題
2. 簡介
- 定義:VirtualLayout是阿里出品的基礎 UI 框架項目
- 作用:快速實現復雜的布局格式的混排 & 通過組件回收提高性能
- 基于 RecyclerView & LayoutManager擴展
- 目前已在Github開源:Github - alibaba - vlayout
3. 應用場景
- 復雜的布局格式混排,如:浮動布局、欄格布局、通欄布局、一拖N布局、瀑布流布局,還可以組合使用這些布局
- 具體場景是:如電商平臺首頁、活動頁等等
V - Layout 目前已在手機天貓 & 淘寶 Android 版內廣泛使用
實際應用效果圖4. 原理解析
V - Layout的本質原理是:通過自定義一個VirtualLayoutManager(繼承自 LayoutManager),用于管理一系列LayoutHelper,將具體的布局能力交給LayoutHelper來完成,從而 快速實現組合布局 的需求。
布局類型
4.1 源碼類說明
V - Layout的源碼類圖如下:
UML類圖具體類說明
- V - Layout默認實現了10種默認布局:(對應同名的LayoutHelper)
下面會進行詳細介紹。
- 特別注意:
介紹完類之后,我將詳細分析 V - Layout的工作流程。
4.2 工作流程
- V - Layout的工作流程分為 初始化 & 布局流程。如下圖:
- 下面我將對初始化 & 布局流程作詳細分析。
4.2.1 初始化
- 在使用 V - layout 快速實現復雜布局前,需要先做一系列的初始化工作。
初始化流程與使用普通的 RecyclerView + LayoutManager 初始化流程基本一致:Vlayout的使用者
初始化流程- 此處的初始化 實際上 就是 使用者在使用 V - layout 時需要做的初始化工作。
- 此處主要先講解下數據列表的獲取:本質上,是對頁面實體 進行 卡片 & 組件的拆解,形成一個位置列表
- 其他初始化步驟將在下面實例講解進行詳細說明
4.2.2 具體布局流程
- 當完成初始化工作后,每當用戶剛打開頁面第一次渲染布局 或 用戶滑動頁面時,都會進行一次布局流程
- 布局流程的本質是:自定義 VirtualLayoutManager持續獲取頁面狀態,并通過LayoutHelperFinder找到對應的LayoutHelper從而實現對應的布局邏輯,從而快速實現組合布局 的需求
- 具體流程如下
總結
下面用一張圖總結 V - Layout 的原理 & 工作流程
在講完原理后,接下來我將如何使用 V - Layout。
5. 使用步驟
- V - Layout的使用其實就是上面說的初始化工作
- 使用步驟如下:
下面我將對每個步驟進行詳細說明。
步驟1:創建RecyclerView & VirtualLayoutManager 對象并進行綁定
recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);// 創建RecyclerView對象VirtualLayoutManager layoutManager = new VirtualLayoutManager(this);// 創建VirtualLayoutManager對象// 同時內部會創建一個LayoutHelperFinder對象,用來后續的LayoutHelper查找recyclerView.setLayoutManager(layoutManager);// 將VirtualLayoutManager綁定到recyclerView步驟2:設置回收復用池大小
如果一屏內相同類型的 View 個數比較多,需要設置一個合適的大小,防止來回滾動時重新創建 View)
// 設置組件復用回收池RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();recyclerView.setRecycledViewPool(viewPool);viewPool.setMaxRecycledViews(0, 10);步驟3:設置Adapter
設置 V - Layout的Adapter有兩種方式:
- 方式1:繼承 自 DelegateAdapter
- 方式2:繼承 自 VirtualLayoutAdapter
下面會進行詳細說明:
方式1:繼承 自 DelegateAdapter
- 定義:DelegateAdapter是V - Layout專門為管理 LayoutHelper定制的 Adapter
繼承自VirtualLayoutAdapter
- 作用:通過管理不同布局的Adapter,繼而管理不同的 LayoutHelper,從而實現使用不同組合布局
- 具體做法:
方式2:繼承 自 VirtualLayoutAdapter
定義:當需要實現復雜需求時, 可以通過繼承VirtualLayoutAdapter從而實現自定義Adapter
具體使用
步驟4:根據數據列表,創建對應的LayoutHelper
- 系統以封裝好以下布局類型(對應同名的LayoutHelper)
- 具體使用如下:
1. 線性布局(LinearLayoutHelper)
- 布局說明:布局子元素(Item)以線性排布的布局
- 具體使用
1. 所有布局的共有屬性說明:
a. setItemCount屬性
- 作用:設置整個布局里的Item數量
如設置的Item總數如與Adapter的getItemCount()方法返回的數量不同,會取決于后者
示意圖- 具體使用
b. Adding & Margin屬性
定義:都是邊距的含義,但二者邊距的定義不同:
- Padding:是 LayoutHelper 的子元素相對 LayoutHelper 邊緣的距離;
- Margin:是 LayoutHelper 邊緣相對父控件(即RecyclerView)的距離。具體如下圖:
示意圖 具體使用
c. bgColor屬性
- 作用:設置布局背景顏色
- 具體使用:
d. aspectRatio屬性
- 作用:設置布局內每行布局的寬與高的比。如下圖
- 具體使用
2. LinearLayoutHelper布局的特有屬性說明
a. dividerHeight屬性
- 作用:設置每行Item之間的距離
設置的間隔會與RecyclerView的addItemDecoration()添加的間隔疊加
示意圖- 具體使用
2. 網格布局(GridLayout)
- 布局說明:布局里的Item以網格的形式進行排列
- 具體使用
GridLayoutHelper布局的特有屬性說明
a. weights屬性
- 作用:設置每行中每個網格寬度占每行總寬度的比例
- 具體使用
b. vGap、hGap屬性
- 作用:分別控制子元素之間的垂直間距 和 水平間距。
- 具體使用
c. spanCount、spanSizeLookup屬性
- 作用:
- spanCount:設置每行多少個網格
- spanSizeLookup:設置每個 Item占用多少個網格(默認= 1)
- 具體使用
d. autoExpand屬性
- 作用:當一行里item的個數 < (每行網格列數 - spanCount值/ 每個Item占有2個網格-setSpanSizeLookup )時,是否自動填滿空白區域
- 具體使用
3. 固定布局(FixLayoutHelper)
- 布局說明:布局里的Item 固定位置
固定在屏幕某個位置,且不可拖拽 & 不隨頁面滾動而滾動。如下圖:(左上角)
固定布局- 具體使用
FixLayoutHelper特有屬性說明
a. AlignType、x、y屬性
- 作用:
- alignType:吸邊基準類型
- x:基準位置的橫向偏移量
- y:基準位置的縱向偏移量
共有4個取值:TOP_LEFT(默認), TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT,具體請看下面示意圖
- 作用對象:FixLayoutHelper, ScrollFixLayoutHelper, FloatLayoutHelper的屬性
4. 可選顯示的固定布局(ScrollFixLayoutHelper)
- 布局說明:布局里的Item 固定位置
以下示意圖為:滑動到底部,布局才在左上角顯示
滑動到底部才在左上角顯示- 具體使用
ScrollFixLayoutHelper特有屬性說明
a. AlignType、x、y屬性
- 作用:
- alignType:吸邊基準類型
- x:基準位置的橫向偏移量
- y:基準位置的縱向偏移量
共有4個取值:TOP_LEFT(默認), TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT,具體請看下面示意圖
- 具體使用
b. ShowType屬性
- 作用:設置Item的顯示模式
共有三種顯示模式
- 具體使用
5. 浮動布局(FloatLayoutHelper)
- 布局說明:布局里的Item只有一個
- 具體使用
6. 欄格布局(ColumnLayoutHelper)
- 布局說明:該布局只設有一欄(該欄設置多個Item)
可理解為只有一行的線性布局
示意圖/**設置欄格布局*/ColumnLayoutHelper columnLayoutHelper = new ColumnLayoutHelper();// 創建對象// 公共屬性columnLayoutHelper.setItemCount(3);// 設置布局里Item個數columnLayoutHelper.setPadding(20, 20, 20, 20);// 設置LayoutHelper的子元素相對LayoutHelper邊緣的距離columnLayoutHelper.setMargin(20, 20, 20, 20);// 設置LayoutHelper邊緣相對父控件(即RecyclerView)的距離columnLayoutHelper.setBgColor(Color.GRAY);// 設置背景顏色columnLayoutHelper.setAspectRatio(6);// 設置設置布局內每行布局的寬與高的比// columnLayoutHelper特有屬性columnLayoutHelper.setWeights(new float[]{30, 40, 30});// 設置該行每個Item占該行總寬度的比例// 同上面Weigths屬性講解7. 通欄布局(SingleLayoutHelper)
- 布局說明:布局只有一欄,該欄只有一個Item
- 具體使用
8. 一拖N布局 (OnePlusNLayoutHelper)
- 布局說明:將布局分為不同比例,最多是1拖4。具體如下圖
- 具體使用
9. 吸邊布局(StickyLayoutHelper)
布局說明:布局只有一個Item,顯示邏輯如下:
- 當它包含的組件處于屏幕可見范圍內時,像正常的組件一樣隨頁面滾動而滾動
- 當組件將要被滑出屏幕返回的時候,可以吸到屏幕的頂部或者底部,實現一種吸住的效果
示意圖(吸在頂部)
- 具體使用
stickyStart、 offset屬性說明
作用:
- stickyStart:設置吸邊位置
- offset:設置吸邊的偏移量
具體使用
當視圖的位置在屏幕范圍內時,視圖會隨頁面滾動而滾動;當視圖的位置滑出屏幕時,StickyLayoutHelper會將視圖固定在頂部(stickyStart = true)或 底部(stickyStart = false)
10. 瀑布流布局(StaggeredGridLayoutHelper)
- 布局說明:以網格的形式進行布局。與網格布局類似,區別在于:
- 網格布局每欄的Item高度是相等的;
- 瀑布流布局每欄的Item高度是可以不相等的。
- 具體使用
自定義布局(即自定義LayoutHelper)
除了使用系統提供的默認布局 LayoutHelper,開發者還可以通過自定義LayoutHelper從而實現自定義布局樣式。有三種方式:
LinearLayoutHelper、GridLayoutHelper都是采用該方法實現
& 回收。主要實現layoutViews()等方法
OnePlusNLayoutHelper采用該方法實現
FixLayoutHelper采用該方法實現
步驟5:將生成的LayoutHelper 交給Adapter,并綁定到RecyclerView 對象
此處的做法會因步驟3中Adapter的設置而有所不同
<-- Adapter繼承 自 DelegateAdapter -->// 步驟1:設置Adapter列表(同時也是設置LayoutHelper列表)List<DelegateAdapter.Adapter> adapters = new LinkedList<>();// 步驟2:創建自定義的Adapter對象 & 綁定數據 & 綁定上述對應的LayoutHelper // 綁定你需要展示的布局LayoutHelper即可,此處僅展示兩個。MyAdapter Adapter_linearLayout = new MyAdapter(this, linearLayoutHelper,ListItem); // ListItem是需要綁定的數據(其實取決于你的Adapter如何定義)MyAdapter Adapter_gridLayoutHelper = new MyAdapter(this, gridLayoutHelper,ListItem);// 步驟3:將創建的Adapter對象放入到DelegateAdapter.Adapter列表里adapters.add(Adapter_linearLayout ) ;adapters.add(Adapter_gridLayoutHelper ) ;// 步驟4:創建DelegateAdapter對象 & 將layoutManager綁定到DelegateAdapter DelegateAdapter delegateAdapter = new DelegateAdapter(layoutManager);// 步驟5:將DelegateAdapter.Adapter列表綁定到DelegateAdapterdelegateAdapter.setAdapters(adapters);// 步驟6:將delegateAdapter綁定到recyclerView recyclerView.setAdapter(delegateAdapter);<-- Adapter繼承 自 VirtualLayoutAdapter -->// 步驟1:設置LayoutHelper列表List<LayoutHelper> helpers = new LinkedList<>();// 步驟2:綁定上述對應的LayoutHelper helpers.add(Adapter_linearLayout ); helpers.add(Adapter_gridLayoutHelper ) ;// 步驟3:創建自定義的MyAdapter對象 & 綁定layoutManager MyAdapter myAdapter = new MyAdapter(layoutManager);// 步驟4:將 layoutHelper 列表傳遞給 adapter myAdapter.setLayoutHelpers(helpers);// 步驟5:將adapter綁定到recyclerView recycler.setAdapter(myAdapter);至此,使用過程講解完畢。
6. 實例說明
- V-Layout的優點在于快速的組合不同布局
- 下面,我將根據上面的步驟說明,用一個實例來使用 V - Layout快速組合布局
步驟1:在Android - Gradle加入依賴
compile ('com.alibaba.android:vlayout:1.0.3@aar') {transitive = true}步驟2:定義主 xml布局
activity_main.xml
xml version="1.0" encoding="utf-8" <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:paddingBottom="@dimen/activity_vertical_margin"android:paddingLeft="@dimen/activity_horizontal_margin"android:paddingRight="@dimen/activity_horizontal_margin"android:paddingTop="@dimen/activity_vertical_margin"tools:context="scut.carson_ho.v_layoutusage.MainActivity"><android.support.v7.widget.RecyclerViewandroid:id="@+id/my_recycler_view"android:layout_width="match_parent"android:layout_height="match_parent"android:scrollbars="horizontal" /> </RelativeLayout>步驟3:定義 RecyclerView每個子元素( Item )的xml布局
item.xml
此處定義的 Item 布局是常用的 上字下圖
xml version="1.0" encoding="utf-8" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:orientation="vertical" android:layout_width="match_parent"android:layout_height="match_parent"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="center"android:text="New Text"android:id="@+id/Item" /><ImageViewandroid:layout_alignParentRight="true"android:layout_gravity="center"android:layout_width="wrap_content"android:layout_height="wrap_content"android:id="@+id/Image"/></LinearLayout>步驟4:設置Adapter
- 設置 V - Layout的Adapter有兩種方式:
- 繼承 自 DelegateAdapter
此處主要以該方式進行演示
- 具體使用
MyAdapter.java
public class MyAdapter extends DelegateAdapter.Adapter<MyAdapter.MainViewHolder> {// 使用DelegateAdapter首先就是要自定義一個它的內部類Adapter,讓LayoutHelper和需要綁定的數據傳進去// 此處的Adapter和普通RecyclerView定義的Adapter只相差了一個onCreateLayoutHelper()方法,其他的都是一樣的做法.private ArrayList<HashMap<String, Object>> listItem;// 用于存放數據列表private Context context;private LayoutHelper layoutHelper;private RecyclerView.LayoutParams layoutParams;private int count = 0;private MyItemClickListener myItemClickListener;// 用于設置Item點擊事件//構造函數(傳入每個的數據列表 & 展示的Item數量)public MyAdapter(Context context, LayoutHelper layoutHelper, int count, ArrayList<HashMap<String, Object>> listItem) {this(context, layoutHelper, count, new RecyclerView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 300), listItem);}public MyAdapter(Context context, LayoutHelper layoutHelper, int count, @NonNull RecyclerView.LayoutParams layoutParams, ArrayList<HashMap<String, Object>> listItem) {this.context = context;this.layoutHelper = layoutHelper;this.count = count;this.layoutParams = layoutParams;this.listItem = listItem;}// 把ViewHolder綁定Item的布局public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {return new MainViewHolder(LayoutInflater.from(context).inflate(R.layout.item, parent, false));}// 此處的Adapter和普通RecyclerView定義的Adapter只相差了一個onCreateLayoutHelper()方法public LayoutHelper onCreateLayoutHelper() {return layoutHelper;}// 綁定Item的數據public void onBindViewHolder(MainViewHolder holder, int position) {holder.Text.setText((String) listItem.get(position).get("ItemTitle"));holder.image.setImageResource((Integer) listItem.get(position).get("ItemImage"));}// 返回Item數目public int getItemCount() {return count;}// 設置Item的點擊事件// 綁定MainActivity傳進來的點擊監聽器public void setOnItemClickListener(MyItemClickListener listener) {myItemClickListener = listener;}//定義Viewholderclass MainViewHolder extends RecyclerView.ViewHolder {public TextView Text;public ImageView image;public MainViewHolder(View root) {super(root);// 綁定視圖Text = (TextView) root.findViewById(R.id.Item);image = (ImageView) root.findViewById(R.id.Image);root.setOnClickListener(new View.OnClickListener() {public void onClick(View v) {if (myItemClickListener != null)myItemClickListener.onItemClick(v, getPosition());}}//監聽到點擊就回調MainActivity的onItemClick函數);}public TextView getText() {return Text;}} }以下步驟都將寫在同一個.Java文件里
步驟5:創建RecyclerView & VirtualLayoutManager 對象并進行綁定
步驟6:設置回收復用池大小
步驟7:設置需要存放的數據
步驟8:根據數據列表,創建對應的LayoutHelper
步驟9:將生成的LayoutHelper 交給Adapter,并綁定到RecyclerView 對象
詳細請看注釋
MainActivity.java
public class MainActivity extends AppCompatActivity implements MyItemClickListener {RecyclerView recyclerView;MyAdapter Adapter_linearLayout,Adapter_GridLayout,Adapter_FixLayout,Adapter_ScrollFixLayout,Adapter_FloatLayout,Adapter_ColumnLayout,Adapter_SingleLayout,Adapter_onePlusNLayout,Adapter_StickyLayout,Adapter_StaggeredGridLayout;private ArrayList<HashMap<String, Object>> listItem;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);/*** 步驟1:創建RecyclerView & VirtualLayoutManager 對象并進行綁定* */recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);// 創建RecyclerView對象VirtualLayoutManager layoutManager = new VirtualLayoutManager(this);// 創建VirtualLayoutManager對象// 同時內部會創建一個LayoutHelperFinder對象,用來后續的LayoutHelper查找recyclerView.setLayoutManager(layoutManager);// 將VirtualLayoutManager綁定到recyclerView/*** 步驟2:設置組件復用回收池* */RecyclerView.RecycledViewPool viewPool = new RecyclerView.RecycledViewPool();recyclerView.setRecycledViewPool(viewPool);viewPool.setMaxRecycledViews(0, 10);/*** 步驟3:設置需要存放的數據* */listItem = new ArrayList<HashMap<String, Object>>();for (int i = 0; i < 100; i++) {HashMap<String, Object> map = new HashMap<String, Object>();map.put("ItemTitle", "第" + i + "行");map.put("ItemImage", R.mipmap.ic_launcher);listItem.add(map);}/*** 步驟4:根據數據列表,創建對應的LayoutHelper* */// 為了展示效果,此處將上面介紹的所有布局都顯示出來/**設置線性布局*/LinearLayoutHelper linearLayoutHelper = new LinearLayoutHelper();// 創建對應的LayoutHelper對象// 公共屬性linearLayoutHelper.setItemCount(4);// 設置布局里Item個數linearLayoutHelper.setPadding(20, 20, 20, 20);// 設置LayoutHelper的子元素相對LayoutHelper邊緣的距離linearLayoutHelper.setMargin(20, 20, 20, 20);// 設置LayoutHelper邊緣相對父控件(即RecyclerView)的距離// linearLayoutHelper.setBgColor(Color.GRAY);// 設置背景顏色linearLayoutHelper.setAspectRatio(6);// 設置設置布局內每行布局的寬與高的比// linearLayoutHelper特有屬性linearLayoutHelper.setDividerHeight(10);// 設置間隔高度// 設置的間隔會與RecyclerView的addItemDecoration()添加的間隔疊加.linearLayoutHelper.setMarginBottom(100);// 設置布局底部與下個布局的間隔// 創建自定義的Adapter對象 & 綁定數據 & 綁定對應的LayoutHelper進行布局繪制Adapter_linearLayout = new MyAdapter(this, linearLayoutHelper, 4, listItem) {// 參數2:綁定綁定對應的LayoutHelper// 參數3:傳入該布局需要顯示的數據個數// 參數4:傳入需要綁定的數據// 通過重寫onBindViewHolder()設置更豐富的布局效果@Overridepublic void onBindViewHolder(MainViewHolder holder, int position) {super.onBindViewHolder(holder, position);// 為了展示效果,將布局的第一個數據設置為linearLayoutif (position == 0) {holder.Text.setText("Linear");}//為了展示效果,將布局里不同位置的Item進行背景顏色設置if (position < 2) {holder.itemView.setBackgroundColor(0x66cc0000 + (position - 6) * 128);} else if (position % 2 == 0) {holder.itemView.setBackgroundColor(0xaa22ff22);} else {holder.itemView.setBackgroundColor(0xccff22ff);}}};Adapter_linearLayout.setOnItemClickListener(this);// 設置每個Item的點擊事件....// 還有其他布局,由于代碼量就較多就不貼出來了。/***步驟5:將生成的LayoutHelper 交給Adapter,并綁定到RecyclerView 對象**/// 1. 設置Adapter列表(同時也是設置LayoutHelper列表)List<DelegateAdapter.Adapter> adapters = new LinkedList<>();// 2. 將上述創建的Adapter對象放入到DelegateAdapter.Adapter列表里adapters.add(Adapter_linearLayout) ;adapters.add(Adapter_StickyLayout) ;adapters.add(Adapter_ScrollFixLayout) ;adapters.add(Adapter_GridLayout) ;adapters.add(Adapter_FixLayout) ;adapters.add(Adapter_FloatLayout) ;adapters.add(Adapter_ColumnLayout) ;adapters.add(Adapter_SingleLayout) ;adapters.add(Adapter_onePlusNLayout) ;adapters.add(Adapter_StaggeredGridLayout) ;// 3. 創建DelegateAdapter對象 & 將layoutManager綁定到DelegateAdapterDelegateAdapter delegateAdapter = new DelegateAdapter(layoutManager);// 4. 將DelegateAdapter.Adapter列表綁定到DelegateAdapterdelegateAdapter.setAdapters(adapters);// 5. 將delegateAdapter綁定到recyclerViewrecyclerView.setAdapter(delegateAdapter);/***步驟6:Item之間的間隔**/recyclerView.addItemDecoration(new RecyclerView.ItemDecoration() {public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {outRect.set(5, 5, 5, 5);}});}/***步驟7:實現Item點擊事件**/// 點擊事件的回調函數@Overridepublic void onItemClick(View view, int postion) {System.out.println("點擊了第"+postion+"行");Toast.makeText(this, (String) listItem.get(postion).get("ItemTitle"), Toast.LENGTH_SHORT).show();} }效果圖
總效果圖源碼地址
Carson_Ho的Github地址:V - Layout
參考文檔:
https://github.com/alibaba/vlayout
http://pingguohe.net/2017/02/28/vlayout-design.html
作者:Carson_Ho
鏈接:https://www.jianshu.com/p/6b658c8802d1
來源:簡書
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
總結
以上是生活随笔為你收集整理的项目接入实现复杂布局的vlayout的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: vivo S16 手机“春日悠蓝”新配色
- 下一篇: 总结和分析几种判断RecyclerVie