
最近在玩一个叫“约会吧”的应用,也是在看直播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
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
android:id="@+id/id_recyclerview"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
android:id="@+id/id_horization_rl"
android:layout_width="match_parent"
android:layout_height="60dp"
android:layout_alignParentBottom="true"
android:orientation="horizontal"
>
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">
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">
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"
/>
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" />
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">
android:layout_width="wrap_content"
android:layout_height="60dp"
android:gravity="center"
android:background="#eeeeee"
android:text="切换底部水平动画"
android:onClick="showHorization"/>
android:layout_width="wrap_content"
android:layout_height="60dp"
android:gravity="center"
android:background="#eeeeee"
android:onClick="showVertical"
android:layout_marginTop="10dp"
android:text="切换底部垂直动画"/>
然后,我们再写一个线程来实现滚动的效果。代码如下:
public class AnimationUtil implements Runnable
});
}
}
public void setOrientaion(boolean isHorization){
this.mOrientaion = isHorization;
}
//根据滑动变化,isScrollUp为true水平左边滑动,否则反之,
//为false垂直往下隐藏,否则反之,
public void startHideAnimation(boolean isScrollUp)
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 = cling(-mViewWidth,mViewWidth,dx);
mScroller.startScroll((int)mAnimationView.getTranslationX(),0,dx,0,DURATION);
ViewCompat.postOnAnimation(mAnimationView,this);
}
//显示控件
public void startShowAnimation()
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()
ViewCompat.setTranslationX(mAnimationView,mScroller.getCurrX());
}
}
public int getScreenWidth()
//控制在一个范围的值
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 else
}
//头部和底部动画操作
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)
public void showHorization(View view)
}
主要是onScrollStateChanged方法里面的操作。主要就是注意下评论布局控件的初始化就好了。
再贴下其他的类
TestAdapter.class
public class TestAdapter extends RecyclerView.Adapter{
private List mDataList;
private Context mContext;
private LayoutInflater mInflater;
public TestAdapter(List 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)
@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
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/white">
android:layout_width="match_parent"
android:layout_height="100dp"
android:orientation="horizontal"
android:gravity="center_vertical">
android:layout_width="60dp"
android:layout_height="60dp"
android:background="#EEEEEE"莫雷伦斯赛事前瞻
android:layout_margin="10dp"
android:src="@drawable/post_default_avatar"/>
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"/>
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:layout_marginTop="10dp"
android:background="#eeeeee"/>
最后,看下实现的效果:
这里 开发环境为android studio 2.1.0 -preview4
以上就是本文的全部内容,希望对大家学习Android软件编程有所帮助。

05月25日 英超第38轮 曼城vs阿斯顿维拉 全场录像回放
2026年05月26日
05月25日 英超第38轮 水晶宫vs阿森纳 全场录像回放
2026年05月26日
05月25日 英超第38轮 桑德兰vs切尔西 全场录像回放
2026年05月26日
05月25日 英超第38轮 利物浦vs布伦特福德 全场录像回放
2026年05月26日
05月25日 英超第38轮 布莱顿vs曼联 全场录像回放
2026年05月26日
05月25日 英超第38轮 热刺vs埃弗顿 全场录像回放
2026年05月26日
05月20日 英超第37轮 伯恩茅斯vs曼城 全场录像回放
2026年05月26日
05月19日 英超第37轮 阿森纳vs伯恩利 全场录像回放
2026年05月26日
05月20日 英超第37轮 切尔西vs热刺 全场录像回放
2026年05月26日
05月18日 英超第37轮 纽卡斯尔联vsv西汉姆联 全场录像回放
2026年05月26日
05月17日 英超第37轮 利兹联vs布莱顿 全场录像回放
2026年05月26日
05月17日 英超第37轮 狼队vs富勒姆 全场录像回放
2026年05月26日
05月17日 英超第37轮 埃弗顿vs桑德兰 全场录像回放
2026年05月26日
05月17日 英超第37轮 布伦特福德vs水晶宫 全场录像回放
2026年05月26日
05月17日 英超第37轮 曼联vs诺丁汉森林 全场录像回放
2026年05月26日
05月16日 德甲第34轮 柏林联合vs奥格斯堡 全场录像回放
2026年05月26日
05月16日 德甲第34轮 门兴vs霍芬海姆 全场录像回放
2026年05月26日
05月16日 德甲第34轮 海登海姆vs美因茨 全场录像回放
2026年05月26日
05月16日 德甲第34轮 弗赖堡vs莱比锡 全场录像回放
2026年05月26日
05月16日 德甲第34轮 圣保利vs沃尔夫斯堡 全场录像回放
2026年05月26日
05月16日 德甲第34轮 勒沃库森vs汉堡 全场录像回放
2026年05月26日
05月16日 德甲第34轮 法兰克福vs斯图加特 全场录像回放
2026年05月26日
05月17日 德甲第34轮 拜仁慕尼黑vs科隆 全场录像回放
2026年05月26日
05月16日 德甲第34轮 不莱梅vs多特蒙德 全场录像回放
2026年05月26日
05月18日 法甲第34轮 斯特拉斯堡vs摩纳哥 全场录像回放
2026年05月26日
05月18日 法甲第34轮 洛里昂vs勒阿弗尔 全场录像回放
2026年05月26日
05月18日 法甲第34轮 马赛vs雷恩 全场录像回放
2026年05月26日
05月18日 法甲第34轮 巴黎FCvs巴黎圣日耳曼 全场录像回放
2026年05月26日
05月18日 法甲第34轮 里尔vs欧塞尔 全场录像回放
2026年05月26日
05月18日 法甲第34轮 尼斯vs梅斯 全场录像回放
2026年05月26日
05月18日 法甲第34轮 布雷斯特vs昂热 全场录像回放
2026年05月26日
05月14日 法甲第29轮补赛 朗斯vs巴黎圣日耳曼 全场录像回放
2026年05月26日
05月14日 法甲第29轮 布雷斯特vs斯特拉斯堡 全场录像回放
2026年05月26日
05月24日 西甲第38轮 瓦伦西亚vs巴塞罗那 全场录像回放
2026年05月26日
05月24日 西甲第38轮 皇家马德里vs毕尔巴鄂竞技 全场录像回放
2026年05月26日
05月18日 西甲第37轮 巴塞罗那vs皇家贝蒂斯 全场录像回放
2026年05月26日
05月18日 西甲第37轮 塞维利亚vs皇家马德里 全场录像回放
2026年05月26日
05月18日 西甲第37轮 皇家社会vs瓦伦西亚 全场录像回放
2026年05月26日
05月18日 西甲第37轮 巴列卡诺vs比利亚雷亚尔 全场录像回放
2026年05月26日
05月18日 西甲第37轮 皇家奥维耶多vs阿拉维斯 全场录像回放
2026年05月26日
05月18日 西甲第37轮 奥萨苏纳vs西班牙人 全场录像回放
2026年05月26日
05月18日 西甲第37轮 莱万特vs马略卡 全场录像回放
2026年05月26日
05月18日 西甲第37轮 埃尔切vs赫塔费 全场录像回放
2026年05月26日
05月18日 西甲第37轮 马德里竞技vs赫罗纳 全场录像回放
2026年05月26日
05月18日 西甲第37轮 毕尔巴鄂竞技vs塞尔塔 全场录像回放
2026年05月26日
05月15日 西甲第36轮 皇家马德里vs皇家奥维耶多 全场录像回放
2026年05月26日
05月15日 西甲第36轮 赫罗纳vs皇家社会 全场录像回放
2026年05月26日
05月15日 西甲第36轮 瓦伦西亚vs巴列卡诺 全场录像回放
2026年05月26日
05月25日 意甲第38轮 维罗纳vs罗马 全场录像回放
2026年05月26日
05月25日 意甲第38轮 都灵vs尤文图斯 全场录像回放
2026年05月26日
05月25日 意甲第38轮 AC米兰vs卡利亚里 全场录像回放
2026年05月26日
05月24日 意甲第38轮 博洛尼亚vs国际米兰 全场录像回放
2026年05月26日
05月18日 意甲第37轮 萨索洛vs莱切 全场录像回放
2026年05月26日
05月18日 意甲第37轮 乌迪内斯vs克雷莫内塞 全场录像回放
2026年05月26日
05月18日 意甲第37轮 卡利亚里vs都灵 全场录像回放
2026年05月26日
05月18日 意甲第37轮 亚特兰大vs博洛尼亚 全场录像回放
2026年05月26日
05月17日 意甲第37轮 国际米兰vs维罗纳 全场录像回放
2026年05月26日
05月17日 意甲第37轮 罗马vs拉齐奥 全场录像回放
2026年05月26日
05月17日 意甲第37轮 比萨vs那不勒斯 全场录像回放
2026年05月26日
05月17日 意甲第37轮 尤文图斯vs佛罗伦萨 全场录像回放
2026年05月26日
05月17日 意甲第37轮 热那亚vsAC米兰 全场录像回放
2026年05月26日
05月12日 意甲第36轮 那不勒斯vs博洛尼亚 全场录像回放
2026年05月26日
06月11日 NBA总决赛G4 马刺vs尼克斯 全场录像回放
2026年06月12日
06月09日 NBA总决赛G3 马刺vs尼克斯 全场录像回放
2026年06月10日
06月06日 NBA总决赛G2 尼克斯vs马刺 全场录像回放
2026年06月07日
06月04日 NBA总决赛G1 尼克斯vs马刺 全场录像回放
2026年06月05日
05月31日 NBA西部决赛G7 马刺vs雷霆 全场录像回放
2026年06月01日
05月30日 WNBA常规赛 菲尼克斯水星vs纽约自由人 全场录像回放
2026年06月01日
05月29日 NBA西部决赛G6 雷霆vs马刺 全场录像回放
2026年05月30日
05月27日 NBA西部决赛G5 马刺vs雷霆 全场录像回放
2026年05月28日
05月26日 NBA东部决赛G4 尼克斯vs骑士 全场录像回放
2026年05月26日
05月25日 NBA西部决赛G4 雷霆vs马刺 全场录像回放
2026年05月26日
05月25日 WNBA常规赛 达拉斯飞翼vs纽约自由人 全场录像回放
2026年05月26日
05月24日 NBA东部决赛G3 尼克斯vs骑士 全场录像回放
2026年05月26日
05月23日 NBA西部决赛G3 雷霆vs马刺 全场录像回放
2026年05月26日
05月22日 WNBA常规赛 金州女武神vs纽约自由人 全场录像回放
2026年05月26日
05月22日 NBA东部决赛G2 骑士vs尼克斯 全场录像回放
2026年05月26日