隐藏视图与RecyclerView滚动的比例

时间:2015-09-02 05:09:45

标签: android android-layout scroll android-recyclerview

在我的Android应用程序中,我有一个recyclerview和LinearLayout。 LinearLayout位于顶部,recyclelerview位于线性布局。我的要求是当recyclerview开始滚动最后一项时,线性布局应该开始隐藏在滚动量的比例中。

我做了一点而且有效。但它与滚动量不成比例。这是我的代码

ScrollListener

public class MyScrollListener extends OnScrollListener {

    private LinearLayoutManager mLayoutManager;

    public MyScrollListener(LinearLayoutManager manager) {
        this.mLayoutManager = manager;
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {

        int visibleItemCount = mLayoutManager.getChildCount();
        int totalItemCount = mLayoutManager.getItemCount();
        int firstVisibleItem = mLayoutManager.findFirstVisibleItemPosition();

        if (visibleItemCount + firstVisibleItem >= totalItemCount) {
            scrollTheShit(dy * -1, ((View) recyclerView.getChildAt(visibleItemCount - 1)).getWidth());
        }
    }

    public void scrollTheShit(int dy, int widthOfLastChild) {}


}

MainActivity

public class MainActivity extends AppCompatActivity {

    RecyclerView recyclerView;
    LinearLayout linearLayout;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        linearLayout = (LinearLayout) findViewById(R.id.container);
        recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
        recyclerView.setHasFixedSize(true);
        final LinearLayoutManager mgr = new LinearLayoutManager(this);
        recyclerView.setLayoutManager(mgr);
        recyclerView.setAdapter(new RecyclerAdapter());


        recyclerView.addOnScrollListener(new MyScrollListener(mgr) {

            @Override
            public void scrollTheShit(int dy, int widthOfLastChild) {

                linearLayout.setY(linearLayout.getY() + dy );
            }
        });
    }


    private class RecyclerAdapter extends Adapter<RecyclerAdapter.ViewHolder> {


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

        @Override
        public void onBindViewHolder(ViewHolder viewHolder,
                                     int position) {
        }

        @Override
        public ViewHolder onCreateViewHolder(ViewGroup parent, int position) {
            View v = LayoutInflater.from(MainActivity.this)
                    .inflate(R.layout.child, parent, false);
            ViewHolder holder = new ViewHolder(v);
            return holder;
        }

        public class ViewHolder extends RecyclerView.ViewHolder {

            public ViewHolder(View arg0) {
                super(arg0);
            }

        }
    }

}

当下面的RecyclerView滚动时,我必须隐藏顶部 enter image description here

我该如何纠正?有人请帮助我

1 个答案:

答案 0 :(得分:0)

这可能会对你有所帮助

QuickReturnRecyclerView.java

import android.content.Context;
import android.os.Build;
import android.support.v7.widget.RecyclerView;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.view.animation.TranslateAnimation;
import android.widget.FrameLayout;

public class QuickReturnRecyclerView extends RecyclerView {
    private static final String TAG = QuickReturnRecyclerView.class.getName();

    private View mReturningView;
    private static final int STATE_ONSCREEN = 0;
    private static final int STATE_OFFSCREEN = 1;
    private static final int STATE_RETURNING = 2;
    private int mState = STATE_ONSCREEN;
    private int mMinRawY = 0;
    private int mReturningViewHeight;
    private int mGravity = Gravity.BOTTOM;

    public QuickReturnRecyclerView(Context context) {
        super(context);
        init();
    }

    public QuickReturnRecyclerView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public QuickReturnRecyclerView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init(){
    }

    /**
     * The view that should be showed/hidden when scrolling the content.
     * Make sure to set the gravity on the this view to either Gravity.Bottom or
     * Gravity.TOP and to put it preferable in a FrameLayout.
     * @param view Any kind of view
     */
    public void setReturningView(View view) {
        mReturningView = view;

        try {
            FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) mReturningView.getLayoutParams();
            mGravity = params.gravity;
        } catch (ClassCastException e) {
            throw new RuntimeException("The return view need to be put in a FrameLayout");
        }

        measureView(mReturningView);
        mReturningViewHeight = mReturningView.getMeasuredHeight();
        addOnScrollListener(new RecyclerScrollListener());
    }

    private void measureView(View child) {
        ViewGroup.LayoutParams p = child.getLayoutParams();
        if (p == null) {
            p = new ViewGroup.LayoutParams(
                    ViewGroup.LayoutParams.FILL_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
        }

        int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0, p.width);
        int lpHeight = p.height;
        int childHeightSpec;
        if (lpHeight > 0) {
            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
        } else {
            childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
        }
        child.measure(childWidthSpec, childHeightSpec);
    }

    private class RecyclerScrollListener extends OnScrollListener {
        private int mScrolledY;

        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            if(mGravity == Gravity.BOTTOM)
                mScrolledY += dy;
            else if(mGravity == Gravity.TOP)
                mScrolledY -= dy;

            if(mReturningView == null)
                return;

            int translationY = 0;
            int rawY = mScrolledY;

            switch (mState) {
                case STATE_OFFSCREEN:
                    if(mGravity == Gravity.BOTTOM) {
                        if (rawY >= mMinRawY) {
                            mMinRawY = rawY;
                        } else {
                            mState = STATE_RETURNING;
                        }
                    } else if(mGravity == Gravity.TOP) {
                        if (rawY <= mMinRawY) {
                            mMinRawY = rawY;
                        } else {
                            mState = STATE_RETURNING;
                        }
                    }

                    translationY = rawY;
                    break;

                case STATE_ONSCREEN:
                    if(mGravity == Gravity.BOTTOM) {

                        if (rawY > mReturningViewHeight) {
                            mState = STATE_OFFSCREEN;
                            mMinRawY = rawY;
                        }
                    } else if(mGravity == Gravity.TOP) {

                        if (rawY < -mReturningViewHeight) {
                            mState = STATE_OFFSCREEN;
                            mMinRawY = rawY;
                        }
                    }
                    translationY = rawY;
                    break;

                case STATE_RETURNING:
                    if(mGravity == Gravity.BOTTOM) {
                        translationY = (rawY - mMinRawY) + mReturningViewHeight;

                        if (translationY < 0) {
                            translationY = 0;
                            mMinRawY = rawY + mReturningViewHeight;
                        }

                        if (rawY == 0) {
                            mState = STATE_ONSCREEN;
                            translationY = 0;
                        }

                        if (translationY > mReturningViewHeight) {
                            mState = STATE_OFFSCREEN;
                            mMinRawY = rawY;
                        }
                    } else if(mGravity == Gravity.TOP) {
                        translationY = (rawY + Math.abs(mMinRawY)) - mReturningViewHeight;

                        if (translationY > 0) {
                            translationY = 0;
                            mMinRawY = rawY - mReturningViewHeight;
                        }

                        if (rawY == 0) {
                            mState = STATE_ONSCREEN;
                            translationY = 0;
                        }

                        if (translationY < -mReturningViewHeight) {
                            mState = STATE_OFFSCREEN;
                            mMinRawY = rawY;
                        }
                    }
                    break;
            }

            /** this can be used if the build is below honeycomb **/
            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.HONEYCOMB) {
                TranslateAnimation anim = new TranslateAnimation(0, 0, translationY, translationY);
                anim.setFillAfter(true);
                anim.setDuration(0);
                mReturningView.startAnimation(anim);
            } else {
                mReturningView.setTranslationY(translationY);
            }
        }
    }
}

activity_main.xml中

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">

    <yourpackagename.QuickReturnRecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scrollbars="vertical" />

    <LinearLayout
        android:id="@+id/linear"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="top"
        android:background="@android:color/darker_gray"
        android:orientation="horizontal"
        android:padding="15dp">

        <Button
            android:id="@+id/button"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="left|top"
            android:layout_weight="1"
            android:text="New Button" />

        <Button
            android:id="@+id/button2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal|top"
            android:layout_weight="1"
            android:text="New Button" />

        <Button
            android:id="@+id/button3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_gravity="right|top"
            android:layout_weight="1"
            android:text="New Button" />
    </LinearLayout>


</FrameLayout>
MainActivity.java中的

只需添加以下行

        mRecyclerView = (QuickReturnRecyclerView) findViewById(R.id.recycler_view);
        linear = (LinearLayout) findViewById(R.id.linear);
        // use this setting to improve performance if you know that changes
        // in content do not change the layout size of the RecyclerView
        mRecyclerView.setHasFixedSize(true);

        // use a linear layout manager
        mLayoutManager = new LinearLayoutManager(getApplicationContext());
        mRecyclerView.setLayoutManager(mLayoutManager);

        mRecyclerView.setReturningView(linear);