码迷,mamicode.com
首页 > 移动开发 > 详细

仿约会吧应用详情页,评论栏随Recyclerview滑动左右移动

时间:2016-04-25 06:52:57      阅读:544      评论:0      收藏:0      [点我收藏+]

标签:

背景


最近在玩一个叫“约会吧”的应用,也是在看直播app,默认下载安装的,安装点进去看这个应用做的不错,就留下来了。然后看他们动态详情页底部有一个效果:Recyclerview滑动到的评论列表的时候,底部点赞那栏会往左滑动,出现一个输入评论的栏;然后下拉到底部的时候输入评论栏会往右滑动,出现点赞栏。详细细节直接来看效果图吧。

技术分享

其实这种效果现在在应用中还是很常见的,有上拉,toolbar、底部view隐藏,下拉显示,或者像现在约会吧这样左右滑动的效果。而且网上资料现在也有很多,比如RecyclerView上拉隐藏Toolbar,下拉显示效果 这篇文章通过ObjectAnimation来实现。想用这种方法的直接去看这篇文章。这里我们通过另外一种方法来实现。仔细下看下这个效果,其实他就是view滚动的效果,想到android里面的滚动,马上就能想到scroller类了,scroller有一个startScroll()方法,通过这个方法我们就可以滚动了。滚动问题解决了,那么这个效果就很简单了,进入页面时,把要显示view的先显示出来,不该显示的暂时放在屏幕外面,当滚动的时间,我们控制view进入屏幕或者退出屏幕。大概思路就是这样,下面我们就来实现这样的效果吧。


效果的实现

首先,我们根据上面的思路把布局给整出来。结构如下图:

技术分享

这里说明下上面的图,分为3块来说,
  • 当Recyclerview上拉的时候,屏幕内5位置的view会隐藏,也就是移动到屏幕外面的6位置,当Recyclerview下拉的时候,屏幕外面的6位置view又会回到5位置显示。
  • 当Recyclerview上拉的时候,屏幕内的1位置的view会隐藏,也就是移动到屏幕外面的4位置,当Recyclerview下拉的时候,屏幕外面的4位置view会回到1位置显示。
  • 当RecyclerView上拉的时候,而且设置为水平方向左右滑动的时候,屏幕内的1位置的view会移动到3位置,同时屏幕外面2位置view会移动到屏幕内1位置来显示,当RecyclerView下拉的时候,屏幕外的3位置会移动到屏幕内的1位置。1位置显示的view也会回到屏幕外的2位置隐藏。这也就是上面应用的效果。

    布局效果和代码如下(这里添加两个按钮来切换底部方向的效果):

    技术分享

            效果图                                         
    

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@android:color/white">
    <android.support.v7.widget.RecyclerView
        android:id="@+id/id_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
    <RelativeLayout
        android:id="@+id/id_horization_rl"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:layout_alignParentBottom="true"
        android:orientation="horizontal"
        >
    <TextView
        android:id="@+id/id_bottom_float"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="我是点赞操作布局"
        android:textSize="18sp"
        android:gravity="center"
        android:background="#E2E2E2">
    </TextView>
    <TextView
        android:id="@+id/id_bottom_comment"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="我是评论输入布局"
        android:textSize="18sp"
        android:gravity="center"
        android:background="#FF4500">
    </TextView>
    </RelativeLayout>
    <TextView
        android:id="@+id/id_bottom_vertical"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="你滑动,我随你而变"
        android:layout_alignParentBottom="true"
        android:background="#eeeeee"
        android:gravity="center"
        android:textSize="16sp"
        />
    <TextView
        android:id="@+id/id_top_vertical"
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:text="你滑动,我随你而变"
        android:background="#eeeeee"
        android:gravity="center"
        android:textSize="16sp" />
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/id_switch"
        android:orientation="vertical"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true">
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:gravity="center"
            android:background="#eeeeee"
            android:text="切换底部水平动画"
            android:onClick="showHorization"/>
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="60dp"
            android:gravity="center"
            android:background="#eeeeee"
            android:onClick="showVertical"
            android:layout_marginTop="10dp"
            android:text="切换底部垂直动画"/>
    </LinearLayout>
</RelativeLayout>

然后,我们再写一个线程来实现滚动的效果。代码如下:

public class AnimationUtil implements Runnable{
    private Context mContext;
    //传入需要操作的view
    private View mAnimationView;
    //view的宽和高
    private int mViewWidth;
    private int mViewHeight;
    //动画执行时间
    private final int DURATION = 400;
    //是水平还是垂直滑动变化
    public boolean mOrientaion ;
    //滚动操作类
    private Scroller mScroller;
    private boolean isShow;
    public AnimationUtil(Context context,final View mAnimationView){
        this.mContext = context ;
        this.mAnimationView = mAnimationView ;
        mScroller = new Scroller(context,new LinearInterpolator());
        //水平布局这里以屏幕宽为准
        mViewWidth = getScreenWidth();
        mViewHeight = mAnimationView.getMeasuredHeight();
        if(mViewHeight==0){
            mAnimationView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    mAnimationView.getViewTreeObserver().removeOnPreDrawListener(this);
                    mViewHeight = mAnimationView.getMeasuredHeight();
                    return true;
                }
            });
        }
    }

    public void setOrientaion(boolean isHorization){
        this.mOrientaion = isHorization;
    }
    //根据滑动变化,isScrollUp为true水平左边滑动,否则反之,
    //为false垂直往下隐藏,否则反之,
    public void startHideAnimation(boolean isScrollUp){
        isShow = false ;
        if(!mOrientaion){
            int dy = (int) (mAnimationView.getTranslationY()+mViewHeight);
            if(!isScrollUp){
                dy = (int)(mAnimationView.getTranslationY() - mViewHeight);
            }
            dy = cling(-mViewHeight,mViewHeight,dy);
            mScroller.startScroll(0, (int) mAnimationView.getTranslationY(),0,dy,DURATION);
            ViewCompat.postOnAnimation(mAnimationView,this);
            return;
        }
        int dx = (int) (mAnimationView.getTranslationX()-mViewWidth);
        if(!isScrollUp){
            dx = (int)(mAnimationView.getTranslationX() + mViewWidth);
        }
        dx = cling(-mViewWidth,mViewWidth,dx);
        mScroller.startScroll((int)mAnimationView.getTranslationX(),0,dx,0,DURATION);
        ViewCompat.postOnAnimation(mAnimationView,this);
    }
    //显示控件
    public void startShowAnimation(){
        isShow = true ;
        if(!mOrientaion){
            int dy = (int) ViewCompat.getTranslationY(mAnimationView);
            dy = cling(-mViewHeight,mViewHeight,dy);
            mScroller.startScroll(0,dy,0,-dy,DURATION);
            ViewCompat.postOnAnimation(mAnimationView,this);
            return;
        }
        int dx = (int) ViewCompat.getTranslationX(mAnimationView);
        dx = cling(-mViewWidth,mViewWidth,dx);
        mScroller.startScroll(dx,0,-dx,0,DURATION);
        ViewCompat.postOnAnimation(mAnimationView,this);
    }
    //判断当前是否绑定动画控件是否显示,
    public boolean isShow() {
        return isShow;
    }

    //终止动画
    public void abortAnimation(){
        mScroller.abortAnimation();
    }
    @Override
    public void run() {
        if(mScroller.computeScrollOffset()){
            //动画没停止就继续滑动
            ViewCompat.postOnAnimation(mAnimationView,this);
            if(!mOrientaion){
                ViewCompat.setTranslationY(mAnimationView,mScroller.getCurrY());
                return;
            }
            ViewCompat.setTranslationX(mAnimationView,mScroller.getCurrX());
        }
    }
    public int getScreenWidth(){
        WindowManager windowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics dm = new DisplayMetrics();
        windowManager.getDefaultDisplay().getMetrics(dm);
        return dm.widthPixels;
    }
    //控制在一个范围的值
    public int cling(int min,int max,int value){
        return Math.min(Math.max(min, value), max);
    }
}

这里简单说下上面AnimationUtil线程,首先它会创建一个滚动操作类Scroller,然后获取需要滚动的view的宽和高的获取,这里宽直接取屏幕的宽度。同时还有一个mOrientaion属性,方向的控制。然后startHideAnimation和startShowAnimation两个方法。其中startHideAnimation中,我们计算出每个效果的初始位置的x和y。然后x和y轴移动的偏移量,然后startScroll方法的调用,然后把通过ViewCompat.postOnAnimation把移动动画绑定在传入的view里面。startShowAnimation方法也是同理。我们知道,调用了startScroll,只是告诉Scroller移动到什么位置,具体的移动信息是在computeScrollOffset获取。所以我们通过这个方法就去判断view是否移动完成,没有移动,继续调用当前线程,同时根据方向设置setTranslationY或者setTranslationX。

view滚动的帮助类实现完了,我们就写个Recyclerview来简单的测试下,MainActivity代码如下:

public class MainActivity extends AppCompatActivity {
    //通过recyclerview来提供滑动事件
    private RecyclerView mRecyclerView;
    //一些简单的测试数据
    private TestAdapter mRecyclerAdapter;
    //水平简单赞布局view绑定动画
    private AnimationUtil mZanAnimationUtil;
    //水平简单评论布局view绑定动画
    private AnimationUtil mCommAnimationUtil;
    //垂直底部view绑定动画
    private AnimationUtil mBottomVerticalUtil;
    //垂直头顶view绑定布局
    private AnimationUtil mTopVerticalUtil;
    private List<String> mDataList=Arrays.asList("对Ta说了悄悄话","冲哥","小欢","对象,你在哪","暖心男神","一次就好",
            "对Ta说了悄悄话","冲哥","小欢","对象,你在哪","暖心男神","一次就好",
            "对Ta说了悄悄话","冲哥","小欢","对象,你在哪","暖心男神","一次就好",
            "对Ta说了悄悄话","冲哥","小欢","对象,你在哪","暖心男神","一次就好");
    private LinearLayoutManager mRecyclerManager;
    //赞布局控件
    private TextView mZanTextView;
    //评论布局控件
    private TextView mCommentView;
    private RelativeLayout mHorizationalRl;
    //底部布局控件
    private TextView mVerticalBottomTv;
    //头部布局控件
    private TextView mVerticalTopTv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mRecyclerView = (RecyclerView) findViewById(R.id.id_recyclerview);
        mZanTextView = (TextView) findViewById(R.id.id_bottom_float);
        mCommentView = (TextView)findViewById(R.id.id_bottom_comment) ;
        mVerticalBottomTv = (TextView)findViewById(R.id.id_bottom_vertical);
        mHorizationalRl = (RelativeLayout)findViewById(R.id.id_horization_rl) ;
        mVerticalTopTv = (TextView)findViewById(R.id.id_top_vertical);
        mZanAnimationUtil = new AnimationUtil(this,mZanTextView);
        mCommAnimationUtil = new AnimationUtil(this,mCommentView);
        mBottomVerticalUtil = new AnimationUtil(this,mVerticalBottomTv);
        mTopVerticalUtil = new AnimationUtil(this,mVerticalTopTv);
        mZanAnimationUtil.setOrientaion(true);
        mCommAnimationUtil.setOrientaion(true);
        mCommAnimationUtil.startHideAnimation(false);
        mHorizationalRl.setVisibility(View.GONE);
        mRecyclerManager = new LinearLayoutManager(this);
        mRecyclerView.setLayoutManager(mRecyclerManager);
        mRecyclerAdapter = new TestAdapter(mDataList,this);
        mRecyclerView.setAdapter(mRecyclerAdapter);
        mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
            @Override
            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                //当滑动停止时动画开始
                if(newState == RecyclerView.SCROLL_STATE_IDLE){
                    //在到达某个item改变水平布局
                    if(mRecyclerManager.findFirstVisibleItemPosition()>4){
                        mZanAnimationUtil.startHideAnimation(true);
                        mCommAnimationUtil.startShowAnimation();
                    }else{
                        mZanAnimationUtil.startShowAnimation();
                        if(mCommAnimationUtil.isShow()){
                            mCommAnimationUtil.startHideAnimation(false);
                        }
                    }
                    //头部和底部动画操作
                    if(mRecyclerManager.findFirstVisibleItemPosition()>0){
                        mBottomVerticalUtil.startHideAnimation(true);
                        mTopVerticalUtil.startHideAnimation(false);
                    }else{
                        mBottomVerticalUtil.startShowAnimation();
                        mTopVerticalUtil.startShowAnimation();
                    }
                }
            }

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

            }
        });
    }
    public void showVertical(View view){
        mHorizationalRl.setVisibility(View.GONE);
        mVerticalBottomTv.setVisibility(View.VISIBLE);
    }
    public void showHorization(View view){
        mHorizationalRl.setVisibility(View.VISIBLE);
        mVerticalBottomTv.setVisibility(View.GONE);
    }
}

主要是onScrollStateChanged方法里面的操作。主要就是注意下评论布局控件的初始化就好了。

再贴下其他的类
TestAdapter.class

public class TestAdapter extends RecyclerView.Adapter<TestAdapter.SimpleViewHolder>{
    private List<String> mDataList;
    private Context mContext;
    private LayoutInflater mInflater;

    public TestAdapter(List<String> mDataList, Context mContext) {
        this.mDataList = mDataList;
        this.mContext = mContext;
        mInflater = LayoutInflater.from(mContext);
    }

    @Override
    public SimpleViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        return new SimpleViewHolder(mInflater.inflate(R.layout.simple_item,parent,false));
    }

    @Override
    public void onBindViewHolder(SimpleViewHolder holder, int position) {
        holder.mTextView.setText(mDataList.get(position));
    }

    @Override
    public int getItemCount() {
        return mDataList.size();
    }

    public class SimpleViewHolder extends RecyclerView.ViewHolder{
        private TextView mTextView;
        public SimpleViewHolder(View itemView) {
            super(itemView);
            this.mTextView = (TextView)itemView.findViewById(R.id.id_text);
        }
    }
}

simple_item.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="@android:color/white">
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="100dp"
        android:orientation="horizontal"
        android:gravity="center_vertical">
        <ImageView
            android:layout_width="60dp"
            android:layout_height="60dp"
            android:background="#EEEEEE"
            android:layout_margin="10dp"
            android:src="@drawable/post_default_avatar"/>
        <TextView
            android:id="@+id/id_text"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="21111111"
            android:textSize="14sp"
            android:layout_marginLeft="10dp"/>
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="0.5dp"
        android:layout_marginTop="10dp"
        android:background="#eeeeee"/>
</LinearLayout>

最后,看下实现的效果:

技术分享

这里 开发环境为android studio 2.1.0 -preview4

代码下载

仿约会吧应用详情页,评论栏随Recyclerview滑动左右移动

标签:

原文地址:http://blog.csdn.net/iamzgx/article/details/51236713

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!