当前位置: 移动技术网 > IT编程>移动开发>Android > Android实现评论栏随Recyclerview滑动左右移动

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

2019年07月24日  | 移动技术网IT编程  | 我要评论

shotloc,中学生暑假计划,郑绪岚近况

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

其实这种效果现在在应用中还是很常见的,有上拉,toolbar、底部view隐藏,下拉显示,或者像现在约会吧这样左右滑动的效果。而且网上资料现在也有很多,有通过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

源码下载:

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

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网