之前做过的一个项目中要实现这样的效果:从屏幕的上端向下滑入一个带色的文字提示框,停留几秒之后再滑出屏幕之外。当时我并没有想到去用第三方库,自己摸索着做出来了。我的做法很简单,就是在界面的最上方放置一个TextView,然后给它设置滑出和滑入的动画。下图就是完成的效果:
看起来还是可以的。写法并不高明,但当时确实满足了我的需求,也让我在解决问题的过程中得到了锻炼。现在就来介绍一下我的做法吧。
1、创建项目
新建一个名为SlidingToast的项目,再新建一个SlidingToastActivity。项目创建完成之后,先来创建SlidingToast提示框的布局:
sliding_toast.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:paddingTop="5dp"
android:paddingBottom="5dp"
android:textColor="@android:color/white"
android:background="@android:color/holo_blue_light"
android:textSize="18sp"
android:id="@+id/tv_toast"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:orientation="vertical">
</TextView>
我需要的只是一个简单的TextView,你可以根据自己的需要创建改为复杂的布局,比如添加图片等等。跟Toast一样,提示框一般情况下是不会显示,也不会占用布局空间的。所以android:visibility
属性设为gone。
写好SlidingToast的布局之后,我们就可以到Activity的布局中使用了。但有一点务必要记住:SlidingToast不能被任何控件盖住,它必须覆盖在所有控件的上方。我采用的根布局是RelativeLayout,所以在布局文件中SlidingToast必须放置在最底层:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.lindroid.slidingtoast.SlidingToastActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="showSlidingToast"
android:text="显示SlidingToast"
android:textAllCaps="false" />
<include layout="@layout/sliding_toast" />
</RelativeLayout>
如果你的根布局是LinearLayout的话,我建议是在外面再包裹一层FrameLayout,使SlidingToast能够位于LinearLayout之上。布局的嵌套会影响性能,但这也是没办法的事。
2、实现动画效果
SlidingToast的动画分为两个步骤,第一步是先从根布局上方滑入,第二步是向上滑出根布局。这两步都可以用补间动画中的位移动画来实现,代码很简单:
public class SlidingToastActivity extends AppCompatActivity {
private TextView tvToast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_sliding_toast);
tvToast = (TextView) findViewById(R.id.tv_toast);
}
public void showSlidingToast(View view) {
tvToast.setVisibility(View.VISIBLE);
//设置SlidingToast的信息
tvToast.setText("这是一条提示信息");
//创建动画集合
AnimationSet animationSet = new AnimationSet(true);
//滑入的动画
TranslateAnimation inAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1, Animation.RELATIVE_TO_SELF, 0);
inAnimation.setDuration(500);
inAnimation.setFillAfter(true);
//将该滑入的位移动画添加到动画集合
animationSet.addAnimation(inAnimation);
//滑出的动画
TranslateAnimation outAnimation = new TranslateAnimation(Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, 0, Animation.RELATIVE_TO_SELF, -1);
outAnimation.setDuration(500);
outAnimation.setFillAfter(true);
//设置动画的启动时间,滑出动画在滑入动画的2秒后执行
outAnimation.setStartOffset(2000);
//将该滑出的位移动画添加到动画集合
animationSet.addAnimation(outAnimation);
//开启动画
tvToast.startAnimation(animationSet);
//动画监听事件,动画完成之后重新让SlidingToast消失
animationSet.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationStart(Animation animation) {
}
@Override
public void onAnimationEnd(Animation animation) {
tvToast.setVisibility(View.GONE);
}
@Override
public void onAnimationRepeat(Animation animation) {
}
});
}
}
只要具备补间动画的知识,上面的代码是很容易理解。我们分别设置滑入和滑出两个位移动画,两者的持续时间相等,但方向相反,而且执行顺序也有先后之分。我们可以创建一个动画集合AnimationSet对象,然后按照执行顺序将动画添加到集合中,再调用setStartOffset
方法让滑出动画在滑入动画执行完毕后的2秒启动。
动画执行完成,SlidingToast会停留在界面上,这显示不是我们想要的,所以给动画设置一个监听事件,在动画结束之后让SlidingToast消失。
3、后记
可能有些朋友已经忍不住吐槽了:“直接用第三方库Crouton不就行了吗?还整这么麻烦?”这……只能怪我孤陋寡闻,当时并不知道有Crouton这个库。不过有时候自己动手实现一下还是有所收获的,至少对于我来说,现阶段积累点代码量还是很有必要的。接下来,我也会去尝试一下Crouton,写一篇学习笔记。
源码下载:
SlidingToast
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。