RecyclerView在中间,而不是顶部方向从横向变为纵向之后 [英] RecyclerView is in the middle instead of top after orientation changes from landscape to portrait
问题描述
我在一个片段中使用recyclerview。如果活动的configChanges包括取向,回收视图显示在屏幕的手机方向变化从横向到纵向后中间。然而它应该是在顶部始终。如果configChanges不包括方向,它总是出现在上方向变化上面。
你有任何想法是什么原因呢?
这是该活动的布局
< android.support.design.widget.CoordinatorLayout
的xmlns:机器人=http://schemas.android.com/apk/res/android
的xmlns:工具=http://schemas.android.com/tools
机器人:layout_width =match_parent
机器人:layout_height =match_parent
的xmlns:程序=http://schemas.android.com/apk/res-auto
工具:上下文=com.butterfly.LoginActivity> < android.support.design.widget.AppBarLayout
机器人:layout_width =match_parent
机器人:主题=@风格/ ThemeOverlay.AppCompat.Dark.ActionBar
机器人:layout_height =WRAP_CONTENT> < android.support.v7.widget.Toolbar
机器人:ID =@ + ID /工具栏
机器人:layout_width =match_parent
机器人:layout_height =?ATTR / actionBarSize
应用:layout_scrollFlags =滚动| enterAlways
应用:popupTheme =@风格/ ThemeOverlay.AppCompat.Light/> < /android.support.design.widget.AppBarLayout>
<的FrameLayout
应用:layout_behavior =@字符串/ appbar_scrolling_view_behavior
机器人:ID =@ + ID / butterflypi_fragment
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:layout_gravity =顶|开始/>
< /android.support.design.widget.CoordinatorLayout>
这是片段的布局替换上述的FrameLayout。
<的RelativeLayout的xmlns:机器人=http://schemas.android.com/apk/res/android
的xmlns:工具=http://schemas.android.com/tools的android:layout_width =match_parent
机器人:layout_height =match_parent
机器人:填充=8DP
的xmlns:card_view =http://schemas.android.com/apk/res-auto
工具:上下文=com.butterfly.fragment.ButterflyPIsFragment> < android.support.v7.widget.RecyclerView
机器人:ID =@ + ID / my_pi_recycler_view
机器人:滚动条=垂直
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:layout_alignParentTop =真 />
< / RelativeLayout的>
我找到了解决方案的这里。
基本上你创建你自己的行为类:
公共类PatchedScrollingViewBehavior扩展AppBarLayout.ScrollingViewBehavior { 公共PatchedScrollingViewBehavior(){
超();
} 公共PatchedScrollingViewBehavior(上下文的背景下,ATTRS的AttributeSet){
超(背景下,ATTRS);
} @覆盖
公共布尔onMeasureChild(CoordinatorLayout父母,子女观,诠释parentWidthMeasureSpec,诠释widthUsed,诠释parentHeightMeasureSpec,诠释heightUsed){
如果(child.getLayoutParams()==高度-1){
列出依赖性= parent.getDependencies(孩子);
如果(dependencies.isEmpty()){
返回false;
} AppBarLayout appBar = findFirstAppBarLayout(依赖);
如果(appBar = NULL&放大器;!&安培; ViewCompat.isLaidOut(appBar)){
如果(ViewCompat.getFitsSystemWindows(appBar)){
ViewCompat.setFitsSystemWindows(孩子,真);
} INT scrollRange = appBar.getTotalScrollRange();
// INT高度= parent.getHeight() - appBar.getMeasuredHeight()+ scrollRange;
INT上级高度= View.MeasureSpec.getSize(parentHeightMeasureSpec);
INT高度=上级高度 - appBar.getMeasuredHeight()+ scrollRange;
INT heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(高度,View.MeasureSpec.AT_MOST);
parent.onMeasureChild(儿童,parentWidthMeasureSpec,widthUsed,heightMeasureSpec,heightUsed);
返回true;
}
} 返回false;
}
私有静态AppBarLayout findFirstAppBarLayout(列表<视图>的观点){
INT I = 0; 对于(INT Z = views.size(); I< Z ++我){
查看查看=(查看)views.get(I)
如果(查看的instanceof AppBarLayout){
返回(AppBarLayout)视图。
}
} 返回null;
}
}
和不断变化的应用程序:layout_behavior在你的FrameLayout:
<的FrameLayout
应用:layout_behavior =your_package.PatchedScrollingViewBehavior
机器人:ID =@ + ID / butterflypi_fragment
机器人:layout_width =match_parent
机器人:layout_height =match_parent
机器人:layout_gravity =顶|开始/>
更新:正如我刚才检查 - 这个问题是固定在22.2.1库,所以请更新库,如果你还在使用22.2.0
I have used recyclerview in a fragment. If activity's configChanges includes orientation, recycler view appears in the middle of the screen after phone orientation changes from landscape to portrait. However it should be on top always. If configChanges does not include orientation, it always appear on top on orientation changes.
Do you have any idea what it is the reason?
This is the activity layout
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="com.butterfly.LoginActivity">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
android:layout_height="wrap_content">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>
<FrameLayout
app:layout_behavior="@string/appbar_scrolling_view_behavior"
android:id="@+id/butterflypi_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|start" />
</android.support.design.widget.CoordinatorLayout>
This is the fragment layout replaces framelayout above.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="8dp"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
tools:context="com.butterfly.fragment.ButterflyPIsFragment">
<android.support.v7.widget.RecyclerView
android:id="@+id/my_pi_recycler_view"
android:scrollbars="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
/>
</RelativeLayout>
I found solution here.
Basically you are creating your own behavior class:
public class PatchedScrollingViewBehavior extends AppBarLayout.ScrollingViewBehavior {
public PatchedScrollingViewBehavior() {
super();
}
public PatchedScrollingViewBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onMeasureChild(CoordinatorLayout parent, View child, int parentWidthMeasureSpec, int widthUsed, int parentHeightMeasureSpec, int heightUsed) {
if (child.getLayoutParams().height == -1) {
List dependencies = parent.getDependencies(child);
if (dependencies.isEmpty()) {
return false;
}
AppBarLayout appBar = findFirstAppBarLayout(dependencies);
if (appBar != null && ViewCompat.isLaidOut(appBar)) {
if (ViewCompat.getFitsSystemWindows(appBar)) {
ViewCompat.setFitsSystemWindows(child, true);
}
int scrollRange = appBar.getTotalScrollRange();
// int height = parent.getHeight() - appBar.getMeasuredHeight() + scrollRange;
int parentHeight = View.MeasureSpec.getSize(parentHeightMeasureSpec);
int height = parentHeight - appBar.getMeasuredHeight() + scrollRange;
int heightMeasureSpec = View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.AT_MOST);
parent.onMeasureChild(child, parentWidthMeasureSpec, widthUsed, heightMeasureSpec, heightUsed);
return true;
}
}
return false;
}
private static AppBarLayout findFirstAppBarLayout(List<View> views) {
int i = 0;
for (int z = views.size(); i < z; ++i) {
View view = (View) views.get(i);
if (view instanceof AppBarLayout) {
return (AppBarLayout) view;
}
}
return null;
}
}
and changing app:layout_behavior in your FrameLayout:
<FrameLayout
app:layout_behavior="your_package.PatchedScrollingViewBehavior"
android:id="@+id/butterflypi_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|start" />
UPDATE: As I just checked - this issue was fixed in 22.2.1 library, so please update library, if you are still using 22.2.0
这篇关于RecyclerView在中间,而不是顶部方向从横向变为纵向之后的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!