【问题标题】:Android BottomSheetBehavior for fragment with nested RecyclerView - strange items layout带有嵌套 RecyclerView 的片段的 Android BottomSheetBehavior - 奇怪的项目布局
【发布时间】:2017-01-14 11:32:03
【问题描述】:

我正在尝试使用片段作为 CoordinatorLayout 中的子项创建简单的测试项目,如果嵌套片段具有 RecyclerView 和 BottomSheetBehavior,我会遇到奇怪的布局问题。所以,我有一个根视图 - CoordinatorLayout,它包含两个 LinearLayouts(片段容器)。我希望第一个片段始终位于底部,允许第二个片段溢出它(就像 BottomSheet 一样)。 但是当我运行它时,我有一个奇怪的 RecyclerView 项目的布局行为。当我第一次扩展 BottomSheet 时,前几个项目可以正常工作,但是当我向下滚动回收站时,突然项目开始有屏幕大小的边距 - 所以屏幕上只有一个孩子可见。但它仍然允许滚动。当我向上滚动时,即使对于第一个项目,它也会保持这种行为,这在开始时表现正确。 我尝试使用自定义 RecyclerView.ItemDecoration 将项目顶部和底部边距设置为 0,但它没有帮助。 这是代码:
MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String TAG_SCROLL = "ScrollingFragment";
    private static final String TAG_BACK = "BgFragment";

    private View mBgContainer;
    private View mScrollContainer;

    @Override
    protected void onCreate( Bundle savedInstanceState ) {
        super.onCreate( savedInstanceState );
        setContentView( R.layout.activity_main );

        mBgContainer = findViewById( R.id.bg_container );
        mScrollContainer = findViewById( R.id.scroll_container );

        Fragment fragm = new ScrollingFragment();
        Fragment back  = new BackFragment();
        getSupportFragmentManager()
                .beginTransaction()
                .add( R.id.bg_container, back, TAG_BACK )
                .add( R.id.scroll_container, fragm, TAG_SCROLL )
                .commit();

        BottomSheetBehavior bottomSheetBehavior = BottomSheetBehavior.from( mScrollContainer );

        bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged( @NonNull View bottomSheet, int newState ) {

                if(newState==BottomSheetBehavior.STATE_EXPANDED){
                    bottomSheet.requestLayout();
                    bottomSheet.invalidate();
                }
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {

            }
        });
    }
}


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout android:id="@+id/main_container"
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context="com.nstudio.coordinatortest.MainActivity">

    <LinearLayout android:id="@+id/bg_container"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical"/>

    <LinearLayout android:id="@+id/scroll_container"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:orientation="vertical"
            app:behavior_hideable="false"
            app:behavior_peekHeight="80dp"
            app:layout_behavior="android.support.design.widget.BottomSheetBehavior"/>

</android.support.design.widget.CoordinatorLayout>


ScrollingFragment.java

public class ScrollingFragment extends Fragment {

    private RecyclerView mRecycler;
    private RecyclerView.LayoutManager mLayoutManager;

    @Nullable
    @Override
    public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState ) {
        View v = inflater.inflate( R.layout.scrolling_fragment, container, false );
        mRecycler = (RecyclerView)v.findViewById( R.id.recycler_view );
        mLayoutManager = new LinearLayoutManager( getContext() );
        mRecycler.setLayoutManager( mLayoutManager );
        mRecycler.setAdapter( new DummyAdapter() );
        mRecycler.addItemDecoration( new VerticalSpaceItemDecoration( 0 ) );
        return v;
    }
    private class DummyAdapter extends RecyclerView.Adapter<DummyViewHolder> {

        private String[] mColors = {"#000000", "#0000ff", "#00ff00", "#ff0000", "#00ffff", "#ff00ff", "#ffff00"};

        @Override
        public DummyViewHolder onCreateViewHolder( ViewGroup parent, int viewType ) {
            return new DummyViewHolder(LayoutInflater.from( getContext() ).inflate( R.layout.dummy_view, parent, false ));
        }

        @Override
        public void onBindViewHolder( DummyViewHolder holder, int position ) {
            holder.setText(position);
            int pos = position % (mColors.length-1);
            holder.setColor(mColors[pos]);
        }

        @Override
        public int getItemCount() {
            return 200;
        }
    }

    private class DummyViewHolder extends RecyclerView.ViewHolder {
        private TextView mTv;
        public DummyViewHolder( View itemView ) {
            super( itemView );
            mTv = (TextView)itemView.findViewById( R.id.tv );
        }

        public void setText(int position) {
            mTv.setText( Integer.toString( position ) );
        }

        public void setColor(String color) {
            mTv.setBackgroundColor( Color.parseColor( color ) );
        }
    }

    public class VerticalSpaceItemDecoration extends RecyclerView.ItemDecoration {

        private final int mVerticalSpaceHeight;

        public VerticalSpaceItemDecoration(int mVerticalSpaceHeight) {
            this.mVerticalSpaceHeight = mVerticalSpaceHeight;
        }

        @Override
        public void getItemOffsets( Rect outRect, View view, RecyclerView parent,
                                    RecyclerView.State state) {
            outRect.top = mVerticalSpaceHeight;
            outRect.bottom = mVerticalSpaceHeight;
        }
    }
}


scrolling_fragment.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
        android:background="#00ffa3">

    <android.support.v7.widget.RecyclerView
            android:id="@+id/recycler_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"/>

</LinearLayout>


dummy_view.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <TextView android:id="@+id/tv"
            android:layout_width="match_parent"
            android:layout_height="100dp"
            android:textColor="#ffffff"
            android:textSize="20sp"
            android:gravity="center"/>

</LinearLayout>


BackFragment.java

public class BackFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView( LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState ) {
        return inflater.inflate( R.layout.back_fragment, container, false );
    }
}


和 build.gradle

apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.1"

    defaultConfig {
        applicationId "com.nstudio.coordinatortest"
        minSdkVersion 16
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        debug {
            minifyEnabled false
            proguardFiles 'proguard-rules.pro'
        }
        release {
            minifyEnabled false
            proguardFiles 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:design:23.2.0'
    compile 'com.android.support:recyclerview-v7:23.2.0'
    compile 'com.android.support:design:23.2.0'
}

感谢任何帮助!

【问题讨论】:

    标签: android android-fragments android-recyclerview android-coordinatorlayout bottom-sheet


    【解决方案1】:

    回收站视图适配器中的每个项目都有整个窗口的高度。

    dummy_view.xml

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
                  android:orientation="vertical"
                  android:layout_width="match_parent"
                  android:layout_height="match_parent"> <!-- HERE -->
    
        <TextView android:id="@+id/tv"
                android:layout_width="match_parent"
                android:layout_height="100dp"
                android:textColor="#ffffff"
                android:textSize="20sp"
                android:gravity="center"/>
    
    </LinearLayout>
    

    将高度更改为wrap_content。这实际上是很合乎逻辑的,但是支持库版本 23.1.1(我认为)match_parent 被忽略了。

    【讨论】:

    • 谢谢,有帮助!我只是想知道,为什么第一个项目具有正常布局,而其他项目则不是......
    • 它没有正常的布局。顶部的第一个 100dp 是 TextView,它下面的其余屏幕是空的。以此类推,以此类推。
    猜你喜欢
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 2015-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    相关资源
    最近更新 更多