Android应用怎么让按钮左移,Android实现评论栏随Recyclerview滑动左右移动

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

9aa7760e20b0c1408b2a867e57eb7cd9.gif

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

效果的实现

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

c488f794ca5132736efe2e9e874f34a9.png

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

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

7feb92fd3a90660462d1fc2dbbf6c6c6.png

效果图

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{

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 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{

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) {

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

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"/>

最后,看下实现的效果:

51272c747f81a57f68685d8afb6b662e.gif

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值