欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android实现评论栏随Recyclerview滑动左右移动

程序员文章站 2024-03-02 19:06:04
最近在玩一个叫“约会吧”的应用,也是在看直播app,默认下载安装的,安装点进去看这个应用做的不错,就留下来了。然后看他们动态详情页底部有一个效果:recyclerview滑...

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

Android实现评论栏随Recyclerview滑动左右移动

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

效果的实现

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

Android实现评论栏随Recyclerview滑动左右移动

这里说明下上面的图,分为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位置隐藏。这也就是上面应用的效果。

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

Android实现评论栏随Recyclerview滑动左右移动

效果图                                        
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实现评论栏随Recyclerview滑动左右移动

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

源码下载:recyclerview滑动左右移动

以上就是本文的全部内容,希望对大家学习android软件编程有所帮助。