diff --git a/README-ch.md b/README-ch.md index 6d54003d..ae4005ca 100644 --- a/README-ch.md +++ b/README-ch.md @@ -1,3 +1,5 @@ +# 注意,该项目停止维护!!! + # vlayout [English Document](README.md) @@ -21,7 +23,7 @@ VirtualLayout是一个针对RecyclerView的LayoutManager扩展, 主要提供一 ## 设计思路 -通过定制化的LayoutManager,接管整个RecyclerView的布局逻辑;LayoutManager管理了一系列LayoutHelper,LayoutHelper负责具体布局逻辑实现的地方;每一个LayoutHelper负责页面某一个范围内的组件布局;不同的LayoutHelper可以做不同的布局逻辑,因此可以在一个RecyclerView页面里提供异构的布局结构,这就能比系统自带的LinearLayoutManager、aridLayoutManager等提供更加丰富的能力。同时支持扩展LayoutHelper来提供更多的布局能力。 +通过定制化的LayoutManager,接管整个RecyclerView的布局逻辑;LayoutManager管理了一系列LayoutHelper,LayoutHelper负责具体布局逻辑实现的地方;每一个LayoutHelper负责页面某一个范围内的组件布局;不同的LayoutHelper可以做不同的布局逻辑,因此可以在一个RecyclerView页面里提供异构的布局结构,这就能比系统自带的LinearLayoutManager、GridLayoutManager等提供更加丰富的能力。同时支持扩展LayoutHelper来提供更多的布局能力。 ## 主要功能 @@ -42,10 +44,12 @@ VirtualLayout是一个针对RecyclerView的LayoutManager扩展, 主要提供一 ## 使用 -版本请参考mvn repository上的最新版本(目前最新版本是1.2.6),最新的 aar 都会发布到 jcenter 和 MavenCentral 上,确保配置了这两个仓库源,然后引入aar依赖: +**虽然 vlayout 布局灵活,然而 API 相对原始,手工维护数据及 LayoutHelper 比较麻烦,强烈建议大家使用 [Tangram-Android](https://github.com/alibaba/Tangram-Android) 来间接使用 vlayout,Tangram 具备 vlayout 里所有的功能,且隐藏了细节,通过数据配置即可搭建页面,能避免绝大多数 Issue 里提到的问题,而且重大更新维护主要基于 Tangram,包括局部刷新、响应式接口等。** + +版本请参考 [release 说明](https://github.com/alibaba/vlayout/releases)里的最新版本,最新的 aar 都会发布到 jcenter 和 MavenCentral 上,确保配置了这两个仓库源,然后引入aar依赖: ``` gradle -compile ('com.alibaba.android:vlayout:1.2.6@aar') { +compile ('com.alibaba.android:vlayout:1.2.8@aar') { transitive = true } ``` @@ -56,7 +60,7 @@ pom.xml com.alibaba.android vlayout - 1.2.6 + 1.2.8 aar ``` diff --git a/README.md b/README.md index 9f6450eb..28252a0a 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# Attention. This project is not maintained any more !!! + # vlayout [中文文档](README-ch.md) @@ -42,11 +44,11 @@ By providing a custom LayoutManager to RecyclerView, VirtualLayout is able to la ### Import Library -Please find the latest version(1.2.6 so far) in maven repository. The newest version has been upload to jcenter and MavenCentral, make sure you have added at least one of these repositories. +Please find the latest version in [release notes](https://github.com/alibaba/vlayout/releases). The newest version has been upload to jcenter and MavenCentral, make sure you have added at least one of these repositories. As follow: For gradle: ``` gradle -compile ('com.alibaba.android:vlayout:1.2.6@aar') { +compile ('com.alibaba.android:vlayout:1.2.8@aar') { transitive = true } ``` @@ -57,7 +59,7 @@ pom.xml com.alibaba.android vlayout - 1.2.6 + 1.2.8 aar ``` diff --git a/docs/VLayoutFAQ.md b/docs/VLayoutFAQ.md index fbbe4e1b..d4028eef 100644 --- a/docs/VLayoutFAQ.md +++ b/docs/VLayoutFAQ.md @@ -13,7 +13,7 @@ 因此如果没有处理好这一点,会导致 `ViewHolder` 的类型转换异常等 bug。有一篇更加详细的资料可参考:[PairFunction](http://pingguohe.net/2017/05/03/the-beauty-of-math-in-vlayout.html) -补充:后来发现一个 bug,当 `hasConsistItemType=true`,在同一位置数据变化,前后构造了不一样的 Adapter,它们返回的 itemType 一样,也会导致类型转换出错,详见:[#182](https://github.com/alibaba/vlayout/issues/182),目前采用人工保证返回不同的 itemType 来规避。 +补充:后来发现一个 bug,当 `hasConsistItemType=false`,在同一位置数据变化,前后构造了不一样的 Adapter,它们返回的 itemType 一样,也会导致类型转换出错,详见:[#182](https://github.com/alibaba/vlayout/issues/182),目前采用人工保证返回不同的 itemType 来规避。 ## 设置每种类型回收复用池的大小 在 README 里写了这么一段 demo:`viewPool.setMaxRecycledViews(0, 10);`,很多人误以为只要这么设置就可以了,实际上有多少种类型的 itemType,就得为它们分别设置复用池大小。比如: @@ -121,3 +121,94 @@ layoutHelper 根据 item 元素的位置和大小确定整块背景的大小, ## 判断 `StickyLayoutHelper` 里的 item 是否到达顶部 通过 `virtualLayoutManager.findFirstVisibleItemPosition()`,如果大于 `StickyLayoutHelper` 里的 item 的位置,说明已经到顶部。[#277](https://github.com/alibaba/vlayout/issues/277) + +## 滚动到某个 item 位置,并带偏移一个距离 +有时候自带的 scrollToPosition 方法或者 smoothScrollToPosition 方法不满足需求,可以尝试自己用动画驱动做一个滚动,下面是一种参考实现,可以基于此调整动画参数; + +``` +public class RecyclerViewFlinger implements Runnable { + + private static final String TAG = "Flinger"; + + private static final float MILLISECONDS_PER_INCH = 25.0F; + + private RecyclerView mRecyclerView; + + private int targetPosition; + + private int offset; + + private int direction = 1; + + private ScrollFinishedListener mFinishedListener; + + private int lastTop; + + private int step; + + public RecyclerViewFlinger(RecyclerView recyclerView, int targetPosition, int offset, + ScrollFinishedListener finishedListener) { +        this.mRecyclerView = recyclerView; +        this.targetPosition = targetPosition; //targetPosition 目标item的位置 +        this.offset = offset;//offset 是目标 item 距离顶部的偏移量 +        this.mFinishedListener = finishedListener;//可以设置一个滚动回调 + if (mRecyclerView != null) { + int firstVisibleItemPosition = mRecyclerView.getFirstVisiblePosition(); + direction = firstVisibleItemPosition < targetPosition ? 1 : -1; + } +        this.step = mRecyclerView.getMeasuredHeight() / 2; //滚动步长,时间等都可以细调 + } + + @Override + public void run() { + if (mRecyclerView != null) { + int firstVisibleItemPosition = mRecyclerView.getFirstVisiblePosition(); + int lastVisibleItemPosition = mRecyclerView.getLastVisiblePosition(); + boolean inscreen = targetPosition >= firstVisibleItemPosition && targetPosition <= lastVisibleItemPosition; + if (inscreen) { + View targetView = mRecyclerView.getLayoutManager().findViewByPosition(targetPosition); + if (targetView != null) { + int top = targetView.getTop(); + int dy = top - offset; + mRecyclerView.smoothScrollBy(0, dy); + if (lastTop == top) { + if (mFinishedListener != null) { + mFinishedListener.onPostExecute(targetView); + } + } else { + lastTop = top; + postOnAnimation(); + } + } + } else { + mRecyclerView.smoothScrollBy(0, step * direction); + postOnAnimation(); + } + + } + } + + public void postOnAnimation() { + if (mRecyclerView == null) { + return; + } + ViewCompat.postOnAnimation(mRecyclerView, this); + } + + public void stop() { + mFinishedListener = null; + if (mRecyclerView == null) { + return; + } + mRecyclerView.removeCallbacks(this); + } + + public interface ScrollFinishedListener { + void onPostExecute(View view); + } + +} +``` + + + diff --git a/examples/src/main/java/com/alibaba/android/vlayout/example/VLayoutActivity.java b/examples/src/main/java/com/alibaba/android/vlayout/example/VLayoutActivity.java index c6f49441..daeb7975 100644 --- a/examples/src/main/java/com/alibaba/android/vlayout/example/VLayoutActivity.java +++ b/examples/src/main/java/com/alibaba/android/vlayout/example/VLayoutActivity.java @@ -29,6 +29,9 @@ import com.alibaba.android.vlayout.RecyclablePagerAdapter; import com.alibaba.android.vlayout.VirtualLayoutManager; import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams; +import com.alibaba.android.vlayout.extend.LayoutManagerCanScrollListener; +import com.alibaba.android.vlayout.extend.PerformanceMonitor; +import com.alibaba.android.vlayout.extend.ViewLifeCycleListener; import com.alibaba.android.vlayout.layout.ColumnLayoutHelper; import com.alibaba.android.vlayout.layout.FixLayoutHelper; import com.alibaba.android.vlayout.layout.FloatLayoutHelper; @@ -109,8 +112,8 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main_activity); - mSwipeRefreshLayout = (SwipeRefreshLayout)findViewById(R.id.swipe_container); -; + mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_container); + ; mFirstText = (TextView) findViewById(R.id.first); mLastText = (TextView) findViewById(R.id.last); mCountText = (TextView) findViewById(R.id.count); @@ -119,7 +122,22 @@ protected void onCreate(Bundle savedInstanceState) { final RecyclerView recyclerView = (RecyclerView) findViewById(R.id.main_view); final VirtualLayoutManager layoutManager = new VirtualLayoutManager(this); + layoutManager.setPerformanceMonitor(new PerformanceMonitor() { + long start; + long end; + + @Override + public void recordStart(String phase, View view) { + start = System.currentTimeMillis(); + } + + @Override + public void recordEnd(String phase, View view) { + end = System.currentTimeMillis(); + Log.d("VLayoutActivity", view.getClass().getName() + " " + (end - start)); + } + }); recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { @Override public void onScrollStateChanged(RecyclerView recyclerView, int scrollState) { @@ -135,8 +153,6 @@ public void onScrolled(RecyclerView recyclerView, int i, int i2) { } }); - layoutManager.setRecycleOffset(300); - recyclerView.setLayoutManager(layoutManager); // layoutManager.setReverseLayout(true); @@ -157,6 +173,45 @@ public void getItemOffsets(Rect outRect, View view, RecyclerView parent, Recycle viewPool.setMaxRecycledViews(0, 20); + layoutManager.setRecycleOffset(300); + + // viewLifeCycleListener should be used with setRecycleOffset() + layoutManager.setViewLifeCycleListener(new ViewLifeCycleListener() { + @Override + public void onAppearing(View view) { +// Log.e("ViewLifeCycleTest", "onAppearing: " + view); + } + + @Override + public void onDisappearing(View view) { +// Log.e("ViewLifeCycleTest", "onDisappearing: " + view); + } + + @Override + public void onAppeared(View view) { +// Log.e("ViewLifeCycleTest", "onAppeared: " + view); + } + + @Override + public void onDisappeared(View view) { +// Log.e("ViewLifeCycleTest", "onDisappeared: " + view); + } + }); + + layoutManager.setLayoutManagerCanScrollListener(new LayoutManagerCanScrollListener() { + @Override + public boolean canScrollVertically() { + Log.i("vlayout", "canScrollVertically: "); + return true; + } + + @Override + public boolean canScrollHorizontally() { + Log.i("vlayout", "canScrollHorizontally: "); + return true; + } + }); + final DelegateAdapter delegateAdapter = new DelegateAdapter(layoutManager, true); recyclerView.setAdapter(delegateAdapter); @@ -264,82 +319,82 @@ public void onBindViewHolder(MainViewHolder holder, int position) { }); } - { - RangeGridLayoutHelper layoutHelper = new RangeGridLayoutHelper(4); - layoutHelper.setBgColor(Color.GREEN); - layoutHelper.setWeights(new float[]{20f, 26.665f}); - layoutHelper.setPadding(15, 15, 15, 15); - layoutHelper.setMargin(15, 50, 15, 150); - layoutHelper.setHGap(10); - layoutHelper.setVGap(10); - GridRangeStyle rangeStyle = new GridRangeStyle(); - rangeStyle.setBgColor(Color.RED); - rangeStyle.setSpanCount(2); - rangeStyle.setWeights(new float[]{46.665f}); - rangeStyle.setPadding(15, 15, 15, 15); - rangeStyle.setMargin(15, 15, 15, 15); - rangeStyle.setHGap(5); - rangeStyle.setVGap(5); - layoutHelper.addRangeStyle(0, 7, rangeStyle); +// { +// RangeGridLayoutHelper layoutHelper = new RangeGridLayoutHelper(4); +// layoutHelper.setBgColor(Color.GREEN); +// layoutHelper.setWeights(new float[]{20f, 26.665f}); +// layoutHelper.setPadding(15, 15, 15, 15); +// layoutHelper.setMargin(15, 50, 15, 150); +// layoutHelper.setHGap(10); +// layoutHelper.setVGap(10); +// GridRangeStyle rangeStyle = new GridRangeStyle(); +// rangeStyle.setBgColor(Color.RED); +// rangeStyle.setSpanCount(2); +// rangeStyle.setWeights(new float[]{46.665f}); +// rangeStyle.setPadding(15, 15, 15, 15); +// rangeStyle.setMargin(15, 15, 15, 15); +// rangeStyle.setHGap(5); +// rangeStyle.setVGap(5); +// layoutHelper.addRangeStyle(0, 7, rangeStyle); +// +// GridRangeStyle rangeStyle1 = new GridRangeStyle(); +// rangeStyle1.setBgColor(Color.YELLOW); +// rangeStyle1.setSpanCount(2); +// rangeStyle1.setWeights(new float[]{46.665f}); +// rangeStyle1.setPadding(15, 15, 15, 15); +// rangeStyle1.setMargin(15, 15, 15, 15); +// rangeStyle1.setHGap(5); +// rangeStyle1.setVGap(5); +// layoutHelper.addRangeStyle(8, 15, rangeStyle1); +// +// GridRangeStyle rangeStyle2 = new GridRangeStyle(); +// rangeStyle2.setBgColor(Color.CYAN); +// rangeStyle2.setSpanCount(2); +// rangeStyle2.setWeights(new float[]{46.665f}); +// rangeStyle2.setPadding(15, 15, 15, 15); +// rangeStyle2.setMargin(15, 15, 15, 15); +// rangeStyle2.setHGap(5); +// rangeStyle2.setVGap(5); +// layoutHelper.addRangeStyle(16, 22, rangeStyle2); +// GridRangeStyle rangeStyle3 = new GridRangeStyle(); +// rangeStyle3.setBgColor(Color.DKGRAY); +// rangeStyle3.setSpanCount(1); +// rangeStyle3.setWeights(new float[]{46.665f}); +// rangeStyle3.setPadding(15, 15, 15, 15); +// rangeStyle3.setMargin(15, 15, 15, 15); +// rangeStyle3.setHGap(5); +// rangeStyle3.setVGap(5); +// rangeStyle2.addChildRangeStyle(0, 2, rangeStyle3); +// GridRangeStyle rangeStyle4 = new GridRangeStyle(); +// rangeStyle4.setBgColor(Color.BLUE); +// rangeStyle4.setSpanCount(2); +// rangeStyle4.setWeights(new float[]{46.665f}); +// rangeStyle4.setPadding(15, 15, 15, 15); +// rangeStyle4.setMargin(15, 15, 15, 15); +// rangeStyle4.setHGap(5); +// rangeStyle4.setVGap(5); +// rangeStyle2.addChildRangeStyle(3, 6, rangeStyle4); +// +// GridRangeStyle rangeStyle5 = new GridRangeStyle(); +// rangeStyle5.setBgColor(Color.RED); +// rangeStyle5.setSpanCount(2); +// rangeStyle5.setPadding(15, 15, 15, 15); +// rangeStyle5.setMargin(15, 15, 15, 15); +// rangeStyle5.setHGap(5); +// rangeStyle5.setVGap(5); +// layoutHelper.addRangeStyle(23, 30, rangeStyle5); +// GridRangeStyle rangeStyle6 = new GridRangeStyle(); +// rangeStyle6.setBgColor(Color.MAGENTA); +// rangeStyle6.setSpanCount(2); +// rangeStyle6.setPadding(15, 15, 15, 15); +// rangeStyle6.setMargin(15, 15, 15, 15); +// rangeStyle6.setHGap(5); +// rangeStyle6.setVGap(5); +// rangeStyle5.addChildRangeStyle(0, 7, rangeStyle6); +// +// adapters.add(new SubAdapter(this, layoutHelper, 23)); +// } - GridRangeStyle rangeStyle1 = new GridRangeStyle(); - rangeStyle1.setBgColor(Color.YELLOW); - rangeStyle1.setSpanCount(2); - rangeStyle1.setWeights(new float[]{46.665f}); - rangeStyle1.setPadding(15, 15, 15, 15); - rangeStyle1.setMargin(15, 15, 15, 15); - rangeStyle1.setHGap(5); - rangeStyle1.setVGap(5); - layoutHelper.addRangeStyle(8, 15, rangeStyle1); - - GridRangeStyle rangeStyle2 = new GridRangeStyle(); - rangeStyle2.setBgColor(Color.CYAN); - rangeStyle2.setSpanCount(2); - rangeStyle2.setWeights(new float[]{46.665f}); - rangeStyle2.setPadding(15, 15, 15, 15); - rangeStyle2.setMargin(15, 15, 15, 15); - rangeStyle2.setHGap(5); - rangeStyle2.setVGap(5); - layoutHelper.addRangeStyle(16, 22, rangeStyle2); - GridRangeStyle rangeStyle3 = new GridRangeStyle(); - rangeStyle3.setBgColor(Color.DKGRAY); - rangeStyle3.setSpanCount(1); - rangeStyle3.setWeights(new float[]{46.665f}); - rangeStyle3.setPadding(15, 15, 15, 15); - rangeStyle3.setMargin(15, 15, 15, 15); - rangeStyle3.setHGap(5); - rangeStyle3.setVGap(5); - rangeStyle2.addChildRangeStyle(0, 2, rangeStyle3); - GridRangeStyle rangeStyle4 = new GridRangeStyle(); - rangeStyle4.setBgColor(Color.BLUE); - rangeStyle4.setSpanCount(2); - rangeStyle4.setWeights(new float[]{46.665f}); - rangeStyle4.setPadding(15, 15, 15, 15); - rangeStyle4.setMargin(15, 15, 15, 15); - rangeStyle4.setHGap(5); - rangeStyle4.setVGap(5); - rangeStyle2.addChildRangeStyle(3, 6, rangeStyle4); - - GridRangeStyle rangeStyle5 = new GridRangeStyle(); - rangeStyle5.setBgColor(Color.RED); - rangeStyle5.setSpanCount(2); - rangeStyle5.setPadding(15, 15, 15, 15); - rangeStyle5.setMargin(15, 15, 15, 15); - rangeStyle5.setHGap(5); - rangeStyle5.setVGap(5); - layoutHelper.addRangeStyle(23, 30, rangeStyle5); - GridRangeStyle rangeStyle6 = new GridRangeStyle(); - rangeStyle6.setBgColor(Color.MAGENTA); - rangeStyle6.setSpanCount(2); - rangeStyle6.setPadding(15, 15, 15, 15); - rangeStyle6.setMargin(15, 15, 15, 15); - rangeStyle6.setHGap(5); - rangeStyle6.setVGap(5); - rangeStyle5.addChildRangeStyle(0, 7, rangeStyle6); - - adapters.add(new SubAdapter(this, layoutHelper, 23)); - } - { SingleLayoutHelper layoutHelper = new SingleLayoutHelper(); layoutHelper.setBgColor(Color.BLUE); @@ -616,7 +671,7 @@ public void onBindViewHolder(MainViewHolder holder, int position) { } adapters.add( - new FooterAdapter(recyclerView, VLayoutActivity.this, new GridLayoutHelper(1), 1)); + new FooterAdapter(recyclerView, VLayoutActivity.this, new GridLayoutHelper(1), 1)); delegateAdapter.setAdapters(adapters); @@ -626,8 +681,8 @@ public void onBindViewHolder(MainViewHolder holder, int position) { trigger = new Runnable() { @Override public void run() { - //recyclerView.scrollToPosition(22); - //recyclerView.getAdapter().notifyDataSetChanged(); + //recyclerView.scrollToPosition(22); + //recyclerView.getAdapter().notifyDataSetChanged(); //mainHandler.postDelayed(trigger, 1000); //List newAdapters = new ArrayList<>(); //newAdapters.add((new SubAdapter(VLayoutActivity.this, new ColumnLayoutHelper(), 3))); @@ -658,7 +713,6 @@ public void onClick(View v) { }); - mainHandler.postDelayed(trigger, 1000); mSwipeRefreshLayout.setOnRefreshListener(new OnRefreshListener() { diff --git a/gradle.properties b/gradle.properties index 13afc4cc..e2f89383 100644 --- a/gradle.properties +++ b/gradle.properties @@ -44,9 +44,9 @@ GROUP=com.alibaba.android ARTIFACT=vlayout VERSION=1 -VERSION_NAME=1.2.6 +VERSION_NAME=1.2.39 PACKAGING_TYPE=aar useNewSupportLibrary=true -systemProp.compileSdkVersion=23 -systemProp.targetSdkVersion=23 -systemProp.buildToolsVersion=23.0.2 \ No newline at end of file +systemProp.compileSdkVersion=26 +systemProp.targetSdkVersion=26 +systemProp.buildToolsVersion=26.0.2 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index f783c8f2..3ca3e4e1 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -27,4 +27,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/jcenterDeploy.gradle b/jcenterDeploy.gradle index fcb5618a..e1d7a7c1 100644 --- a/jcenterDeploy.gradle +++ b/jcenterDeploy.gradle @@ -86,14 +86,21 @@ artifacts { } // Bintray -//Properties properties = new Properties() -//properties.load(project.rootProject.file('local.properties').newDataInputStream()) +Properties properties = new Properties() +File localProperties = project.rootProject.file('local.properties') +if (localProperties.exists()) { + properties.load(project.rootProject.file('local.properties').newDataInputStream()) +} bintray { -// user = properties.getProperty("bintray.user") -// key = properties.getProperty("bintray.apikey") - user = project.hasProperty('bintrayUser') ? project.getProperty('bintrayUser') : "" - key = project.hasProperty('bintrayApikey') ? project.getProperty('bintrayApikey') : "" + user = properties.getProperty("bintray.user") + key = properties.getProperty("bintray.apikey") + if (!user) { + user = project.hasProperty('bintrayUser') ? project.getProperty('bintrayUser') : "" + } + if (!key) { + key = project.hasProperty('bintrayApikey') ? project.getProperty('bintrayApikey') : "" + } configurations = ['archives'] pkg { @@ -109,10 +116,25 @@ bintray { desc = libraryDescription gpg { sign = true //Determines whether to GPG sign the files. The default is false -// passphrase = properties.getProperty("bintray.gpg.password") - passphrase = project.hasProperty('bintrayGPG') ? project.getProperty('bintrayGPG') : "" + passphrase = properties.getProperty("bintray.gpg.password") + if (!passphrase) { + passphrase = project.hasProperty('bintrayGPG') ? project.getProperty('bintrayGPG') : "" + } //Optional. The passphrase for GPG signing' } + + mavenCentralSync { + sync = true + user = properties.getProperty('bintray.oss.user') + if (!user) { + user = project.hasProperty('bintray.oss.user') ? project.getProperty('bintray.oss.user') : "" + } + password = properties.getProperty('bintray.oss.password') + if (!password) { + password = project.hasProperty('bintray.oss.password') ? project.getProperty('bintray.oss.password') : "" + } + close = '1' + } } } } diff --git a/vlayout/build.gradle b/vlayout/build.gradle index 1a2e32cd..e439533c 100644 --- a/vlayout/build.gradle +++ b/vlayout/build.gradle @@ -24,20 +24,41 @@ apply plugin: 'com.android.library' +buildscript { + repositories { + maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } + maven { url "http://oss.jfrog.org/oss-snapshot-local/" } + mavenCentral() + jcenter() + } + + dependencies { + classpath 'com.android.tools.build:gradle:2.3.0' + } +} + +repositories { + maven { url 'https://oss.sonatype.org/content/repositories/snapshots/' } + maven { url "http://oss.jfrog.org/oss-snapshot-local/" } + jcenter() + mavenLocal() +} + + ext { bintrayRepo = 'Tangram' bintrayName = 'vlayout' - publishedGroupId = GROUP - libraryName = ARTIFACT - artifact = ARTIFACT + publishedGroupId = project.hasProperty('GROUP') ? GROUP : '' + libraryName = project.hasProperty('ARTIFACT') ? ARTIFACT : '' + artifact = project.hasProperty('ARTIFACT') ? ARTIFACT : '' libraryDescription = 'Project vlayout is a powerfull LayoutManager extension for RecyclerView, it provides a group of layouts for RecyclerView. Make it able to handle a complicate situation when grid, list and other layouts in the same recyclerview.' siteUrl = 'https://github.com/alibaba/vlayout' gitUrl = 'https://github.com/alibaba/vlayout.git' - libraryVersion = VERSION_NAME + libraryVersion = project.hasProperty('VERSION_NAME') ? VERSION_NAME : '' developerId = 'longerian' developerName = 'longerian' @@ -71,13 +92,19 @@ android { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } } + } + } + + lintOptions { + abortOnError false + } + } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) // compile project(':extension') - if (useNewSupportLibrary == true) { + if (project.hasProperty('useNewSupportLibrary')) { compile 'com.android.support:recyclerview-v7:25.2.0@aar' compile('com.android.support:support-v4:25.2.0@aar') compile 'com.android.support:support-annotations:25.2.0' diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/Cantor.java b/vlayout/src/main/java/com/alibaba/android/vlayout/Cantor.java index 73b2d7e8..1729b0b4 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/Cantor.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/Cantor.java @@ -28,11 +28,11 @@ public static void reverseCantor(long cantor, long[] result) { result = new long[2]; } // reverse Cantor Function - int w = (int) (Math.floor(Math.sqrt(8 * cantor + 1) - 1) / 2); - int t = (w * w + w) / 2; + long w = (long) (Math.floor(Math.sqrt(8 * cantor + 1) - 1) / 2); + long t = (w * w + w) / 2; - int k2 = (int)(cantor - t); - int k1 = w - k2; + long k2 = cantor - t; + long k1 = w - k2; result[0] = k1; result[1] = k2; } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/DelegateAdapter.java b/vlayout/src/main/java/com/alibaba/android/vlayout/DelegateAdapter.java index 0ddf2085..1373c750 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/DelegateAdapter.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/DelegateAdapter.java @@ -131,13 +131,18 @@ public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType @SuppressWarnings("unchecked") @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { + Pair pair = findAdapterByPosition(position); + if (pair == null) { + return; + } + pair.second.onBindViewHolder(holder, position - pair.first.mStartPosition); + pair.second.onBindViewHolderWithOffset(holder, position - pair.first.mStartPosition, position); } @SuppressWarnings("unchecked") @Override public void onBindViewHolder(RecyclerView.ViewHolder holder, int position, List payloads) { - super.onBindViewHolder(holder, position, payloads); Pair pair = findAdapterByPosition(position); if (pair == null) { return; @@ -216,7 +221,7 @@ public void onViewRecycled(RecyclerView.ViewHolder holder) { super.onViewRecycled(holder); int position = holder.getPosition(); - if (position > 0) { + if (position >= 0) { Pair pair = findAdapterByPosition(position); if (pair != null) { pair.second.onViewRecycled(holder); @@ -230,7 +235,7 @@ public void onViewRecycled(RecyclerView.ViewHolder holder) { public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { super.onViewAttachedToWindow(holder); int position = holder.getPosition(); - if (position > 0) { + if (position >= 0) { Pair pair = findAdapterByPosition(position); if (pair != null) { pair.second.onViewAttachedToWindow(holder); @@ -243,7 +248,7 @@ public void onViewAttachedToWindow(RecyclerView.ViewHolder holder) { public void onViewDetachedFromWindow(RecyclerView.ViewHolder holder) { super.onViewDetachedFromWindow(holder); int position = holder.getPosition(); - if (position > 0) { + if (position >= 0) { Pair pair = findAdapterByPosition(position); if (pair != null) { pair.second.onViewDetachedFromWindow(holder); @@ -631,7 +636,7 @@ public SimpleViewAdapter(@NonNull View view) { @Override public LayoutHelper onCreateLayoutHelper() { - return new SingleLayoutHelper(); + return mLayoutHelper; } @Override diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/ExposeLinearLayoutManagerEx.java b/vlayout/src/main/java/com/alibaba/android/vlayout/ExposeLinearLayoutManagerEx.java index ec3d5f0a..b569c353 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/ExposeLinearLayoutManagerEx.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/ExposeLinearLayoutManagerEx.java @@ -129,7 +129,7 @@ class ExposeLinearLayoutManagerEx extends LinearLayoutManager { private final Method mEnsureLayoutStateMethod; - private int recycleOffset; + protected int recycleOffset; /** * Creates a vertical LinearLayoutManager @@ -1155,8 +1155,7 @@ protected int fill(RecyclerView.Recycler recycler, LayoutState layoutState, } recycleByLayoutStateExpose(recycler, layoutState); } - int remainingSpace = layoutState.mAvailable + layoutState.mExtra + ( - layoutState.mLayoutDirection == LayoutState.LAYOUT_START ? 0 : recycleOffset); //FIXME opt here to fix bg and shake + int remainingSpace = layoutState.mAvailable + layoutState.mExtra + recycleOffset; while (remainingSpace > 0 && layoutState.hasMore(state)) { layoutChunkResultCache.resetInternal(); layoutChunk(recycler, state, layoutState, layoutChunkResultCache); @@ -1739,11 +1738,22 @@ public void assignFromView(View child) { if (mLayoutFromEnd) { mCoordinate = mOrientationHelper.getDecoratedEnd(child) + computeAlignOffset(child, mLayoutFromEnd, true) + mOrientationHelper.getTotalSpaceChange(); + if (DEBUG) { + Log.d(TAG, "1 mLayoutFromEnd " + mLayoutFromEnd + " mOrientationHelper.getDecoratedEnd(child) " + + mOrientationHelper.getDecoratedEnd(child) + " computeAlignOffset(child, mLayoutFromEnd, true) " + computeAlignOffset(child, mLayoutFromEnd, true)); + } } else { mCoordinate = mOrientationHelper.getDecoratedStart(child) + computeAlignOffset(child, mLayoutFromEnd, true); + if (DEBUG) { + Log.d(TAG, "2 mLayoutFromEnd " + mLayoutFromEnd + " mOrientationHelper.getDecoratedStart(child) " + + mOrientationHelper.getDecoratedStart(child) + " computeAlignOffset(child, mLayoutFromEnd, true) " + computeAlignOffset(child, mLayoutFromEnd, true)); + } } mPosition = getPosition(child); + if (DEBUG) { + Log.d(TAG, "position " + mPosition + " mCoordinate " + mCoordinate); + } } } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/LayoutHelperFinder.java b/vlayout/src/main/java/com/alibaba/android/vlayout/LayoutHelperFinder.java index 76ddd28c..09f876df 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/LayoutHelperFinder.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/LayoutHelperFinder.java @@ -32,7 +32,7 @@ /** * LayoutHelperFinder provides as repository of LayoutHelpers */ -public abstract class LayoutHelperFinder implements Iterable { +public abstract class LayoutHelperFinder { /** * Put layouts into the finder @@ -57,10 +57,10 @@ public abstract class LayoutHelperFinder implements Iterable { protected abstract List getLayoutHelpers(); /** - * Get iterator that in reverse order + * Get layoutHelpers that in reverse order * * @return */ - protected abstract Iterable reverse(); + protected abstract List reverse(); } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/RangeLayoutHelperFinder.java b/vlayout/src/main/java/com/alibaba/android/vlayout/RangeLayoutHelperFinder.java index a151d4d5..3201b7f1 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/RangeLayoutHelperFinder.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/RangeLayoutHelperFinder.java @@ -27,6 +27,7 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; @@ -35,7 +36,7 @@ import java.util.ListIterator; /** - An implement of {@link LayoutHelperFinder} which finds layoutHelpers by position + * An implement of {@link LayoutHelperFinder} which finds layoutHelpers by position */ public class RangeLayoutHelperFinder extends LayoutHelperFinder { @@ -45,6 +46,11 @@ public class RangeLayoutHelperFinder extends LayoutHelperFinder { @NonNull private List mLayoutHelpers = new LinkedList<>(); + @NonNull + private List mReverseLayoutHelpers =new LinkedList<>(); + + private LayoutHelperItem[] mSortedLayoutHelpers = null; + @NonNull private Comparator mLayoutHelperItemComparator = new Comparator() { @Override @@ -54,31 +60,8 @@ public int compare(LayoutHelperItem lhs, LayoutHelperItem rhs) { }; @Override - public Iterator iterator() { - return Collections.unmodifiableList(mLayoutHelpers).iterator(); - } - - @Override - protected Iterable reverse() { - final ListIterator i = mLayoutHelpers.listIterator(mLayoutHelpers.size()); - return new Iterable() { - @Override - public Iterator iterator() { - return new Iterator() { - public boolean hasNext() { - return i.hasPrevious(); - } - - public LayoutHelper next() { - return i.previous(); - } - - public void remove() { - i.remove(); - } - }; - } - }; + protected List reverse() { + return mReverseLayoutHelpers; } /** @@ -87,44 +70,54 @@ public void remove() { @Override public void setLayouts(@Nullable List layouts) { mLayoutHelpers.clear(); + mReverseLayoutHelpers.clear(); mLayoutHelperItems.clear(); if (layouts != null) { - for (LayoutHelper helper : layouts) { + ListIterator iterator = layouts.listIterator(); + LayoutHelper helper = null; + while (iterator.hasNext()) { + helper = iterator.next(); mLayoutHelpers.add(helper); mLayoutHelperItems.add(new LayoutHelperItem(helper)); } - Collections.sort(mLayoutHelperItems, mLayoutHelperItemComparator); + while (iterator.hasPrevious()) { + mReverseLayoutHelpers.add(iterator.previous()); + } + + // Collections.sort(mLayoutHelperItems, mLayoutHelperItemComparator); + mSortedLayoutHelpers = mLayoutHelperItems.toArray(new LayoutHelperItem[mLayoutHelperItems.size()]); + Arrays.sort(mSortedLayoutHelpers, mLayoutHelperItemComparator); } } @NonNull @Override protected List getLayoutHelpers() { - return Collections.unmodifiableList(mLayoutHelpers); + return mLayoutHelpers; } @Nullable @Override public LayoutHelper getLayoutHelper(int position) { - final int count = mLayoutHelperItems.size(); - if (count == 0) { + if (mSortedLayoutHelpers == null || mSortedLayoutHelpers.length == 0) { return null; } + final int count = mSortedLayoutHelpers.length; int s = 0, e = count - 1, m; LayoutHelperItem rs = null; - // binary search range while (s <= e) { m = (s + e) / 2; - rs = mLayoutHelperItems.get(m); + rs = mSortedLayoutHelpers[m]; if (rs.getStartPosition() > position) { e = m - 1; } else if (rs.getEndPosition() < position) { s = m + 1; - } else if (rs.getStartPosition() <= position && rs.getEndPosition() >= position) + } else if (rs.getStartPosition() <= position && rs.getEndPosition() >= position) { break; + } rs = null; } @@ -132,7 +125,6 @@ public LayoutHelper getLayoutHelper(int position) { return rs == null ? null : rs.layoutHelper; } - static class LayoutHelperItem { LayoutHelperItem(LayoutHelper helper) { diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/RecyclablePagerAdapter.java b/vlayout/src/main/java/com/alibaba/android/vlayout/RecyclablePagerAdapter.java index 8bc39cf2..2f88e85f 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/RecyclablePagerAdapter.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/RecyclablePagerAdapter.java @@ -81,7 +81,14 @@ public Object instantiateItem(ViewGroup container, int position) { //so the attributes of layoutParam such as widthFactor and position will also be reused, //while these attributes should be reset to default value during reused. //Considering ViewPager.LayoutParams has a few inner attributes which could not be modify outside, we provide a new instance here - container.addView(holder.itemView, new ViewPager.LayoutParams()); + + ViewPager.LayoutParams layoutParams = new ViewPager.LayoutParams(); + if (holder.itemView.getLayoutParams() != null) { + layoutParams.width = holder.itemView.getLayoutParams().width; + layoutParams.height = holder.itemView.getLayoutParams().height; + } + + container.addView(holder.itemView, layoutParams); return holder; } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/VirtualLayoutManager.java b/vlayout/src/main/java/com/alibaba/android/vlayout/VirtualLayoutManager.java index e7e17073..257d960c 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/VirtualLayoutManager.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/VirtualLayoutManager.java @@ -24,19 +24,6 @@ package com.alibaba.android.vlayout; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import com.alibaba.android.vlayout.layout.BaseLayoutHelper; -import com.alibaba.android.vlayout.layout.DefaultLayoutHelper; -import com.alibaba.android.vlayout.layout.FixAreaAdjuster; -import com.alibaba.android.vlayout.layout.FixAreaLayoutHelper; - import android.content.Context; import android.graphics.Rect; import android.os.Build; @@ -52,6 +39,24 @@ import android.view.ViewGroup; import android.view.ViewParent; +import com.alibaba.android.vlayout.extend.LayoutManagerCanScrollListener; +import com.alibaba.android.vlayout.extend.PerformanceMonitor; +import com.alibaba.android.vlayout.extend.ViewLifeCycleHelper; +import com.alibaba.android.vlayout.extend.ViewLifeCycleListener; +import com.alibaba.android.vlayout.layout.BaseLayoutHelper; +import com.alibaba.android.vlayout.layout.DefaultLayoutHelper; +import com.alibaba.android.vlayout.layout.FixAreaAdjuster; +import com.alibaba.android.vlayout.layout.FixAreaLayoutHelper; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + /** * A {@link android.support.v7.widget.RecyclerView.LayoutManager} implementation which provides @@ -67,10 +72,12 @@ public class VirtualLayoutManager extends ExposeLinearLayoutManagerEx implements LayoutManagerHelper { protected static final String TAG = "VirtualLayoutManager"; + private static final String PHASE_MEASURE = "measure"; + private static final String PHASE_LAYOUT = "layout"; private static final String TRACE_LAYOUT = "VLM onLayoutChildren"; private static final String TRACE_SCROLL = "VLM scroll"; - private static boolean sDebuggable = false; + public static boolean sDebuggable = false; public static void enableDebugging(boolean isDebug) { sDebuggable = isDebug; @@ -90,10 +97,33 @@ public static void enableDebugging(boolean isDebug) { private boolean mNestedScrolling = false; + private boolean mCanScrollHorizontally; + + private boolean mCanScrollVertically; + + private LayoutManagerCanScrollListener layoutManagerCanScrollListener; + private boolean mEnableMarginOverlapping = false; private int mMaxMeasureSize = -1; + private PerformanceMonitor mPerformanceMonitor; + + private ViewLifeCycleHelper mViewLifeCycleHelper; + + private Comparator, Integer>> mRangeComparator = new Comparator, Integer>>() { + @Override + public int compare(Pair, Integer> a, Pair, Integer> b) { + if (a == null && b == null) return 0; + if (a == null) return -1; + if (b == null) return 1; + + Range lr = a.first; + Range rr = b.first; + + return lr.getLower() - rr.getLower(); + } + }; public VirtualLayoutManager(@NonNull final Context context) { this(context, VERTICAL); @@ -118,9 +148,14 @@ public VirtualLayoutManager(@NonNull final Context context, int orientation, boo super(context, orientation, reverseLayout); this.mOrientationHelper = OrientationHelperEx.createOrientationHelper(this, orientation); this.mSecondaryOrientationHelper = OrientationHelperEx.createOrientationHelper(this, orientation == VERTICAL ? HORIZONTAL : VERTICAL); + this.mCanScrollVertically = super.canScrollVertically(); + this.mCanScrollHorizontally = super.canScrollHorizontally(); setHelperFinder(new RangeLayoutHelperFinder()); } + public void setPerformanceMonitor(PerformanceMonitor performanceMonitor) { + mPerformanceMonitor = performanceMonitor; + } public void setNoScrolling(boolean noScrolling) { this.mNoScrolling = noScrolling; @@ -129,6 +164,18 @@ public void setNoScrolling(boolean noScrolling) { mSpaceMeasuring = false; } + public void setCanScrollVertically(boolean canScrollVertically) { + this.mCanScrollVertically = canScrollVertically; + } + + public void setCanScrollHorizontally(boolean canScrollHorizontally) { + this.mCanScrollHorizontally = canScrollHorizontally; + } + + public void setLayoutManagerCanScrollListener(LayoutManagerCanScrollListener layoutManagerCanScrollListener) { + this.layoutManagerCanScrollListener = layoutManagerCanScrollListener; + } + public void setNestedScrolling(boolean nestedScrolling) { setNestedScrolling(nestedScrolling, -1); } @@ -149,8 +196,13 @@ public void setHelperFinder(@NonNull final LayoutHelperFinder finder) { List helpers = new LinkedList<>(); if (this.mHelperFinder != null) { - for (LayoutHelper helper : mHelperFinder) { - helpers.add(helper); + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); + helpers.add(layoutHelper); + } } @@ -183,16 +235,19 @@ public void setFixOffset(int left, int top, int right, int bottom) { * @param helpers group of layoutHelpers */ public void setLayoutHelpers(@Nullable List helpers) { - for (LayoutHelper helper : mHelperFinder) { + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator it0 = layoutHelpers.iterator(); + while (it0.hasNext()) { + LayoutHelper helper = it0.next(); oldHelpersSet.put(System.identityHashCode(helper), helper); } // set ranges if (helpers != null) { int start = 0; - for (int i = 0; i < helpers.size(); i++) { - LayoutHelper helper = helpers.get(i); - + Iterator it1 = helpers.iterator(); + while (it1.hasNext()) { + LayoutHelper helper = it1.next(); if (helper instanceof FixAreaLayoutHelper) { ((FixAreaLayoutHelper) helper).setAdjuster(mFixAreaAdjustor); } @@ -214,11 +269,13 @@ public void setLayoutHelpers(@Nullable List helpers) { this.mHelperFinder.setLayouts(helpers); - for (LayoutHelper helper : mHelperFinder) { - newHelpersSet.put(System.identityHashCode(helper), helper); + layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + while (iterator.hasNext()) { + LayoutHelper layoutHelper = iterator.next(); + newHelpersSet.put(System.identityHashCode(layoutHelper), layoutHelper); } - for (Iterator> it = oldHelpersSet.entrySet().iterator(); it.hasNext(); ) { Map.Entry entry = it.next(); Integer key = entry.getKey(); @@ -332,7 +389,11 @@ public void onAnchorReady(RecyclerView.State state, ExposeLinearLayoutManagerEx. mTempAnchorInfoWrapper.position = anchorInfo.mPosition; mTempAnchorInfoWrapper.coordinate = anchorInfo.mCoordinate; - for (LayoutHelper layoutHelper : mHelperFinder) { + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); layoutHelper.onRefreshLayout(state, mTempAnchorInfoWrapper, this); } } @@ -400,7 +461,11 @@ public int obtainExtraMargin(View child, boolean isLayoutEnd, boolean useAnchor) private void runPreLayout(RecyclerView.Recycler recycler, RecyclerView.State state) { if (mNested == 0) { - for (LayoutHelper layoutHelper : mHelperFinder.reverse()) { + List reverseLayoutHelpers = mHelperFinder.reverse(); + Iterator iterator = reverseLayoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); layoutHelper.beforeLayout(recycler, state, this); } } @@ -414,7 +479,11 @@ private void runPostLayout(RecyclerView.Recycler recycler, RecyclerView.State st mNested = 0; final int startPosition = findFirstVisibleItemPosition(); final int endPosition = findLastVisibleItemPosition(); - for (LayoutHelper layoutHelper : mHelperFinder) { + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); try { layoutHelper.afterLayout(recycler, state, startPosition, endPosition, scrolled, this); } catch (Exception e) { @@ -423,6 +492,10 @@ private void runPostLayout(RecyclerView.Recycler recycler, RecyclerView.State st } } } + + if (null != mViewLifeCycleHelper) { + mViewLifeCycleHelper.checkViewStatusInScreen(); + } } } @@ -566,8 +639,12 @@ public void onScrollStateChanged(int state) { int startPosition = findFirstVisibleItemPosition(); int endPosition = findLastVisibleItemPosition(); - for (LayoutHelper helper : mHelperFinder) { - helper.onScrollStateChanged(state, startPosition, endPosition, this); + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); + layoutHelper.onScrollStateChanged(state, startPosition, endPosition, this); } } @@ -575,22 +652,47 @@ public void onScrollStateChanged(int state) { public void offsetChildrenHorizontal(int dx) { super.offsetChildrenHorizontal(dx); - for (LayoutHelper helper : mHelperFinder) { - helper.onOffsetChildrenHorizontal(dx, this); + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); + layoutHelper.onOffsetChildrenHorizontal(dx, this); + } } @Override public void offsetChildrenVertical(int dy) { super.offsetChildrenVertical(dy); - for (LayoutHelper helper : mHelperFinder) { - helper.onOffsetChildrenVertical(dy, this); + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); + layoutHelper.onOffsetChildrenVertical(dy, this); } + + if (null != mViewLifeCycleHelper) { + mViewLifeCycleHelper.checkViewStatusInScreen(); + } + } + + public void setViewLifeCycleListener(@NonNull ViewLifeCycleListener viewLifeCycleListener) { + if (null == viewLifeCycleListener) { + throw new IllegalArgumentException("ViewLifeCycleListener should not be null!"); + } + + mViewLifeCycleHelper = new ViewLifeCycleHelper(this, viewLifeCycleListener); + } + + public int getVirtualLayoutDirection() { + return mLayoutState.mLayoutDirection; } private LayoutStateWrapper mTempLayoutStateWrapper = new LayoutStateWrapper(); - private List, Integer>> mRangeLengths = new LinkedList<>(); + private List, Integer>> mRangeLengths = new ArrayList<>(); @Nullable private int findRangeLength(@NonNull final Range range) { @@ -644,7 +746,9 @@ protected void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State st // no item consumed if (layoutState.mCurrentPosition == position) { - Log.w(TAG, "layoutHelper[" + layoutHelper.getClass().getSimpleName() + "@" + layoutHelper.toString() + "] consumes no item!"); + if (sDebuggable) { + Log.w(TAG, "layoutHelper[" + layoutHelper.getClass().getSimpleName() + "@" + layoutHelper.toString() + "] consumes no item!"); + } // break as no item consumed result.mFinished = true; } else { @@ -665,19 +769,7 @@ protected void layoutChunk(RecyclerView.Recycler recycler, RecyclerView.State st } mRangeLengths.add(Pair.create(range, consumed)); - Collections.sort(mRangeLengths, new Comparator, Integer>>() { - @Override - public int compare(Pair, Integer> a, Pair, Integer> b) { - if (a == null && b == null) return 0; - if (a == null) return -1; - if (b == null) return 1; - - Range lr = a.first; - Range rr = b.first; - - return lr.getLower() - rr.getLower(); - } - }); + Collections.sort(mRangeLengths, mRangeComparator); } } @@ -784,8 +876,12 @@ public void onItemsMoved(RecyclerView recyclerView, int from, int to, int itemCo @Override public void onItemsChanged(RecyclerView recyclerView) { - for (LayoutHelper helper : mHelperFinder) { - helper.onItemsChanged(this); + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); + layoutHelper.onItemsChanged(this); } // setLayoutHelpers(mHelperFinder.getLayoutHelpers()); @@ -837,8 +933,12 @@ public void onAttachedToWindow(RecyclerView view) { public void onDetachedFromWindow(RecyclerView view, RecyclerView.Recycler recycler) { super.onDetachedFromWindow(view, recycler); - for (LayoutHelper helper : mHelperFinder) { - helper.clear(this); + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); + layoutHelper.clear(this); } mRecyclerView = null; @@ -1069,8 +1169,12 @@ public List getFixedViews() { // TODO: support zIndex? List views = new LinkedList<>(); - for (LayoutHelper helper : mHelperFinder) { - View fixedView = helper.getFixedView(); + List layoutHelpers = mHelperFinder.getLayoutHelpers(); + Iterator iterator = layoutHelpers.iterator(); + LayoutHelper layoutHelper = null; + while (iterator.hasNext()) { + layoutHelper = iterator.next(); + View fixedView = layoutHelper.getFixedView(); if (fixedView != null) { views.add(fixedView); } @@ -1230,25 +1334,45 @@ public int getChildMeasureSpec(int parentSize, int size, boolean canScroll) { @Override public boolean canScrollHorizontally() { - return super.canScrollHorizontally() && !mNoScrolling; + boolean ret = true; + if (layoutManagerCanScrollListener != null) { + ret = ret && layoutManagerCanScrollListener.canScrollHorizontally(); + } + return mCanScrollHorizontally && !mNoScrolling && ret; } @Override public boolean canScrollVertically() { - return super.canScrollVertically() && !mNoScrolling; + boolean ret = true; + if (layoutManagerCanScrollListener != null) { + ret = ret && layoutManagerCanScrollListener.canScrollVertically(); + } + return mCanScrollVertically && !mNoScrolling && ret; } @Override public void layoutChildWithMargins(View child, int left, int top, int right, int bottom) { final ViewGroup.MarginLayoutParams lp = (ViewGroup.MarginLayoutParams) child.getLayoutParams(); + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordStart(PHASE_LAYOUT, child); + } layoutDecorated(child, left + lp.leftMargin, top + lp.topMargin, right - lp.rightMargin, bottom - lp.bottomMargin); + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordEnd(PHASE_LAYOUT, child); + } } @Override public void layoutChild(View child, int left, int top, int right, int bottom) { + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordStart(PHASE_LAYOUT, child); + } layoutDecorated(child, left, top, right, bottom); + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordEnd(PHASE_LAYOUT, child); + } } @Override @@ -1366,17 +1490,34 @@ private void measureChildWithDecorations(View child, int widthSpec, int heightSp calculateItemDecorationsForChild(child, mDecorInsets); widthSpec = updateSpecWithExtra(widthSpec, mDecorInsets.left, mDecorInsets.right); heightSpec = updateSpecWithExtra(heightSpec, mDecorInsets.top, mDecorInsets.bottom); + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordStart(PHASE_MEASURE, child); + } child.measure(widthSpec, heightSpec); + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordEnd(PHASE_MEASURE, child); + } } private void measureChildWithDecorationsAndMargin(View child, int widthSpec, int heightSpec) { calculateItemDecorationsForChild(child, mDecorInsets); RecyclerView.LayoutParams lp = (RecyclerView.LayoutParams) child.getLayoutParams(); - widthSpec = updateSpecWithExtra(widthSpec, lp.leftMargin + mDecorInsets.left, - lp.rightMargin + mDecorInsets.right); - heightSpec = updateSpecWithExtra(heightSpec, lp.topMargin + mDecorInsets.top, - lp.bottomMargin + mDecorInsets.bottom); + + if (getOrientation() == VERTICAL) { + widthSpec = updateSpecWithExtra(widthSpec, lp.leftMargin + mDecorInsets.left, + lp.rightMargin + mDecorInsets.right); + } + if (getOrientation() == HORIZONTAL) { + heightSpec = updateSpecWithExtra(heightSpec, mDecorInsets.top, + mDecorInsets.bottom); + } + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordStart(PHASE_MEASURE, child); + } child.measure(widthSpec, heightSpec); + if (mPerformanceMonitor != null) { + mPerformanceMonitor.recordEnd(PHASE_MEASURE, child); + } } /** @@ -1425,8 +1566,11 @@ public View findViewByPosition(int position) { @Override public void recycleView(View view) { if (mRecyclerView != null) { - RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(view); - mRecyclerView.getRecycledViewPool().putRecycledView(holder); + ViewParent parent = view.getParent(); + if (parent != null && parent == mRecyclerView) { + RecyclerView.ViewHolder holder = mRecyclerView.getChildViewHolder(view); + mRecyclerView.getRecycledViewPool().putRecycledView(holder); + } } } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/extend/InnerRecycledViewPool.java b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/InnerRecycledViewPool.java index 1c9e5081..b51981e5 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/extend/InnerRecycledViewPool.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/InnerRecycledViewPool.java @@ -30,9 +30,6 @@ import android.view.View; import java.io.Closeable; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; /** * Wrapping original RecycledViewPool to provides destroy callback on Views @@ -44,7 +41,7 @@ public final class InnerRecycledViewPool extends RecyclerView.RecycledViewPool { private static final String TAG = "InnerRecycledViewPool"; - private static final int DEFAULT_MAX_SIZE = 5; + private static int DEFAULT_MAX_SIZE = 20; /* * Wrapped InnerPool @@ -177,4 +174,8 @@ private void destroyViewHolder(RecyclerView.ViewHolder holder) { } } } + + public void setDefaultMaxSize(int maxSize) { + DEFAULT_MAX_SIZE = maxSize; + } } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/extend/LayoutManagerCanScrollListener.java b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/LayoutManagerCanScrollListener.java new file mode 100644 index 00000000..01d3b011 --- /dev/null +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/LayoutManagerCanScrollListener.java @@ -0,0 +1,7 @@ +package com.alibaba.android.vlayout.extend; + +public interface LayoutManagerCanScrollListener { + boolean canScrollVertically(); + + boolean canScrollHorizontally(); +} diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/extend/PerformanceMonitor.java b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/PerformanceMonitor.java new file mode 100644 index 00000000..7c4ec661 --- /dev/null +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/PerformanceMonitor.java @@ -0,0 +1,57 @@ +package com.alibaba.android.vlayout.extend; + +import android.support.annotation.Keep; +import android.view.View; + +/** + * Add callback during measure and layout, help you to monitor your view's performance.
+ * Designed as Class instead of Interface is able to extend api in future.
+ * + * Created by longerian on 2018/5/16. + * + * @author longerian + * @date 2018/05/16 + */ +public class PerformanceMonitor { + + /** + * Record the start time + * @param phase + * @param viewType + */ + @Keep + public void recordStart(String phase, String viewType) { + + } + + /** + * Record the end time + * @param phase + * @param viewType + */ + @Keep + public void recordEnd(String phase, String viewType) { + + } + + /** + * Record the start time + * @param phase + * @param view + */ + @Keep + public void recordStart(String phase, View view) { + + } + + /** + * Record the end time + * @param phase + * @param view + */ + @Keep + public void recordEnd(String phase, View view) { + + } + +} diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/extend/ViewLifeCycleHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/ViewLifeCycleHelper.java new file mode 100644 index 00000000..7cd204ff --- /dev/null +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/ViewLifeCycleHelper.java @@ -0,0 +1,144 @@ +package com.alibaba.android.vlayout.extend; + +import android.support.annotation.NonNull; +import android.support.v4.util.ArrayMap; +import android.view.View; + +import com.alibaba.android.vlayout.VirtualLayoutManager; + +import java.util.HashMap; + +public class ViewLifeCycleHelper { + public enum STATUS { + APPEARING, + APPEARED, + DISAPPEARING, + DISAPPEARED + } + + private HashMap mViewStatusMap = new HashMap<>(); + + private ViewLifeCycleListener mViewLifeCycleListener; + + private VirtualLayoutManager mVirtualLayoutManager; + + private int scrHeight; + + public ViewLifeCycleHelper(VirtualLayoutManager virtualLayoutManager, @NonNull ViewLifeCycleListener mViewLifeCycleListener) { + this.mViewLifeCycleListener = mViewLifeCycleListener; + this.mVirtualLayoutManager = virtualLayoutManager; + } + + public void checkViewStatusInScreen() { + for (int i = 0; i < mVirtualLayoutManager.getChildCount(); i++) { + View view = mVirtualLayoutManager.getChildAt(i); + if (scrHeight == 0) { + scrHeight = view.getContext().getResources().getDisplayMetrics().heightPixels; + } + + if (mVirtualLayoutManager.getVirtualLayoutDirection() == VirtualLayoutManager.LayoutState.LAYOUT_END) { + if (view.getTop() <= 0 && view.getBottom() >= 0 && isViewReadyDisAppearing(view)) { + setViewDisappearing(view); + } else if (view.getTop() <= scrHeight && view.getBottom() >= scrHeight && isViewReadyAppearing(view)) { + setViewAppearing(view); + } + } else { + if (view.getTop() <= 0 && view.getBottom() >= 0 && isViewReadyAppearing(view)) { + setViewAppearing(view); + } else if (view.getTop() <= scrHeight && view.getBottom() >= scrHeight && isViewReadyDisAppearing(view)) { + setViewDisappearing(view); + } + } + + if (view.getTop() >= 0 && view.getBottom() <= scrHeight) { + // fully in screen + + if (isViewReadyAppearing(view)) { + setViewAppearing(view); + + } else if (isViewReadyAppeared(view)) { + setViewAppeared(view); + } + } else if (view.getBottom() <= 0 || view.getTop() >= scrHeight) { + // not in screen + if (isViewReadyDisAppearing(view)) { + setViewDisappearing(view); + + } else if (isViewReadyDisAppeared(view)) { + setViewDisappeared(view); + } + + } + } + } + + private STATUS getViewStatus(View view) { + if (!mViewStatusMap.containsKey(view)) { + mViewStatusMap.put(view, STATUS.DISAPPEARED); + return STATUS.DISAPPEARED; + } + return mViewStatusMap.get(view); + } + + private void setViewstatus(View view, STATUS status) { + mViewStatusMap.put(view, status); + } + + private boolean isViewReadyAppearing(View view) { + return getViewStatus(view) == STATUS.DISAPPEARED; + } + + private void setViewAppearing(View view) { + if (getViewStatus(view) == STATUS.APPEARING) { + return; + } + + setViewstatus(view, STATUS.APPEARING); + if (null != mViewLifeCycleListener) { + mViewLifeCycleListener.onAppearing(view); + } + } + + private boolean isViewReadyAppeared(View view) { + return getViewStatus(view) == STATUS.APPEARING; + } + + private void setViewAppeared(View view) { + if (getViewStatus(view) == STATUS.APPEARED) { + return; + } + setViewstatus(view, STATUS.APPEARED); + if (null != mViewLifeCycleListener) { + mViewLifeCycleListener.onAppeared(view); + } + } + + private boolean isViewReadyDisAppearing(View view) { + return getViewStatus(view) == STATUS.APPEARED; + } + + private void setViewDisappearing(View view) { + if (getViewStatus(view) == STATUS.DISAPPEARING) { + return; + } + + setViewstatus(view, STATUS.DISAPPEARING); + if (null != mViewLifeCycleListener) { + mViewLifeCycleListener.onDisappearing(view); + } + } + + private boolean isViewReadyDisAppeared(View view) { + return getViewStatus(view) == STATUS.DISAPPEARING; + } + + private void setViewDisappeared(View view) { + if (getViewStatus(view) == STATUS.DISAPPEARED) { + return; + } + setViewstatus(view, STATUS.DISAPPEARED); + if (null != mViewLifeCycleListener) { + mViewLifeCycleListener.onDisappeared(view); + } + } +} diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/extend/ViewLifeCycleListener.java b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/ViewLifeCycleListener.java new file mode 100644 index 00000000..21e12114 --- /dev/null +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/extend/ViewLifeCycleListener.java @@ -0,0 +1,13 @@ +package com.alibaba.android.vlayout.extend; + +import android.view.View; + +public interface ViewLifeCycleListener { + void onAppearing(View view); + + void onDisappearing(View view); + + void onAppeared(View view); + + void onDisappeared(View view); +} diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/AbstractFullFillLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/AbstractFullFillLayoutHelper.java index 1b00ad70..208aaf76 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/AbstractFullFillLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/AbstractFullFillLayoutHelper.java @@ -24,7 +24,10 @@ package com.alibaba.android.vlayout.layout; +import android.graphics.Rect; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.Recycler; +import android.support.v7.widget.RecyclerView.State; import android.util.Log; import android.view.View; import android.view.ViewGroup.LayoutParams; @@ -45,6 +48,12 @@ public abstract class AbstractFullFillLayoutHelper extends BaseLayoutHelper { private static final String TAG = "FullFillLayoutHelper"; + protected boolean hasHeader = false; + + protected boolean hasFooter = false; + + protected boolean mLayoutWithAnchor = false; + protected int getAllChildren(View[] toFill, RecyclerView.Recycler recycler, LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper) { @@ -130,10 +139,26 @@ protected final void setMeasuredDimension(int measuredWidth, int measuredHeight) @Override public void checkAnchorInfo(RecyclerView.State state, VirtualLayoutManager.AnchorInfoWrapper anchorInfo, LayoutManagerHelper helper) { if (anchorInfo.layoutFromEnd) { - anchorInfo.position = getRange().getUpper(); + if (!hasFooter) { + anchorInfo.position = getRange().getUpper(); + } else { + //keep the previously calculated position + } } else { - anchorInfo.position = getRange().getLower(); + if (!hasHeader) { + anchorInfo.position = getRange().getLower(); + } else { + //keep the previously calculated position + } } + mLayoutWithAnchor = true; + } + + @Override + public void afterLayout(Recycler recycler, State state, int startPosition, int endPosition, int scrolled, + LayoutManagerHelper helper) { + super.afterLayout(recycler, state, startPosition, endPosition, scrolled, helper); + mLayoutWithAnchor = false; } @Override @@ -171,10 +196,54 @@ protected LayoutParams generateLayoutParams(LayoutParams p) { public boolean isRecyclable(int childPos, int startIndex, int endIndex, LayoutManagerHelper helper, boolean fromStart) { Range range = getRange(); if (range.contains(childPos)) { - return Range.create(startIndex, endIndex).contains(range); + if (hasHeader && childPos == getRange().getLower()) { + return true; + } + if (hasFooter && childPos == getRange().getUpper()) { + return true; + } + Range childRange = Range.create(range.getLower() + (hasHeader ? 1 : 0), + range.getUpper() - (hasFooter ? 1 : 0)); + return Range.create(startIndex, endIndex).contains(childRange); } else { Log.w(TAG, "Child item not match"); return true; } } + + public void setHasHeader(boolean hasHeader) { + this.hasHeader = hasHeader; + } + + public void setHasFooter(boolean hasFooter) { + this.hasFooter = hasFooter; + } + + protected void calculateRect(int mainAxisSize, Rect areaRect, LayoutStateWrapper layoutState, LayoutManagerHelper helper) { + if (helper.getOrientation() == VirtualLayoutManager.VERTICAL) { + areaRect.left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft; + areaRect.right = helper.getContentWidth() - helper.getPaddingRight() - mMarginRight - mPaddingRight; + + // whether this layout pass is layout to start or to end + if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) { + // fill start, from bottom to top + areaRect.bottom = layoutState.getOffset() - (mLayoutWithAnchor ? 0 : (hasFooter ? 0 : mMarginBottom + mPaddingBottom)); + areaRect.top = areaRect.bottom - mainAxisSize; + } else { + areaRect.top = layoutState.getOffset() + (mLayoutWithAnchor ? 0 : (hasHeader ? 0 : mMarginTop + mPaddingTop)); + areaRect.bottom = areaRect.top + mainAxisSize; + } + } else { + areaRect.top = helper.getPaddingTop() + mMarginTop + mPaddingTop; + areaRect.bottom = helper.getContentHeight() - helper.getPaddingBottom() - mMarginBottom - mPaddingBottom; + + if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) { + areaRect.right = layoutState.getOffset() - (mLayoutWithAnchor ? 0 :(hasFooter ? 0 : mMarginRight + mPaddingRight)); + areaRect.left = areaRect.right - mainAxisSize; + } else { + areaRect.left = layoutState.getOffset() + (mLayoutWithAnchor ? 0 : (hasHeader ? 0 : mMarginLeft + mPaddingLeft)); + areaRect.right = areaRect.left + mainAxisSize; + } + } + } } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java index 4bb45106..5c77b8c3 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/BaseLayoutHelper.java @@ -206,7 +206,7 @@ public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state mLayoutRegion.right = helper.getContentWidth() - helper.getPaddingRight() - mMarginRight; } else { mLayoutRegion.top = helper.getPaddingTop() + mMarginTop; - mLayoutRegion.bottom = helper.getContentWidth() - helper.getPaddingBottom() - mMarginBottom; + mLayoutRegion.bottom = helper.getContentHeight() - helper.getPaddingBottom() - mMarginBottom; } bindLayoutView(mLayoutView); @@ -507,14 +507,14 @@ protected void handleStateOnResult(LayoutChunkResult result, View view) { /** * Helper methods to handle focus states for views - * FIXME 可变参数性能不好,会引起一次潜在的数组对象创建,在频繁滑动过程中,容易引起GC,如果只有一个View,建议调用上述方法 * @param result * @param views */ - protected void handleStateOnResult(LayoutChunkResult result, View... views) { + protected void handleStateOnResult(LayoutChunkResult result, View[] views) { if (views == null) return; - for (View view : views) { + for (int i = 0; i < views.length; i++) { + View view = views[i]; if (view == null) { continue; } @@ -534,35 +534,6 @@ protected void handleStateOnResult(LayoutChunkResult result, View... views) { } } - - protected void calculateRect(int mainAxisSize, Rect areaRect, LayoutStateWrapper layoutState, LayoutManagerHelper helper) { - if (helper.getOrientation() == VirtualLayoutManager.VERTICAL) { - areaRect.left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft; - areaRect.right = helper.getContentWidth() - helper.getPaddingRight() - mMarginRight - mPaddingRight; - - // whether this layout pass is layout to start or to end - if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) { - // fill start, from bottom to top - areaRect.bottom = layoutState.getOffset() - mMarginBottom - mPaddingBottom; - areaRect.top = areaRect.bottom - mainAxisSize; - } else { - areaRect.top = layoutState.getOffset() + mMarginTop + mPaddingTop; - areaRect.bottom = areaRect.top + mainAxisSize; - } - } else { - areaRect.top = helper.getPaddingTop() + mMarginTop + mPaddingTop; - areaRect.bottom = helper.getContentHeight() - helper.getPaddingBottom() - mMarginBottom - mPaddingBottom; - - if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) { - areaRect.right = layoutState.getOffset() - mMarginRight - mPaddingRight; - areaRect.left = areaRect.right - mainAxisSize; - } else { - areaRect.left = layoutState.getOffset() + mMarginLeft + mPaddingLeft; - areaRect.right = areaRect.left + mainAxisSize; - } - } - } - protected int computeStartSpace(LayoutManagerHelper helper, boolean layoutInVertical, boolean isLayoutEnd, boolean isOverLapMargin) { int startSpace = 0; LayoutHelper lastLayoutHelper = null; @@ -578,16 +549,12 @@ protected int computeStartSpace(LayoutManagerHelper helper, boolean layoutInVert return 0; if (!isOverLapMargin) { - startSpace = layoutInVertical - ? (isLayoutEnd ? mMarginTop + mPaddingTop : mMarginBottom + mPaddingBottom) - : (isLayoutEnd ? mMarginLeft + mPaddingLeft : mMarginRight + mPaddingRight); + startSpace = layoutInVertical ? mMarginTop + mPaddingTop : mMarginLeft + mPaddingLeft; } else { int offset = 0; if (lastMarginLayoutHelper == null) { - offset = layoutInVertical - ? (isLayoutEnd ? mMarginTop + mPaddingTop : mMarginBottom + mPaddingBottom) - : (isLayoutEnd ? mMarginLeft + mPaddingLeft : mMarginRight + mPaddingRight); + offset = layoutInVertical ? mMarginTop + mPaddingTop : mMarginLeft + mPaddingLeft; } else { offset = layoutInVertical ? (isLayoutEnd ? calGap(lastMarginLayoutHelper.mMarginBottom, mMarginTop) : calGap(lastMarginLayoutHelper.mMarginTop, mMarginBottom)) @@ -605,8 +572,7 @@ protected int computeStartSpace(LayoutManagerHelper helper, boolean layoutInVert protected int computeEndSpace(LayoutManagerHelper helper, boolean layoutInVertical, boolean isLayoutEnd, boolean isOverLapMargin) { int endSpace = layoutInVertical - ? (isLayoutEnd ? mMarginBottom + mPaddingBottom : mMarginTop + mPaddingTop) - : (isLayoutEnd ? mMarginRight + mPaddingRight : mMarginLeft + mPaddingLeft); + ? mMarginBottom + mPaddingBottom : mMarginLeft + mPaddingLeft; //Log.e("huang", "computeEndSpace offset: " + endSpace + ", isLayoutEnd: " + isLayoutEnd + ", " + this); //Log.e("huang", "===================\n\n"); return endSpace; diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/FloatLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/FloatLayoutHelper.java index cf9c06f4..8254faf8 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/FloatLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/FloatLayoutHelper.java @@ -275,8 +275,8 @@ private void doMeasureAndLayout(View view, LayoutManagerHelper helper) { helper.getContentHeight() - helper.getPaddingTop() - helper.getPaddingBottom(), params.height, layoutInVertical); } - // do measurement - helper.measureChildWithMargins(view, widthSpec, heightSpec); + // do measurement, measure child without taking off margins, see https://github.com/alibaba/Tangram-Android/issues/81 + helper.measureChild(view, widthSpec, heightSpec); } else { int widthSpec; final int heightSpec = helper.getChildMeasureSpec( @@ -294,8 +294,8 @@ private void doMeasureAndLayout(View view, LayoutManagerHelper helper) { helper.getContentWidth() - helper.getPaddingLeft() - helper.getPaddingRight(), params.width, !layoutInVertical); } - // do measurement - helper.measureChildWithMargins(view, widthSpec, heightSpec); + // do measurement, measure child without taking off margins, see https://github.com/alibaba/Tangram-Android/issues/81 + helper.measureChild(view, widthSpec, heightSpec); } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/LinearLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/LinearLayoutHelper.java index 2e6b3a38..b21f47c2 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/LinearLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/LinearLayoutHelper.java @@ -27,9 +27,11 @@ import com.alibaba.android.vlayout.LayoutManagerHelper; import com.alibaba.android.vlayout.OrientationHelperEx; import com.alibaba.android.vlayout.VirtualLayoutManager; +import com.alibaba.android.vlayout.VirtualLayoutManager.AnchorInfoWrapper; import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.State; import android.util.Log; import android.view.View; @@ -47,6 +49,8 @@ public class LinearLayoutHelper extends BaseLayoutHelper { private int mDividerHeight = 0; + private boolean mLayoutWithAnchor = false; + public LinearLayoutHelper() { this(0); } @@ -113,8 +117,9 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (!isStartLine) { if (!isOverLapMargin) { - gap = mDividerHeight; + gap = mLayoutWithAnchor ? 0 : mDividerHeight; } else { + //TODO check layout with anchor if (isLayoutEnd) { int marginTop = params.topMargin; View sibling = helper.findViewByPosition(currentPosition - 1); @@ -209,6 +214,13 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state } handleStateOnResult(result, view); + mLayoutWithAnchor = false; + } + + @Override + public void checkAnchorInfo(State state, AnchorInfoWrapper anchorInfo, LayoutManagerHelper helper) { + super.checkAnchorInfo(state, anchorInfo, helper); + mLayoutWithAnchor = true; } @Override diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelper.java index d250c8ae..f6943687 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelper.java @@ -24,19 +24,22 @@ package com.alibaba.android.vlayout.layout; -import android.graphics.Rect; -import android.support.v7.widget.RecyclerView; -import android.util.Log; -import android.view.View; -import android.view.View.MeasureSpec; -import android.view.ViewGroup; +import java.util.Arrays; import com.alibaba.android.vlayout.LayoutManagerHelper; import com.alibaba.android.vlayout.OrientationHelperEx; import com.alibaba.android.vlayout.VirtualLayoutManager; +import com.alibaba.android.vlayout.VirtualLayoutManager.AnchorInfoWrapper; +import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutParams; import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutStateWrapper; -import java.util.Arrays; +import android.graphics.Rect; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.State; +import android.view.View; +import android.view.View.MeasureSpec; +import android.view.ViewGroup; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static com.alibaba.android.vlayout.VirtualLayoutManager.VERTICAL; @@ -110,20 +113,10 @@ public class OnePlusNLayoutHelper extends AbstractFullFillLayoutHelper { private View[] mChildrenViews; - private View mHeader; - - private View mFooter; - - private View[] mContentViews; - private float[] mColWeights = new float[0]; private float mRowWeight = Float.NaN; - private boolean hasHeader = false; - - private boolean hasFooter = false; - public OnePlusNLayoutHelper() { setItemCount(0); } @@ -156,13 +149,7 @@ public void onRangeChange(int start, int end) { } } - public void setHasHeader(boolean hasHeader) { - this.hasHeader = hasHeader; - } - public void setHasFooter(boolean hasFooter) { - this.hasFooter = hasFooter; - } public void setColWeights(float[] weights) { if (weights != null) { @@ -172,7 +159,6 @@ public void setColWeights(float[] weights) { } } - public void setRowWeight(float weight) { this.mRowWeight = weight; } @@ -184,80 +170,106 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (isOutOfRange(layoutState.getCurrentPosition())) { return; } - - final int originCurPos = layoutState.getCurrentPosition(); - - if (mChildrenViews == null || mChildrenViews.length != getItemCount()) { - mChildrenViews = new View[getItemCount()]; - } - - int count = getAllChildren(mChildrenViews, recycler, layoutState, result, helper); - if (count == 0) { - return; - } - int contentCount = count; - if (hasHeader) { - contentCount = contentCount - 1; - mHeader = mChildrenViews[0]; - mChildrenViews[0] = null; - } - if (hasFooter) { - contentCount = contentCount - 1; - mFooter = mChildrenViews[count - 1]; - mChildrenViews[count - 1] = null; - } - if (mContentViews == null || mContentViews.length != contentCount) { - mContentViews = new View[contentCount]; - } - int j = 0; - for (int i = 0; i < mChildrenViews.length; i++) { - if (mChildrenViews[i] == null) { - continue; - } - mContentViews[j] = mChildrenViews[i]; - j++; - } - - if (count != getItemCount()) { - Log.w(TAG, "The real number of children is not match with range of LayoutHelper"); - } - + final OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final boolean layoutInVertical = helper.getOrientation() == VERTICAL; - + final boolean layoutStart = layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START; final int parentWidth = helper.getContentWidth(); final int parentHeight = helper.getContentHeight(); final int parentHPadding = helper.getPaddingLeft() + helper.getPaddingRight() - + getHorizontalMargin() + getHorizontalPadding(); + + getHorizontalMargin() + getHorizontalPadding(); final int parentVPadding = helper.getPaddingTop() + helper.getPaddingBottom() - + getVerticalMargin() + getVerticalPadding(); - - int mainConsumed = 0; - int headerConsumed = handleHeader(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, - parentHPadding, parentVPadding); - int footerConsumed = handleFooter(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, - parentHPadding, parentVPadding); - if (contentCount == 1) { - mainConsumed = handleOne(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding, headerConsumed, footerConsumed); - } else if (contentCount == 2) { - mainConsumed = handleTwo(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding, headerConsumed, footerConsumed); - } else if (contentCount == 3) { - mainConsumed = handleThree(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding, headerConsumed, footerConsumed); - } else if (contentCount == 4) { - mainConsumed = handleFour(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding, headerConsumed, footerConsumed); - } else if (contentCount == 5) { - mainConsumed = handleFive(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding, headerConsumed, footerConsumed); + + getVerticalMargin() + getVerticalPadding(); + + final int currentPosition = layoutState.getCurrentPosition(); + if (hasHeader && currentPosition == getRange().getLower()) { + View header = nextView(recycler, layoutState, helper, result); + int headerConsumed = handleHeader(header, layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, + parentHPadding, parentVPadding); + if (header != null) { + int left = 0, right = 0, top = 0, bottom = 0; + if (layoutInVertical) { + if (layoutStart) { + bottom = layoutState.getOffset(); + top = bottom - headerConsumed; + } else { + top = layoutState.getOffset() + (mLayoutWithAnchor ? 0 : mMarginTop + mPaddingTop); + bottom = top + headerConsumed; + } + left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft; + right = left + orientationHelper.getDecoratedMeasurementInOther(header); + } else { + if (layoutStart) { + right = layoutState.getOffset(); + left = right - headerConsumed; + } else { + left = layoutState.getOffset() + (mLayoutWithAnchor ? 0 : mMarginLeft + mPaddingLeft); + right = left + headerConsumed; + } + top = helper.getPaddingTop() + mMarginTop + mPaddingTop; + bottom = top + orientationHelper.getDecoratedMeasurementInOther(header); + } + layoutChildWithMargin(header, left, top, right, bottom, helper); + } + result.mConsumed = headerConsumed; + handleStateOnResult(result, header); + } else if (hasFooter && currentPosition == getRange().getUpper()) { + View footer = nextView(recycler, layoutState, helper, result); + int footerConsumed = handleFooter(footer, layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, + parentHPadding, parentVPadding); + if (footer != null) { + int left = 0, right = 0, top = 0, bottom = 0; + if (layoutInVertical) { + if (layoutStart) { + bottom = layoutState.getOffset() - (mLayoutWithAnchor ? 0 : mMarginBottom + mPaddingBottom); //TODO margin overlap + top = bottom - footerConsumed; + } else { + top = layoutState.getOffset(); + bottom = top + footerConsumed; + } + left = helper.getPaddingLeft() + mMarginLeft + mPaddingLeft; + right = left + orientationHelper.getDecoratedMeasurementInOther(footer); + } else { + if (layoutStart) { + right = layoutState.getOffset() - (mLayoutWithAnchor ? 0 : mMarginRight + mPaddingRight); //TODO margin overlap + left = right - footerConsumed; + } else { + left = layoutState.getOffset(); + right = left + footerConsumed; + } + top = helper.getPaddingTop() + mMarginTop + mPaddingTop; + bottom = top + orientationHelper.getDecoratedMeasurementInOther(footer); + } + layoutChildWithMargin(footer, left, top, right, bottom, helper); + } + result.mConsumed = footerConsumed; + handleStateOnResult(result, footer); + } else { + int contentCount = getItemCount() - (hasHeader ? 1 : 0) - (hasFooter ? 1 : 0); + if (mChildrenViews == null || mChildrenViews.length != contentCount) { + mChildrenViews = new View[contentCount]; + } + int count = getAllChildren(mChildrenViews, recycler, layoutState, result, helper); + if (count == 0 || count < contentCount) { + return; + } + int mainConsumed = 0; + if (contentCount == 1) { + mainConsumed = handleOne(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); + } else if (contentCount == 2) { + mainConsumed = handleTwo(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); + } else if (contentCount == 3) { + mainConsumed = handleThree(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); + } else if (contentCount == 4) { + mainConsumed = handleFour(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); + } else if (contentCount == 5) { + mainConsumed = handleFive(layoutState, result, helper, layoutInVertical, parentWidth, parentHeight, parentHPadding, parentVPadding); + } + result.mConsumed = mainConsumed; + Arrays.fill(mChildrenViews, null); } - - result.mConsumed = mainConsumed; - - Arrays.fill(mChildrenViews, null); - Arrays.fill(mContentViews, null); - //mHeader = null; - //mFooter = null; } - - private float getViewMainWeight(ViewGroup.MarginLayoutParams params, int index) { + private float getViewMainWeight(int index) { if (mColWeights.length > index) { return mColWeights[index]; } @@ -268,86 +280,82 @@ private float getViewMainWeight(ViewGroup.MarginLayoutParams params, int index) @Override protected void onClear(LayoutManagerHelper helper) { super.onClear(helper); - mHeader = null; - mFooter = null; + } + + @Override + public void checkAnchorInfo(State state, AnchorInfoWrapper anchorInfo, LayoutManagerHelper helper) { + super.checkAnchorInfo(state, anchorInfo, helper); + mLayoutWithAnchor = true; } @Override public int computeAlignOffset(int offset, boolean isLayoutEnd, boolean useAnchor, LayoutManagerHelper helper) { - //Log.d("Longer", "range " + getRange() + " offset " + offset + " isLayoutEnd " + isLayoutEnd + " useAnchor " + useAnchor + " mHeader " + (mHeader != null ? mHeader.hashCode() : "null")); - OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - if (offset == 1 && isLayoutEnd) { - Log.w(TAG, "Should not happen after adjust anchor without header"); + //Log.d(TAG, + // "range " + getRange() + " offset " + offset + " isLayoutEnd " + isLayoutEnd + " useAnchor " + useAnchor + // + " helper " + this.hashCode()); + final boolean layoutInVertical = helper.getOrientation() == LinearLayoutManager.VERTICAL; + + if (useAnchor) { return 0; - } else if (useAnchor) { - Log.w(TAG, "Happens when header scroll out of window and layoutManager use first content view as anchor to layout"); - return -mMarginTop - mPaddingTop - (mHeader != null ? orientationHelper.getDecoratedMeasurement(mHeader) : 0); } - - if (helper.getOrientation() == VERTICAL) { - if (isLayoutEnd) { - return mMarginBottom + mPaddingBottom; - } else { - return -mMarginTop - mPaddingTop; + if (isLayoutEnd) { + if (offset == getItemCount() - 1) { + return layoutInVertical ? mMarginBottom + mPaddingBottom : mMarginRight + mPaddingRight; } } else { - if (isLayoutEnd) { - return mMarginRight + mPaddingRight; - } else { - return -mMarginLeft - mPaddingLeft; + if (offset == 0) { + return layoutInVertical ? -mMarginTop - mPaddingTop : -mMarginLeft - mPaddingLeft; } } + return 0; } - private int handleHeader(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, + private int handleHeader(View header, LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { - if (mHeader == null) { + if (header == null) { return 0; } OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( - mHeader.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp = (LayoutParams) header.getLayoutParams(); + // fill width int widthSpec = helper.getChildMeasureSpec(parentWidth - parentHPadding, layoutInVertical ? MATCH_PARENT : lp.width, !layoutInVertical); int heightSpec = helper.getChildMeasureSpec(parentHeight - parentVPadding, layoutInVertical ? lp.height : MeasureSpec.EXACTLY, layoutInVertical); - helper.measureChildWithMargins(mHeader, widthSpec, heightSpec); - return orientationHelper.getDecoratedMeasurement(mHeader); + helper.measureChildWithMargins(header, widthSpec, heightSpec); + return orientationHelper.getDecoratedMeasurement(header); } - private int handleFooter(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, + private int handleFooter(View footer, LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { - if (mFooter == null) { + if (footer == null) { return 0; } OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( - mFooter.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp = (LayoutParams) footer.getLayoutParams(); // fill width int widthSpec = helper.getChildMeasureSpec(parentWidth - parentHPadding, layoutInVertical ? MATCH_PARENT : lp.width, !layoutInVertical); int heightSpec = helper.getChildMeasureSpec(parentHeight - parentVPadding, layoutInVertical ? lp.height : MeasureSpec.EXACTLY, layoutInVertical); - helper.measureChildWithMargins(mFooter, widthSpec, heightSpec); - return orientationHelper.getDecoratedMeasurement(mFooter); + helper.measureChildWithMargins(footer, widthSpec, heightSpec); + return orientationHelper.getDecoratedMeasurement(footer); } private int handleOne(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, - boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding, - int headerConsumed, int footerConsumed) { - int mainConsumed = headerConsumed + footerConsumed; + boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { + int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - View view = mContentViews[0]; - final ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( - (ViewGroup.MarginLayoutParams) view.getLayoutParams()); + View view = mChildrenViews[0]; + final VirtualLayoutManager.LayoutParams lp = (LayoutParams) view.getLayoutParams(); if (!Float.isNaN(mAspectRatio)) { if (layoutInVertical) { @@ -357,7 +365,7 @@ private int handleOne(LayoutStateWrapper layoutState, LayoutChunkResult result, } } - final float weight = getViewMainWeight(lp, 0); + final float weight = getViewMainWeight(0); // fill width int widthSpec = helper.getChildMeasureSpec( @@ -369,38 +377,28 @@ private int handleOne(LayoutStateWrapper layoutState, LayoutChunkResult result, helper.measureChildWithMargins(view, widthSpec, heightSpec); - mainConsumed += orientationHelper.getDecoratedMeasurement(view) + (layoutInVertical ? - getVerticalMargin() + getVerticalPadding() - : getHorizontalMargin() + getHorizontalPadding()); + mainConsumed += orientationHelper.getDecoratedMeasurement(view); - calculateRect(mainConsumed - getVerticalMargin() - getVerticalPadding(), mAreaRect, layoutState, helper); + calculateRect(mainConsumed, mAreaRect, layoutState, helper); - if (mHeader != null) { - layoutChildWithMargin(mHeader, mAreaRect.left, mAreaRect.top, mAreaRect.right, mAreaRect.top + headerConsumed, helper); - } - layoutChildWithMargin(view, mAreaRect.left, mAreaRect.top + headerConsumed, mAreaRect.right, mAreaRect.bottom - footerConsumed, + layoutChildWithMargin(view, mAreaRect.left, mAreaRect.top, mAreaRect.right, mAreaRect.bottom, helper); - if (mFooter != null) { - layoutChildWithMargin(mFooter, mAreaRect.left, mAreaRect.bottom - footerConsumed, mAreaRect.right, mAreaRect.bottom, helper); - } - handleStateOnResult(result, mHeader, view, mFooter); + handleStateOnResult(result, view); + mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); return mainConsumed; } private int handleTwo(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, - boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding, - int headerConsumed, int footerConsumed) { - int mainConsumed = headerConsumed + footerConsumed; + boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { + int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - final View child1 = mContentViews[0]; - final ViewGroup.MarginLayoutParams lp1 = new ViewGroup.MarginLayoutParams( - (ViewGroup.MarginLayoutParams)child1.getLayoutParams()); - final View child2 = mContentViews[1]; - final ViewGroup.MarginLayoutParams lp2 = new ViewGroup.MarginLayoutParams( - (ViewGroup.MarginLayoutParams)child2.getLayoutParams()); - final float weight1 = getViewMainWeight(lp1, 0); - final float weight2 = getViewMainWeight(lp1, 1); + final View child1 = mChildrenViews[0]; + final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); + final View child2 = mChildrenViews[1]; + final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); + final float weight1 = getViewMainWeight(0); + final float weight2 = getViewMainWeight(1); if (layoutInVertical) { @@ -430,29 +428,19 @@ private int handleTwo(LayoutStateWrapper layoutState, LayoutChunkResult result, helper.getChildMeasureSpec(helper.getContentHeight(), lp2.height, true)); mainConsumed += Math.max(orientationHelper.getDecoratedMeasurement(child1), - orientationHelper.getDecoratedMeasurement(child2)) + getVerticalMargin() - + getVerticalPadding(); - - calculateRect(mainConsumed - getVerticalMargin() - getVerticalPadding(), mAreaRect, layoutState, helper); + orientationHelper.getDecoratedMeasurement(child2)); - if (mHeader != null) { - layoutChildWithMargin(mHeader, mAreaRect.left, mAreaRect.top, mAreaRect.right, mAreaRect.top + headerConsumed, helper); - } - if (mFooter != null) { - layoutChildWithMargin(mFooter, mAreaRect.left, mAreaRect.bottom - footerConsumed, mAreaRect.right, mAreaRect.bottom, helper); - } + calculateRect(mainConsumed, mAreaRect, layoutState, helper); int right1 = mAreaRect.left + orientationHelper .getDecoratedMeasurementInOther(child1); - layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top + headerConsumed, - right1, mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); - layoutChildWithMargin(child2, - right1, mAreaRect.top + headerConsumed, - right1 + orientationHelper.getDecoratedMeasurementInOther(child2), - mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child2, right1, mAreaRect.top, + right1 + orientationHelper.getDecoratedMeasurementInOther(child2), mAreaRect.bottom, helper); + mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { if (!Float.isNaN(mAspectRatio)) { @@ -480,10 +468,9 @@ private int handleTwo(LayoutStateWrapper layoutState, LayoutChunkResult result, MeasureSpec.EXACTLY)); mainConsumed += Math.max(orientationHelper.getDecoratedMeasurement(child1), - orientationHelper.getDecoratedMeasurement(child2)) + getHorizontalMargin() - + getHorizontalPadding(); + orientationHelper.getDecoratedMeasurement(child2)); - calculateRect(mainConsumed - getHorizontalPadding() - getHorizontalMargin(), mAreaRect, layoutState, helper); + calculateRect(mainConsumed, mAreaRect, layoutState, helper); int bottom1 = mAreaRect.top + orientationHelper .getDecoratedMeasurementInOther(child1); @@ -493,32 +480,29 @@ private int handleTwo(LayoutStateWrapper layoutState, LayoutChunkResult result, layoutChildWithMargin(child2, mAreaRect.left, bottom1, mAreaRect.right, bottom1 + orientationHelper.getDecoratedMeasurementInOther(child2), helper); + mainConsumed = mAreaRect.right - mAreaRect.left + (hasHeader ? 0 : mMarginLeft + mPaddingRight) + (hasFooter ? 0 : mMarginRight + mPaddingRight); } - handleStateOnResult(result, mHeader, child1, child2, mFooter); + handleStateOnResult(result, mChildrenViews); return mainConsumed; } private int handleThree(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, - boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding, - int headerConsumed, int footerConsumed) { - int mainConsumed = headerConsumed + footerConsumed; + boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { + int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - final View child1 = mContentViews[0]; - final ViewGroup.MarginLayoutParams lp1 = new ViewGroup.MarginLayoutParams( - (ViewGroup.MarginLayoutParams)child1.getLayoutParams()); - final View child2 = helper.getReverseLayout() ? mContentViews[2] : mContentViews[1]; - final View child3 = helper.getReverseLayout() ? mContentViews[1] : mContentViews[2]; + final View child1 = mChildrenViews[0]; + final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); + final View child2 = helper.getReverseLayout() ? mChildrenViews[2] : mChildrenViews[1]; + final View child3 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[2]; - final ViewGroup.MarginLayoutParams lp2 = new ViewGroup.MarginLayoutParams( - (ViewGroup.MarginLayoutParams)child2.getLayoutParams()); - final ViewGroup.MarginLayoutParams lp3 = new ViewGroup.MarginLayoutParams( - (ViewGroup.MarginLayoutParams)child3.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); + final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); - final float weight1 = getViewMainWeight(lp1, 0); - final float weight2 = getViewMainWeight(lp1, 1); - final float weight3 = getViewMainWeight(lp1, 2); + final float weight1 = getViewMainWeight(0); + final float weight2 = getViewMainWeight(1); + final float weight3 = getViewMainWeight(2); if (layoutInVertical) { @@ -570,66 +554,48 @@ private int handleThree(LayoutStateWrapper layoutState, LayoutChunkResult result mainConsumed += Math.max(height1 + lp1.topMargin + lp1.bottomMargin, height2 + lp2.topMargin + lp2.bottomMargin + height3 + lp3.topMargin - + lp3.bottomMargin) - + getVerticalMargin() + getVerticalPadding(); - - calculateRect(mainConsumed - getVerticalMargin() - getVerticalPadding(), mAreaRect, layoutState, helper); + + lp3.bottomMargin); - if (mHeader != null) { - layoutChildWithMargin(mHeader, mAreaRect.left, mAreaRect.top, mAreaRect.right, mAreaRect.top + headerConsumed, helper); - } - if (mFooter != null) { - layoutChildWithMargin(mFooter, mAreaRect.left, mAreaRect.bottom - footerConsumed, mAreaRect.right, mAreaRect.bottom, helper); - } + calculateRect(mainConsumed, mAreaRect, layoutState, helper); int right1 = mAreaRect.left + orientationHelper .getDecoratedMeasurementInOther(child1); - layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top + headerConsumed, right1, - mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); int right2 = right1 + orientationHelper.getDecoratedMeasurementInOther(child2); - layoutChildWithMargin(child2, - right1, mAreaRect.top + headerConsumed, right2, - mAreaRect.top + child2.getMeasuredHeight() + lp2.topMargin - + lp2.bottomMargin + headerConsumed, helper); - - layoutChildWithMargin(child3, - right1, - mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3) - footerConsumed, - right1 + orientationHelper.getDecoratedMeasurementInOther(child3), - mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child2, right1, mAreaRect.top, right2, + mAreaRect.top + child2.getMeasuredHeight() + lp2.topMargin + lp2.bottomMargin, helper); + + layoutChildWithMargin(child3, right1, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3), + right1 + orientationHelper.getDecoratedMeasurementInOther(child3), mAreaRect.bottom, helper); + mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { // TODO: horizontal support } - handleStateOnResult(result, mHeader, child1, child2, child3, mFooter); + handleStateOnResult(result, mChildrenViews); return mainConsumed; } private int handleFour(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, - boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding, - int headerConsumed, int footerConsumed) { + boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { - int mainConsumed = headerConsumed + footerConsumed; + int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - final View child1 = mContentViews[0]; - final VirtualLayoutManager.LayoutParams lp1 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child1.getLayoutParams()); - final View child2 = helper.getReverseLayout() ? mContentViews[3] : mContentViews[1]; - final VirtualLayoutManager.LayoutParams lp2 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child2.getLayoutParams()); - final View child3 = mContentViews[2]; - final VirtualLayoutManager.LayoutParams lp3 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child3.getLayoutParams()); - final View child4 = helper.getReverseLayout() ? mContentViews[1] : mContentViews[3]; - final VirtualLayoutManager.LayoutParams lp4 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child4.getLayoutParams()); - - final float weight1 = getViewMainWeight(lp1, 0); - final float weight2 = getViewMainWeight(lp1, 1); - final float weight3 = getViewMainWeight(lp1, 2); - final float weight4 = getViewMainWeight(lp1, 3); + final View child1 = mChildrenViews[0]; + final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); + final View child2 = helper.getReverseLayout() ? mChildrenViews[3] : mChildrenViews[1]; + final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); + final View child3 = mChildrenViews[2]; + final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); + final View child4 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[3]; + final VirtualLayoutManager.LayoutParams lp4 = (VirtualLayoutManager.LayoutParams) child4.getLayoutParams(); + + final float weight1 = getViewMainWeight(0); + final float weight2 = getViewMainWeight(1); + final float weight3 = getViewMainWeight(2); + final float weight4 = getViewMainWeight(3); if (layoutInVertical) { @@ -692,72 +658,54 @@ private int handleFour(LayoutStateWrapper layoutState, LayoutChunkResult result, mainConsumed += Math.max(height1 + lp1.topMargin + lp1.bottomMargin, height2 + lp2.topMargin + lp2.bottomMargin + Math .max(height3 + lp3.topMargin + lp3.bottomMargin, - height3 + lp4.topMargin + lp4.bottomMargin)) - + getVerticalMargin() + getVerticalPadding(); + height3 + lp4.topMargin + lp4.bottomMargin)); - calculateRect(mainConsumed - getVerticalMargin() - getVerticalPadding(), mAreaRect, layoutState, helper); - - if (mHeader != null) { - layoutChildWithMargin(mHeader, mAreaRect.left, mAreaRect.top, mAreaRect.right, mAreaRect.top + headerConsumed, helper); - } - if (mFooter != null) { - layoutChildWithMargin(mFooter, mAreaRect.left, mAreaRect.bottom - footerConsumed, mAreaRect.right, mAreaRect.bottom, helper); - } + calculateRect(mainConsumed, mAreaRect, layoutState, helper); int right1 = mAreaRect.left + orientationHelper .getDecoratedMeasurementInOther(child1); - layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top + headerConsumed, - right1, mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); int right2 = right1 + orientationHelper.getDecoratedMeasurementInOther(child2); - layoutChildWithMargin(child2, right1, mAreaRect.top + headerConsumed, right2, - mAreaRect.top + orientationHelper.getDecoratedMeasurement(child2) + headerConsumed, - helper); + layoutChildWithMargin(child2, right1, mAreaRect.top, right2, + mAreaRect.top + orientationHelper.getDecoratedMeasurement(child2), helper); int right3 = right1 + orientationHelper.getDecoratedMeasurementInOther(child3); - layoutChildWithMargin(child3, right1, - mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3) - footerConsumed, - right3, mAreaRect.bottom - footerConsumed, helper); - - layoutChildWithMargin(child4, right3, - mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child4) - footerConsumed, - right3 + orientationHelper.getDecoratedMeasurementInOther(child4), - mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child3, right1, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3), + right3, mAreaRect.bottom, helper); + + layoutChildWithMargin(child4, right3, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child4), + right3 + orientationHelper.getDecoratedMeasurementInOther(child4), mAreaRect.bottom, helper); + mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { // TODO: horizontal support } - handleStateOnResult(result, mHeader, child1, child2, child3, child4, mFooter); + handleStateOnResult(result, mChildrenViews); return mainConsumed; } private int handleFive(LayoutStateWrapper layoutState, LayoutChunkResult result, LayoutManagerHelper helper, - boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding, - int headerConsumed, int footerConsumed) { - int mainConsumed = headerConsumed + footerConsumed; + boolean layoutInVertical, int parentWidth, int parentHeight, int parentHPadding, int parentVPadding) { + int mainConsumed = 0; OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); - final View child1 = mContentViews[0]; - final VirtualLayoutManager.LayoutParams lp1 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child1.getLayoutParams()); - final View child2 = helper.getReverseLayout() ? mContentViews[4] : mContentViews[1]; - final VirtualLayoutManager.LayoutParams lp2 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child2.getLayoutParams()); - final View child3 = helper.getReverseLayout() ? mContentViews[3] : mContentViews[2]; - final VirtualLayoutManager.LayoutParams lp3 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child3.getLayoutParams()); - final View child4 = helper.getReverseLayout() ? mContentViews[2] : mContentViews[3]; - final VirtualLayoutManager.LayoutParams lp4 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child4.getLayoutParams()); - final View child5 = helper.getReverseLayout() ? mContentViews[1] : mContentViews[4]; - final VirtualLayoutManager.LayoutParams lp5 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child5.getLayoutParams()); - - final float weight1 = getViewMainWeight(lp1, 0); - final float weight2 = getViewMainWeight(lp1, 1); - final float weight3 = getViewMainWeight(lp1, 2); - final float weight4 = getViewMainWeight(lp1, 3); - final float weight5 = getViewMainWeight(lp1, 4); + final View child1 = mChildrenViews[0]; + final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); + final View child2 = helper.getReverseLayout() ? mChildrenViews[4] : mChildrenViews[1]; + final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); + final View child3 = helper.getReverseLayout() ? mChildrenViews[3] : mChildrenViews[2]; + final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); + final View child4 = helper.getReverseLayout() ? mChildrenViews[2] : mChildrenViews[3]; + final VirtualLayoutManager.LayoutParams lp4 = (VirtualLayoutManager.LayoutParams) child4.getLayoutParams(); + final View child5 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[4]; + final VirtualLayoutManager.LayoutParams lp5 = (VirtualLayoutManager.LayoutParams) child5.getLayoutParams(); + + final float weight1 = getViewMainWeight(0); + final float weight2 = getViewMainWeight(1); + final float weight3 = getViewMainWeight(2); + final float weight4 = getViewMainWeight(3); + final float weight5 = getViewMainWeight(4); if (layoutInVertical) { @@ -830,48 +778,33 @@ private int handleFive(LayoutStateWrapper layoutState, LayoutChunkResult result, mainConsumed += Math.max(height1 + lp1.topMargin + lp1.bottomMargin, height2 + lp2.topMargin + lp2.bottomMargin + Math .max(height3 + lp3.topMargin + lp3.bottomMargin, - height3 + lp4.topMargin + lp4.bottomMargin)) - + getVerticalMargin() + getVerticalPadding(); - - calculateRect(mainConsumed - getVerticalMargin() - getVerticalPadding(), mAreaRect, layoutState, helper); + height3 + lp4.topMargin + lp4.bottomMargin)); - if (mHeader != null) { - layoutChildWithMargin(mHeader, mAreaRect.left, mAreaRect.top, mAreaRect.right, mAreaRect.top + headerConsumed, helper); - } - if (mFooter != null) { - layoutChildWithMargin(mFooter, mAreaRect.left, mAreaRect.bottom - footerConsumed, mAreaRect.right, mAreaRect.bottom, helper); - } + calculateRect(mainConsumed, mAreaRect, layoutState, helper); - int right1 = mAreaRect.left + orientationHelper - .getDecoratedMeasurementInOther(child1); - layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top + headerConsumed, - right1, mAreaRect.bottom - footerConsumed, helper); + int right1 = mAreaRect.left + orientationHelper.getDecoratedMeasurementInOther(child1); + layoutChildWithMargin(child1, mAreaRect.left, mAreaRect.top, right1, mAreaRect.bottom, helper); int right2 = right1 + orientationHelper.getDecoratedMeasurementInOther(child2); - layoutChildWithMargin(child2, right1, mAreaRect.top + headerConsumed, right2, - mAreaRect.top + orientationHelper.getDecoratedMeasurement(child2) + headerConsumed, - helper); + layoutChildWithMargin(child2, right1, mAreaRect.top, right2, + mAreaRect.top + orientationHelper.getDecoratedMeasurement(child2), helper); int right3 = right1 + orientationHelper.getDecoratedMeasurementInOther(child3); - layoutChildWithMargin(child3, right1, - mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3) - footerConsumed, - right3, mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child3, right1, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child3), + right3, mAreaRect.bottom, helper); int right4 = right3 + orientationHelper.getDecoratedMeasurementInOther(child4); - layoutChildWithMargin(child4, right3, - mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child4) - footerConsumed, - right3 + orientationHelper.getDecoratedMeasurementInOther(child4), - mAreaRect.bottom - footerConsumed, helper); - - layoutChildWithMargin(child5, right4, - mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child5) - footerConsumed, - right4 + orientationHelper.getDecoratedMeasurementInOther(child5), - mAreaRect.bottom - footerConsumed, helper); + layoutChildWithMargin(child4, right3, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child4), + right3 + orientationHelper.getDecoratedMeasurementInOther(child4), mAreaRect.bottom, helper); + + layoutChildWithMargin(child5, right4, mAreaRect.bottom - orientationHelper.getDecoratedMeasurement(child5), + right4 + orientationHelper.getDecoratedMeasurementInOther(child5), mAreaRect.bottom, helper); + mainConsumed = mAreaRect.bottom - mAreaRect.top + (hasHeader ? 0 : mMarginTop + mPaddingTop) + (hasFooter ? 0 : mMarginBottom + mPaddingBottom); } else { // TODO: horizontal support } - handleStateOnResult(result, mHeader, child1, child2, child3, child4, child5, mFooter); + handleStateOnResult(result, mChildrenViews); return mainConsumed; } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelperEx.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelperEx.java index 07526ced..03eea1a1 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelperEx.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/OnePlusNLayoutHelperEx.java @@ -185,7 +185,7 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state } - private float getViewMainWeight(ViewGroup.MarginLayoutParams params, int index) { + private float getViewMainWeight(int index) { if (mColWeights.length > index) { return mColWeights[index]; } @@ -228,26 +228,21 @@ private int handleFive(LayoutStateWrapper layoutState, LayoutChunkResult result, OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final View child1 = mChildrenViews[0]; - final VirtualLayoutManager.LayoutParams lp1 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child1.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); final View child2 = helper.getReverseLayout() ? mChildrenViews[4] : mChildrenViews[1]; - final VirtualLayoutManager.LayoutParams lp2 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child2.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); final View child3 = helper.getReverseLayout() ? mChildrenViews[3] : mChildrenViews[2]; - final VirtualLayoutManager.LayoutParams lp3 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child3.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); final View child4 = helper.getReverseLayout() ? mChildrenViews[2] : mChildrenViews[3]; - final VirtualLayoutManager.LayoutParams lp4 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child4.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp4 = (VirtualLayoutManager.LayoutParams) child4.getLayoutParams(); final View child5 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[4]; - final VirtualLayoutManager.LayoutParams lp5 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child5.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp5 = (VirtualLayoutManager.LayoutParams) child5.getLayoutParams(); - final float weight1 = getViewMainWeight(lp1, 0); - final float weight2 = getViewMainWeight(lp1, 1); - final float weight3 = getViewMainWeight(lp1, 2); - final float weight4 = getViewMainWeight(lp1, 3); - final float weight5 = getViewMainWeight(lp1, 4); + final float weight1 = getViewMainWeight(0); + final float weight2 = getViewMainWeight(1); + final float weight3 = getViewMainWeight(2); + final float weight4 = getViewMainWeight(3); + final float weight5 = getViewMainWeight(4); if (layoutInVertical) { @@ -349,7 +344,7 @@ private int handleFive(LayoutStateWrapper layoutState, LayoutChunkResult result, // TODO: horizontal support } - handleStateOnResult(result, child1, child2, child3, child4, child5); + handleStateOnResult(result, mChildrenViews); return mainConsumed; } @@ -361,30 +356,24 @@ private int handSix(LayoutStateWrapper layoutState, LayoutChunkResult result, La OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final View child1 = mChildrenViews[0]; - final VirtualLayoutManager.LayoutParams lp1 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child1.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); final View child2 = helper.getReverseLayout() ? mChildrenViews[5] : mChildrenViews[1]; - final VirtualLayoutManager.LayoutParams lp2 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child2.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); final View child3 = helper.getReverseLayout() ? mChildrenViews[4] : mChildrenViews[2]; - final VirtualLayoutManager.LayoutParams lp3 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child3.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); final View child4 = helper.getReverseLayout() ? mChildrenViews[3] : mChildrenViews[3]; - final VirtualLayoutManager.LayoutParams lp4 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child4.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp4 = (VirtualLayoutManager.LayoutParams) child4.getLayoutParams(); final View child5 = helper.getReverseLayout() ? mChildrenViews[2] : mChildrenViews[4]; - final VirtualLayoutManager.LayoutParams lp5 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child5.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp5 = (VirtualLayoutManager.LayoutParams) child5.getLayoutParams(); final View child6 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[5]; - final VirtualLayoutManager.LayoutParams lp6 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child6.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp6 = (VirtualLayoutManager.LayoutParams) child6.getLayoutParams(); - final float weight1 = getViewMainWeight(lp1, 0); - final float weight2 = getViewMainWeight(lp1, 1); - final float weight3 = getViewMainWeight(lp1, 2); - final float weight4 = getViewMainWeight(lp1, 3); - final float weight5 = getViewMainWeight(lp1, 4); - final float weight6 = getViewMainWeight(lp1, 5); + final float weight1 = getViewMainWeight(0); + final float weight2 = getViewMainWeight(1); + final float weight3 = getViewMainWeight(2); + final float weight4 = getViewMainWeight(3); + final float weight5 = getViewMainWeight(4); + final float weight6 = getViewMainWeight(5); if (layoutInVertical) { @@ -512,7 +501,7 @@ private int handSix(LayoutStateWrapper layoutState, LayoutChunkResult result, La // TODO: horizontal support } - handleStateOnResult(result, child1, child2, child3, child4, child5, child6); + handleStateOnResult(result, mChildrenViews); return mainConsumed; } @@ -522,34 +511,27 @@ private int handSeven(LayoutStateWrapper layoutState, LayoutChunkResult result, OrientationHelperEx orientationHelper = helper.getMainOrientationHelper(); final View child1 = mChildrenViews[0]; - final VirtualLayoutManager.LayoutParams lp1 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child1.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp1 = (VirtualLayoutManager.LayoutParams) child1.getLayoutParams(); final View child2 = helper.getReverseLayout() ? mChildrenViews[6] : mChildrenViews[1]; - final VirtualLayoutManager.LayoutParams lp2 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child2.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp2 = (VirtualLayoutManager.LayoutParams) child2.getLayoutParams(); final View child3 = helper.getReverseLayout() ? mChildrenViews[5] : mChildrenViews[2]; - final VirtualLayoutManager.LayoutParams lp3 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child3.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp3 = (VirtualLayoutManager.LayoutParams) child3.getLayoutParams(); final View child4 = helper.getReverseLayout() ? mChildrenViews[4] : mChildrenViews[3]; - final VirtualLayoutManager.LayoutParams lp4 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child4.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp4 = (VirtualLayoutManager.LayoutParams) child4.getLayoutParams(); final View child5 = helper.getReverseLayout() ? mChildrenViews[3] : mChildrenViews[4]; - final VirtualLayoutManager.LayoutParams lp5 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child5.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp5 = (VirtualLayoutManager.LayoutParams) child5.getLayoutParams(); final View child6 = helper.getReverseLayout() ? mChildrenViews[2] : mChildrenViews[5]; - final VirtualLayoutManager.LayoutParams lp6 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child6.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp6 = (VirtualLayoutManager.LayoutParams) child6.getLayoutParams(); final View child7 = helper.getReverseLayout() ? mChildrenViews[1] : mChildrenViews[6]; - final VirtualLayoutManager.LayoutParams lp7 = new VirtualLayoutManager.LayoutParams( - (VirtualLayoutManager.LayoutParams)child7.getLayoutParams()); + final VirtualLayoutManager.LayoutParams lp7 = (VirtualLayoutManager.LayoutParams) child7.getLayoutParams(); - final float weight1 = getViewMainWeight(lp1, 0); - final float weight2 = getViewMainWeight(lp1, 1); - final float weight3 = getViewMainWeight(lp1, 2); - final float weight4 = getViewMainWeight(lp1, 3); - final float weight5 = getViewMainWeight(lp1, 4); - final float weight6 = getViewMainWeight(lp1, 5); - final float weight7 = getViewMainWeight(lp1, 6); + final float weight1 = getViewMainWeight(0); + final float weight2 = getViewMainWeight(1); + final float weight3 = getViewMainWeight(2); + final float weight4 = getViewMainWeight(3); + final float weight5 = getViewMainWeight(4); + final float weight6 = getViewMainWeight(5); + final float weight7 = getViewMainWeight(6); if (layoutInVertical) { @@ -677,7 +659,7 @@ private int handSeven(LayoutStateWrapper layoutState, LayoutChunkResult result, // TODO: horizontal support } - handleStateOnResult(result, child1, child2, child3, child4, child5, child6); + handleStateOnResult(result, mChildrenViews); return mainConsumed; } } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java index 12b210db..22e5c700 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeGridLayoutHelper.java @@ -24,7 +24,13 @@ package com.alibaba.android.vlayout.layout; -import java.util.Arrays; +import android.support.annotation.NonNull; +import android.support.v4.util.ArrayMap; +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.RecyclerView.Recycler; +import android.support.v7.widget.RecyclerView.State; +import android.util.Log; +import android.view.View; import com.alibaba.android.vlayout.LayoutManagerHelper; import com.alibaba.android.vlayout.OrientationHelperEx; @@ -35,13 +41,9 @@ import com.alibaba.android.vlayout.layout.GridLayoutHelper.DefaultSpanSizeLookup; import com.alibaba.android.vlayout.layout.GridLayoutHelper.SpanSizeLookup; -import android.support.annotation.NonNull; -import android.support.v4.util.ArrayMap; -import android.support.v7.widget.RecyclerView; -import android.support.v7.widget.RecyclerView.Recycler; -import android.support.v7.widget.RecyclerView.State; -import android.util.Log; -import android.view.View; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; import static android.support.v7.widget.LinearLayoutManager.VERTICAL; @@ -258,8 +260,8 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (!layingOutInPrimaryDirection) { // fill the remaining spacing this row - int itemSpanIndex = getSpanIndex(rangeStyle.mSpanSizeLookup, rangeStyle.mSpanCount, recycler, state, layoutState.getCurrentPosition()); - int itemSpanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, layoutState.getCurrentPosition()); + int itemSpanIndex = getSpanIndex(rangeStyle.mSpanSizeLookup, rangeStyle.mSpanCount, recycler, state, currentPosition); + int itemSpanSize = getSpanSize(rangeStyle.mSpanSizeLookup, recycler, state, currentPosition); remainingSpan = itemSpanIndex + itemSpanSize; @@ -343,20 +345,12 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state break; // item did not fit into this row or column } - View view = layoutState.next(recycler); - if (view == null) { - break; - } - if (!isStartLine) { isStartLine = helper.getReverseLayout() ? pos == mRangeStyle.getRange().getUpper().intValue() : pos == mRangeStyle.getRange().getLower().intValue(); } if (!isSecondStartLine) { if (!rangeStyle.equals(mRangeStyle)) { - if (mLayoutWithAnchor) { - pos = layoutState.getCurrentPosition(); - } isSecondStartLine = helper.getReverseLayout() ? pos == rangeStyle.getRange().getUpper() .intValue() : pos == rangeStyle.getRange().getLower().intValue(); } @@ -369,14 +363,19 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (!isSecondEndLine) { if (!rangeStyle.equals(mRangeStyle)) { - if (mLayoutWithAnchor) { - pos = layoutState.getCurrentPosition(); - } isSecondEndLine = helper.getReverseLayout() ? pos == rangeStyle.getRange().getLower() .intValue() : pos == rangeStyle.getRange().getUpper().intValue(); + if (DEBUG) { + Log.d(TAG, "isSecondEndLineLogic:" + isSecondEndLine + " helper.getReverseLayout()=" + helper.getReverseLayout() + " pos=" + pos + " rangeStyle.getRange().getLower()=" + rangeStyle.getRange().getLower() + " rangeStyle.getRange().getUpper()=" + rangeStyle.getRange().getUpper()); + } } } + View view = layoutState.next(recycler); + if (view == null) { + break; + } + consumedSpanCount += spanSize; rangeStyle.mSet[count] = view; count++; @@ -528,6 +527,9 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (isSecondEndLine) { secondEndSpace = (layoutInVertical ? rangeStyle.getMarginBottom() + rangeStyle.getPaddingBottom() : rangeStyle.getMarginRight() + rangeStyle.getPaddingRight()); + if (DEBUG) { + Log.d(TAG, "isSecondEndLineLogic:" + isSecondEndLine + " pos=" + currentPosition + " secondEndSpace=" + secondEndSpace); + } } @@ -613,8 +615,8 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (DEBUG) { Log.d(TAG, - (layoutStart ? "⬆ " : "⬇ ") + currentPosition + " consumed " + result.mConsumed + " startSpace " + startSpace + " endSpace " - + endSpace + " secondStartSpace " + secondStartSpace + " secondEndSpace " + secondEndSpace + " lastUnconsumedSpace " + lastUnconsumedSpace); + (layoutStart ? "⬆ " : "⬇ ") + currentPosition + " consumed " + result.mConsumed + " startSpace " + startSpace + " endSpace " + + endSpace + " secondStartSpace " + secondStartSpace + " secondEndSpace " + secondEndSpace + " lastUnconsumedSpace " + lastUnconsumedSpace + " isSecondEndLine=" + isSecondEndLine); } int left = 0, right = 0, top = 0, bottom = 0; @@ -670,7 +672,7 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (DEBUG) { Log.d(TAG, "layout item in position: " + params.getViewPosition() + " with text with SpanIndex: " + index + " into (" + - left + ", " + top + ", " + right + ", " + bottom + " )"); + left + ", " + top + ", " + right + ", " + bottom + "), topInfo=[layoutState.getOffset()=" + layoutState.getOffset() + " startSpace=" + startSpace + " secondStartSpace=" + secondStartSpace + " consumedGap=" + consumedGap + " lastUnconsumedSpace=" + lastUnconsumedSpace + "]"); } // We calculate everything with View's bounding box (which includes decor and margins) @@ -917,13 +919,13 @@ public GridRangeStyle findRangeStyleByPosition(int position) { } private GridRangeStyle findRangeStyle(GridRangeStyle rangeStyle, int position){ - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - GridRangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); - Range range = rangeStyle.mChildren.keyAt(i); + for (Map.Entry, GridRangeStyle> entry : rangeStyle.mChildren.entrySet()) { + GridRangeStyle childRangeStyle = entry.getValue(); + Range range = entry.getKey(); if (!childRangeStyle.isChildrenEmpty()){ return findRangeStyle(childRangeStyle, position); } else if (range.contains(position)) { - return rangeStyle.mChildren.valueAt(i); + return childRangeStyle; } } return rangeStyle; @@ -932,11 +934,11 @@ private GridRangeStyle findRangeStyle(GridRangeStyle rangeStyle, int position){ public GridRangeStyle findSiblingStyleByPosition(int position) { GridRangeStyle rangeStyle = null; if (mParent != null) { - ArrayMap, GridRangeStyle> siblings = mParent.mChildren; - for (int i = 0, size = siblings.size(); i < size; i++) { - Range range = siblings.keyAt(i); + HashMap, GridRangeStyle> siblings = mParent.mChildren; + for (Map.Entry, GridRangeStyle> entry : siblings.entrySet()) { + Range range = entry.getKey(); if (range.contains(position)) { - GridRangeStyle childRangeStyle = siblings.valueAt(i); + GridRangeStyle childRangeStyle = entry.getValue(); if (!childRangeStyle.equals(this)) { rangeStyle = childRangeStyle; } @@ -949,8 +951,8 @@ public GridRangeStyle findSiblingStyleByPosition(int position) { public void onInvalidateSpanIndexCache() { mSpanSizeLookup.invalidateSpanIndexCache(); - for (int i = 0, size = mChildren.size(); i < size; i++) { - GridRangeStyle rangeStyle = mChildren.valueAt(i); + for (Map.Entry, GridRangeStyle> entry : mChildren.entrySet()) { + GridRangeStyle rangeStyle = entry.getValue(); rangeStyle.onInvalidateSpanIndexCache(); } } @@ -958,8 +960,8 @@ public void onInvalidateSpanIndexCache() { public static int computeEndAlignOffset(GridRangeStyle rangeStyle, boolean layoutInVertical) { int offset = layoutInVertical ? rangeStyle.mMarginBottom + rangeStyle.mPaddingBottom : rangeStyle.mMarginRight + rangeStyle.mPaddingRight; int endPosition = rangeStyle.getRange().getUpper().intValue(); - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - GridRangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); + for (Map.Entry, GridRangeStyle> entry : rangeStyle.mChildren.entrySet()) { + GridRangeStyle childRangeStyle = entry.getValue(); if (!childRangeStyle.isChildrenEmpty()){ offset += computeEndAlignOffset(childRangeStyle, layoutInVertical); }else if (childRangeStyle.mRange.getUpper().intValue() == endPosition) { @@ -974,10 +976,10 @@ public static int computeEndAlignOffset(GridRangeStyle rangeStyle, boolean layou public static int computeStartAlignOffset(GridRangeStyle rangeStyle, boolean layoutInVertical) { int offset = layoutInVertical ? -rangeStyle.mMarginTop - rangeStyle.mPaddingTop : -rangeStyle.mMarginLeft - rangeStyle.mPaddingLeft; int startPosition = rangeStyle.getRange().getLower().intValue(); - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - GridRangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); + for (Map.Entry, GridRangeStyle> entry : rangeStyle.mChildren.entrySet()) { + GridRangeStyle childRangeStyle = entry.getValue(); if (!childRangeStyle.isChildrenEmpty()){ - //FIXEME may compute the wrong start space here + //FIXME may compute the wrong start space here offset += computeStartAlignOffset(childRangeStyle, layoutInVertical); }else if (childRangeStyle.mRange.getLower().intValue() == startPosition) { offset += (layoutInVertical ? -childRangeStyle.mMarginTop - childRangeStyle.mPaddingTop diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java index 160a7bb6..0f53bb28 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/RangeStyle.java @@ -1,6 +1,8 @@ package com.alibaba.android.vlayout.layout; import java.lang.reflect.Array; +import java.util.HashMap; +import java.util.Map; import com.alibaba.android.vlayout.LayoutManagerHelper; import com.alibaba.android.vlayout.OrientationHelperEx; @@ -43,7 +45,7 @@ public class RangeStyle { protected Range mRange; //TODO update data structure - protected ArrayMap, T> mChildren = new ArrayMap<>(); + protected HashMap, T> mChildren = new HashMap<>(); protected int mPaddingLeft; @@ -404,9 +406,9 @@ public boolean isLastPosition(int position) { public void setRange(int start, int end) { mRange = Range.create(start, end); if (!mChildren.isEmpty()) { - SimpleArrayMap, T> newMap = new SimpleArrayMap<>(); - for (int i = 0, size = mChildren.size(); i < size; i++) { - T rangeStyle = mChildren.valueAt(i); + HashMap, T> newMap = new HashMap<>(); + for (Map.Entry, T> entry : mChildren.entrySet()) { + T rangeStyle = entry.getValue(); int newStart = rangeStyle.getOriginStartOffset() + start; int newEnd = rangeStyle.getOriginEndOffset() + start; Range newRange = Range.create(newStart, newEnd); @@ -421,9 +423,9 @@ public void setRange(int start, int end) { public void beforeLayout(RecyclerView.Recycler recycler, RecyclerView.State state, LayoutManagerHelper helper) { if (!isChildrenEmpty()) { - for (int i = 0, size = mChildren.size(); i < size; i++) { - RangeStyle rangeStyle = mChildren.valueAt(i); - rangeStyle.beforeLayout(recycler, state, helper); + for (Map.Entry, T> entry : mChildren.entrySet()) { + RangeStyle childRangeStyle = entry.getValue(); + childRangeStyle.beforeLayout(recycler, state, helper); } } if (requireLayoutView()) { @@ -452,9 +454,9 @@ public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state LayoutManagerHelper helper) { if (!isChildrenEmpty()) { - for (int i = 0, size = mChildren.size(); i < size; i++) { - RangeStyle rangeStyle = mChildren.valueAt(i); - rangeStyle.afterLayout(recycler, state, startPosition, endPosition, scrolled, helper); + for (Map.Entry, T> entry : mChildren.entrySet()) { + RangeStyle childRangeStyle = entry.getValue(); + childRangeStyle.afterLayout(recycler, state, startPosition, endPosition, scrolled, helper); } } if (DEBUG) { @@ -521,8 +523,8 @@ public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state private void unionChildRegion(RangeStyle rangeStyle) { if (!rangeStyle.isChildrenEmpty()) { - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - RangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); + for (Map.Entry, T> entry : rangeStyle.mChildren.entrySet()) { + RangeStyle childRangeStyle = entry.getValue(); unionChildRegion(childRangeStyle); if (childRangeStyle.mLayoutView != null) { rangeStyle.mLayoutRegion.union(childRangeStyle.mLayoutView.getLeft(), childRangeStyle.mLayoutView.getTop(), @@ -534,8 +536,8 @@ private void unionChildRegion(RangeStyle rangeStyle) { private void removeChildViews(LayoutManagerHelper helper, RangeStyle rangeStyle) { if (!rangeStyle.isChildrenEmpty()) { - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - RangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); + for (Map.Entry, T> entry : rangeStyle.mChildren.entrySet()) { + RangeStyle childRangeStyle = entry.getValue(); removeChildViews(helper, childRangeStyle); } } @@ -551,8 +553,8 @@ private void removeChildViews(LayoutManagerHelper helper, RangeStyle rangeSty public void adjustLayout(int startPosition, int endPosition, LayoutManagerHelper helper) { if (!isChildrenEmpty()) { - for (int i = 0, size = mChildren.size(); i < size; i++) { - RangeStyle rangeStyle = mChildren.valueAt(i); + for (Map.Entry, T> entry : mChildren.entrySet()) { + RangeStyle rangeStyle = entry.getValue(); rangeStyle.adjustLayout(startPosition, endPosition, helper); } } @@ -605,8 +607,8 @@ private void hideLayoutViews(LayoutManagerHelper helper) { } private void hideChildLayoutViews(LayoutManagerHelper helper, RangeStyle rangeStyle) { - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - RangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); + for (Map.Entry, T> entry : rangeStyle.mChildren.entrySet()) { + RangeStyle childRangeStyle = entry.getValue(); if (!childRangeStyle.isChildrenEmpty()) { hideChildLayoutViews(helper, childRangeStyle); } @@ -628,8 +630,8 @@ public boolean requireLayoutView() { private boolean requireChildLayoutView(RangeStyle rangeStyle) { boolean self = rangeStyle.mBgColor != 0 || rangeStyle.mLayoutViewBindListener != null; - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - RangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); + for (Map.Entry, T> entry : rangeStyle.mChildren.entrySet()) { + RangeStyle childRangeStyle = entry.getValue(); if (!childRangeStyle.isChildrenEmpty()) { self |= requireChildLayoutView(childRangeStyle); } else { @@ -688,8 +690,8 @@ private void clearChild(LayoutManagerHelper helper, RangeStyle rangeStyle) { return; } - for (int i = 0, size = rangeStyle.mChildren.size(); i < size; i++) { - RangeStyle childRangeStyle = rangeStyle.mChildren.valueAt(i); + for (Map.Entry, T> entry : rangeStyle.mChildren.entrySet()) { + RangeStyle childRangeStyle = entry.getValue(); clearChild(helper, childRangeStyle); } } diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StaggeredGridLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StaggeredGridLayoutHelper.java index 08cb76d3..42c27d2d 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StaggeredGridLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StaggeredGridLayoutHelper.java @@ -41,7 +41,6 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.view.ViewCompat; -import android.support.v7.widget.OrientationHelper; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView.LayoutParams; import android.util.Log; @@ -89,6 +88,10 @@ public class StaggeredGridLayoutHelper extends BaseLayoutHelper { private List prelayoutViewList = new ArrayList<>(); + private boolean mLayoutWithAnchor; + + private int anchorPosition; + private WeakReference mLayoutManager = null; private final Runnable checkForGapsRunnable = new Runnable() { @@ -190,6 +193,7 @@ public void beforeLayout(RecyclerView.Recycler recycler, RecyclerView.State stat @Override public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state, int startPosition, int endPosition, int scrolled, LayoutManagerHelper helper) { super.afterLayout(recycler, state, startPosition, endPosition, scrolled, helper); + mLayoutWithAnchor = false; if (startPosition > getRange().getUpper() || endPosition < getRange().getLower()) { //do not in visible screen, skip return; @@ -239,6 +243,7 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state prelayoutViewList.clear(); while (layoutState.hasMore(state) && !mRemainingSpans.isEmpty() && !isOutOfRange(layoutState.getCurrentPosition())) { boolean isStartLine = false, isEndLine = false; + int currentPosition = layoutState.getCurrentPosition(); View view = layoutState.next(recycler); if (view == null) { @@ -260,7 +265,7 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state } // handle margin for start/end line isStartLine = position - getRange().getLower() < mNumLanes; - isEndLine = getRange().getUpper() - position < mNumLanes; //fix the end line condiition + isEndLine = getRange().getUpper() - position < mNumLanes; //fix the end line condition, edit by longerian if (layoutState.isPreLayout()) { prelayoutViewList.add(view); @@ -291,15 +296,22 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (isStartLine) { start += computeStartSpace(helper, layoutInVertical, true, isOverLapMargin); - //Log.d(TAG", "startLine " + position + " " + start); } else { - start += (layoutInVertical ? mVGap : mHGap); - //Log.d(TAG", "normalStartLine " + position + " " + start); + if (mLayoutWithAnchor) { + if (Math.abs(currentPosition - anchorPosition) < mNumLanes) { + //do not add extra gaps here + } else { + start += (layoutInVertical ? mVGap : mHGap); + } + } else { + start += (layoutInVertical ? mVGap : mHGap); + } } end = start + orientationHelper.getDecoratedMeasurement(view); } else { if (isEndLine) { - end = currentSpan.getStartLine(defaultNewViewLine, orientationHelper) - (layoutInVertical ? mMarginBottom + mPaddingRight : mMarginRight + mPaddingRight); + end = currentSpan.getStartLine(defaultNewViewLine, orientationHelper) - (layoutInVertical ? + mMarginBottom + mPaddingRight : mMarginRight + mPaddingRight); //Log.d(TAG, "endLine " + position + " " + end); } else { end = currentSpan.getStartLine(defaultNewViewLine, orientationHelper) - (layoutInVertical ? mVGap : mHGap); @@ -343,17 +355,19 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state handleStateOnResult(result, view); } - if (isOutOfRange(layoutState.getCurrentPosition())) { + if (isOutOfRange(layoutState.getCurrentPosition()) && mSpans != null) { // reach the end of layout, cache the gap // TODO: how to retain gap if (layoutState.getLayoutDirection() == LayoutStateWrapper.LAYOUT_START) { - for (Span span : mSpans) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; if (span.mCachedStart != INVALID_LINE) { span.mLastEdgeStart = span.mCachedStart; } } } else { - for (Span span : mSpans) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; if (span.mCachedEnd != INVALID_LINE) { span.mLastEdgeEnd = span.mCachedEnd; } @@ -392,18 +406,18 @@ private void recycleForPreLayout(RecyclerView.Recycler recycler, LayoutStateWrap Span span = findSpan(position, child, false); if (span != null) { span.popEnd(orientationHelper); - helper.removeChildView(child); - recycler.recycleView(child); } + helper.removeChildView(child); + recycler.recycleView(child); } else { LayoutParams lp = (LayoutParams) child.getLayoutParams(); int position = lp.getViewPosition(); Span span = findSpan(position, child, false); if (span != null) { span.popEnd(orientationHelper); - helper.removeChildView(child); - recycler.recycleView(child); } + helper.removeChildView(child); + recycler.recycleView(child); break; } } @@ -582,8 +596,11 @@ private void checkForGaps() { //FIXME do not clear loopup, may cause lane error while scroll //mLazySpanLookup.clear(); - for (Span span : mSpans) { - span.setLine(alignLine); + if (mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; + span.setLine(alignLine); + } } layoutManager.requestSimpleAnimationsInNextLayout(); @@ -607,9 +624,12 @@ private View hasGapsToFix(VirtualLayoutManager layoutManager, final int position BitSet mSpansToCheck = new BitSet(mNumLanes); mSpansToCheck.set(0, mNumLanes, true); - for (Span span : mSpans) { - if (span.mViews.size() != 0 && checkSpanForGap(span, layoutManager, alignLine)) { - return layoutManager.getReverseLayout() ? span.mViews.get(span.mViews.size() - 1) : span.mViews.get(0); + if (mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; + if (span.mViews.size() != 0 && checkSpanForGap(span, layoutManager, alignLine)) { + return layoutManager.getReverseLayout() ? span.mViews.get(span.mViews.size() - 1) : span.mViews.get(0); + } } } @@ -693,6 +713,9 @@ private void recycleFromEnd(RecyclerView.Recycler recycler, int line, LayoutMana private Span findSpan(int position, View child, boolean isStart) { int span = mLazySpanLookup.getSpan(position); + if (mSpans == null){ + return null; + } if (span >= 0 && span < mSpans.length) { Span sp = mSpans[span]; if (isStart && sp.findStart(child)) { @@ -914,8 +937,11 @@ public void onRefreshLayout(RecyclerView.State state, VirtualLayoutManager.Ancho if (BuildConfig.DEBUG) { Log.d(TAG, "onRefreshLayout span.clear()"); } - for (Span span : mSpans) { - span.clear(); + if (mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; + span.clear(); + } } } } @@ -947,20 +973,26 @@ public void checkAnchorInfo(RecyclerView.State state, VirtualLayoutManager.Ancho if (BuildConfig.DEBUG) { Log.d(TAG, "checkAnchorInfo span.clear()"); } - for (Span span : mSpans) { - span.clear(); - span.setLine(anchorInfo.coordinate); + if (mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; + span.clear(); + span.setLine(anchorInfo.coordinate); + } } } else { int anchorPos = anchorInfo.layoutFromEnd ? Integer.MIN_VALUE : Integer.MAX_VALUE; - for (Span span : mSpans) { - if (!span.mViews.isEmpty()) { - if (anchorInfo.layoutFromEnd) { - View view = span.mViews.get(span.mViews.size() - 1); - anchorPos = Math.max(anchorPos, helper.getPosition(view)); - } else { - View view = span.mViews.get(0); - anchorPos = Math.min(anchorPos, helper.getPosition(view)); + if (mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; + if (!span.mViews.isEmpty()) { + if (anchorInfo.layoutFromEnd) { + View view = span.mViews.get(span.mViews.size() - 1); + anchorPos = Math.max(anchorPos, helper.getPosition(view)); + } else { + View view = span.mViews.get(0); + anchorPos = Math.min(anchorPos, helper.getPosition(view)); + } } } } @@ -997,13 +1029,19 @@ public void checkAnchorInfo(RecyclerView.State state, VirtualLayoutManager.Ancho } } } + } else { + anchorPosition = anchorInfo.position; + mLayoutWithAnchor = true; } if (BuildConfig.DEBUG) { Log.d(TAG, "checkAnchorInfo span.cacheReferenceLineAndClear()"); } - for (Span span : mSpans) { - span.cacheReferenceLineAndClear(helper.getReverseLayout() ^ anchorInfo.layoutFromEnd, offset, orientationHelper); + if (mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; + span.cacheReferenceLineAndClear(helper.getReverseLayout() ^ anchorInfo.layoutFromEnd, offset, orientationHelper); + } } } } @@ -1011,7 +1049,7 @@ public void checkAnchorInfo(RecyclerView.State state, VirtualLayoutManager.Ancho @Override public void onItemsChanged(LayoutManagerHelper helper) { - mLazySpanLookup.clear(); +// mLazySpanLookup.clear(); } @Override @@ -1031,8 +1069,9 @@ public void onRestoreInstanceState(Bundle bundle) { @Override public void onOffsetChildrenVertical(int dy, LayoutManagerHelper helper) { super.onOffsetChildrenVertical(dy, helper); - if (helper.getOrientation() == VERTICAL) { - for (Span span : mSpans) { + if (helper.getOrientation() == VERTICAL && mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; span.onOffset(dy); } } @@ -1041,8 +1080,9 @@ public void onOffsetChildrenVertical(int dy, LayoutManagerHelper helper) { @Override public void onOffsetChildrenHorizontal(int dx, LayoutManagerHelper helper) { super.onOffsetChildrenHorizontal(dx, helper); - if (helper.getOrientation() == HORIZONTAL) { - for (Span span : mSpans) { + if (helper.getOrientation() == HORIZONTAL && mSpans != null) { + for (int i = 0, size = mSpans.length; i < size; i++) { + Span span = mSpans[i]; span.onOffset(dx); } } @@ -1326,7 +1366,7 @@ int invalidateAfter(int position) { } int getSpan(int position) { - if (mData == null || position >= mData.length) { + if (mData == null || position >= mData.length || position < 0) { return INVALID_SPAN_ID; } else { return mData[position]; diff --git a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StickyLayoutHelper.java b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StickyLayoutHelper.java index 8dad360d..3556eb2a 100644 --- a/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StickyLayoutHelper.java +++ b/vlayout/src/main/java/com/alibaba/android/vlayout/layout/StickyLayoutHelper.java @@ -24,16 +24,18 @@ package com.alibaba.android.vlayout.layout; +import android.support.annotation.Nullable; +import android.support.v7.widget.RecyclerView; +import android.util.Log; +import android.view.View; + import com.alibaba.android.vlayout.LayoutHelper; import com.alibaba.android.vlayout.LayoutManagerHelper; import com.alibaba.android.vlayout.OrientationHelperEx; import com.alibaba.android.vlayout.VirtualLayoutManager; import com.alibaba.android.vlayout.VirtualLayoutManager.LayoutStateWrapper; -import android.support.annotation.Nullable; -import android.support.v7.widget.RecyclerView; -import android.util.Log; -import android.view.View; +import java.util.List; import static android.support.v7.widget.LinearLayoutManager.VERTICAL; @@ -45,18 +47,32 @@ * @since 1.0.0 */ public class StickyLayoutHelper extends FixAreaLayoutHelper { + public interface StickyListener { + void onSticky(int pos, View view); + + void onUnSticky(int pos, View view); + } + + public interface Stackable { + boolean enable(); + } private static final String TAG = "StickyStartLayoutHelper"; private int mPos = -1; private boolean mStickyStart = true; - private int mOffset = 0; + private int mOffset = 0; private View mFixView = null; + private boolean mDoNormalHandle = false; + private boolean isLastStatusSticking = false; + + private StickyListener stickyListener; + private Stackable mStackable; public StickyLayoutHelper() { this(true); @@ -76,7 +92,7 @@ public void setOffset(int offset) { } public boolean isStickyNow() { - return !mDoNormalHandle; + return !mDoNormalHandle && mFixView != null; } @Override @@ -173,7 +189,9 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state top = orientationHelper.getStartAfterPadding() + mMarginTop + mOffset + mAdjuster.top; bottom = top + result.mConsumed; } else { - Log.i("Sticky", "remainingSpace: " + remainingSpace + " offset: " + mOffset); + if (VirtualLayoutManager.sDebuggable) { + Log.i("Sticky", "remainingSpace: " + remainingSpace + " offset: " + mOffset); + } } } @@ -219,12 +237,9 @@ public void layoutViews(RecyclerView.Recycler recycler, RecyclerView.State state if (mDoNormalHandle) { helper.addChildView(layoutState, view); handleStateOnResult(result, view); - mFixView = null; } else { // result.mConsumed += mOffset; } - - } @@ -279,6 +294,7 @@ public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state } } + View stickyView = mFixView; // Not in normal flow if (!mDoNormalHandle && mFixView != null) { // already capture in layoutViews phase @@ -291,12 +307,25 @@ public void afterLayout(RecyclerView.Recycler recycler, RecyclerView.State state } else { fixLayoutStateInCase2(orientationHelper, recycler, startPosition, endPosition, helper); } + + if (stickyListener != null) { + if (isLastStatusSticking && !isStickyNow()) { + stickyListener.onUnSticky(mPos, stickyView); + isLastStatusSticking = false; + } else if (!isLastStatusSticking && isStickyNow()) { + stickyListener.onSticky(mPos, mFixView); + isLastStatusSticking = true; + } + } } private void fixLayoutStateFromAbnormal2Normal(OrientationHelperEx orientationHelper, RecyclerView.Recycler recycler, int startPosition, int endPosition, - LayoutManagerHelper helper) { + LayoutManagerHelper helper) { //fix status, from abnormal to normal - Log.i(TAG, "abnormal pos: " + mPos + " start: " + startPosition + " end: " + endPosition); + if (VirtualLayoutManager.sDebuggable) { + Log.i(TAG, "abnormal pos: " + mPos + " start: " + startPosition + " end: " + endPosition); + } + if (mFixView != null) { int top, bottom; View refer = null; @@ -344,13 +373,14 @@ private void fixLayoutStateFromAbnormal2Normal(OrientationHelperEx orientationHe } private void fixLayoutStateInCase1(OrientationHelperEx orientationHelper, RecyclerView.Recycler recycler, int startPosition, int endPosition, - LayoutManagerHelper helper) { + LayoutManagerHelper helper) { // considering the case when last layoutHelper has margin bottom // 1. normal flow to abnormal flow; 2. abnormal flow to normal flow if ((mStickyStart && endPosition >= mPos) || (!mStickyStart && startPosition <= mPos)) { int consumed = orientationHelper.getDecoratedMeasurement(mFixView); boolean layoutInVertical = helper.getOrientation() == VERTICAL; - final int startAdjust = layoutInVertical ? mAdjuster.top : mAdjuster.left; + int extraTopOffset = getExtraTopOffset(helper); + final int startAdjust = layoutInVertical ? mAdjuster.top + extraTopOffset : mAdjuster.left; final int endAdjust = layoutInVertical ? mAdjuster.bottom : mAdjuster.right; int left = 0, top = 0, right = 0, bottom = 0; @@ -472,7 +502,9 @@ private void fixLayoutStateInCase1(OrientationHelperEx orientationHelper, Recycl if (mDoNormalHandle) { // offset if (index >= 0) { - helper.addChildView(mFixView, index); + if (mFixView.getParent() == null) { + helper.addChildView(mFixView, index); + } mFixView = null; } } else { @@ -487,7 +519,7 @@ private void fixLayoutStateInCase1(OrientationHelperEx orientationHelper, Recycl } private void fixLayoutStateInCase2(OrientationHelperEx orientationHelper, RecyclerView.Recycler recycler, int startPosition, int endPosition, - LayoutManagerHelper helper) { + LayoutManagerHelper helper) { // 1. normal flow to abnormal flow; 2. abnormal flow to normal flow // (mDoNormalHandle && mFixView != null) || (!mDoNormalHandle && mFixView == null) View eView = mFixView; @@ -498,13 +530,14 @@ private void fixLayoutStateInCase2(OrientationHelperEx orientationHelper, Recycl boolean normalHandle = false; boolean layoutInVertical = helper.getOrientation() == VERTICAL; - final int startAdjust = layoutInVertical ? mAdjuster.top : mAdjuster.left; + int extraTopOffset = getExtraTopOffset(helper); + final int startAdjust = layoutInVertical ? mAdjuster.top + extraTopOffset : mAdjuster.left; final int endAdjust = layoutInVertical ? mAdjuster.bottom : mAdjuster.right; if ((mStickyStart && endPosition >= mPos) || (!mStickyStart && startPosition <= mPos)) { if (eView == null) { // TODO? why do condition here? - if (mOffset + (mStickyStart ? startAdjust : endAdjust) > 0) { + if (mOffset + (mStickyStart ? startAdjust : endAdjust) >= 0) { normalHandle = true; } mFixView = recycler.getViewForPosition(mPos); @@ -661,7 +694,9 @@ private void fixLayoutStateInCase2(OrientationHelperEx orientationHelper, Recycl if (normalHandle) { // offset if (index >= 0) { - helper.addChildView(mFixView, index); + if (mFixView.getParent() == null) { + helper.addChildView(mFixView, index); + } mFixView = null; } } else { @@ -683,8 +718,8 @@ public View getFixedView() { public void onClear(LayoutManagerHelper helper) { super.onClear(helper); if (mFixView != null) { - helper.removeChildView(mFixView); helper.recycleView(mFixView); + helper.removeChildView(mFixView); mFixView = null; } } @@ -724,5 +759,44 @@ private void doMeasure(View view, LayoutManagerHelper helper) { } } + + public void setStickyListener(StickyListener stickyListener) { + this.stickyListener = stickyListener; + } + + public void setStackable(Stackable stackable) { + mStackable = stackable; + } + + /** + * + * get extra top offset when there are multi-sticky views at the top of current view + * in order to avoid views overlap + * the offset value is equal to total sticky views' height. + * @param helper + */ + private int getExtraTopOffset(LayoutManagerHelper helper) { + if (mStackable == null || !mStackable.enable()) { + return 0; + } + + int offset = 0; + if (helper instanceof VirtualLayoutManager){ + List helperList = ((VirtualLayoutManager) helper).getLayoutHelpers(); + for (LayoutHelper helperItem : helperList) { + if (helperItem.isFixLayout()) { + if (helperItem.getRange().getUpper() < this.getRange().getLower()) { + View view = helperItem.getFixedView(); + if (view != null) { + offset += view.getHeight(); + } + } + } + } + + } + + return offset; + } } diff --git a/vlayout/src/test/java/com/alibaba/android/vlayout/test/AdapterBuilder.java b/vlayout/src/test/java/com/alibaba/android/vlayout/test/AdapterBuilder.java deleted file mode 100644 index 131a7122..00000000 --- a/vlayout/src/test/java/com/alibaba/android/vlayout/test/AdapterBuilder.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2016 Alibaba Group - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alibaba.android.vlayout.test; - -import android.content.Context; -import android.support.v7.widget.RecyclerView; - -/** - * Created by villadora on 15/8/13. - */ -public class AdapterBuilder { - public static AdapterBuilder newBuilder(Context context) { - return new AdapterBuilder(); - } - - public RecyclerView.Adapter build() { - return null; - } -} diff --git a/vlayout/src/test/java/com/alibaba/android/vlayout/test/LinearLayoutHelperTest.java b/vlayout/src/test/java/com/alibaba/android/vlayout/test/LinearLayoutHelperTest.java deleted file mode 100644 index 384fc5be..00000000 --- a/vlayout/src/test/java/com/alibaba/android/vlayout/test/LinearLayoutHelperTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2016 Alibaba Group - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alibaba.android.vlayout.test; - -import android.app.Activity; -import android.support.v7.widget.RecyclerView; - -import com.alibaba.android.vlayout.VirtualLayoutManager; -import com.alibaba.android.vlayout.vlayout.BuildConfig; - -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.robolectric.Robolectric; -import org.robolectric.RobolectricGradleTestRunner; -import org.robolectric.annotation.Config; -import org.robolectric.shadows.ShadowLog; - -/** - * Created by villadora on 15/8/13. - */ -@RunWith(RobolectricGradleTestRunner.class) -@Config(constants = BuildConfig.class) -public class LinearLayoutHelperTest { - - private Activity mActivity; - - private RecyclerView mRecyclerView; - - private VirtualLayoutManager mLayoutManager; - - @Before - public void setup() { - ShadowLog.stream = System.out; - mActivity = Robolectric.buildActivity(Activity.class).create().get(); - mRecyclerView = new RecyclerView(mActivity); - mLayoutManager = new VirtualLayoutManager(mActivity); - } - - @Test - public void test_findFirstCompletelyVisibleItem() { - RecyclerView.Adapter adapter = AdapterBuilder.newBuilder(mActivity).build(); - // Utils.setupLayoutTest(null, adapter, mLayoutManager, mRecyclerView); - - Assert.assertEquals(0, mLayoutManager.findFirstCompletelyVisibleItemPosition()); - } - -} - diff --git a/vlayout/src/test/java/com/alibaba/android/vlayout/test/VirtualLayoutAdapterTest.java b/vlayout/src/test/java/com/alibaba/android/vlayout/test/VirtualLayoutAdapterTest.java deleted file mode 100644 index 6ddb1981..00000000 --- a/vlayout/src/test/java/com/alibaba/android/vlayout/test/VirtualLayoutAdapterTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * MIT License - * - * Copyright (c) 2016 Alibaba Group - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -package com.alibaba.android.vlayout.test; - -import com.alibaba.android.vlayout.vlayout.BuildConfig; - -import org.junit.runner.RunWith; -import org.robolectric.RobolectricTestRunner; -import org.robolectric.annotation.Config; - -/** - * Created by villadora on 15/8/7. - */ -@RunWith(RobolectricTestRunner.class) -@Config(constants = BuildConfig.class) -public class VirtualLayoutAdapterTest { - - -}