「这是我参与11月更文挑战的第10天,活动详情查看:2021最后一次更文挑战」
Android动画实现一般都用animation
动画包含三大类型View Animation
帧动画(Drawable Animation)
Property Animation(属性动画); 属性动画比较好用,可以重点关注一下。
既然是滚动肯定要按国际滚动标准——向上平移啦!
实现原理
利用平移动画translate完成动画向上平移
在res—下新建文件夹anim(animation的简称)
创建动画文件
anim_marquee_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromYDelta="100%p"
android:toYDelta="0"/>
<alpha
android:duration="500"
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
</set>
复制代码
anim_marquee_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="500"
android:fromYDelta="0"
android:toYDelta="-100%p"/>
<alpha
android:duration="500"
android:fromAlpha="1.0"
android:toAlpha="0.0"/>
</set>
复制代码
动画文件写好了就开始自定义view啦
首先来了解一下ViewFlipper
ViewFlipper是Android自带的一个多页面管理控件,且可以自动播放! 和ViewPager不同,ViewPager是一页页的,而ViewFlipper则是一层层的,和ViewPager一样,很多时候, 用来实现进入应用后的引导页,或者用于图片轮播。
android:inAnimation //设置View或ImageView进入屏幕时使用的动画
android:outAnimation //设置View或ImageView退出屏幕时使用的动画
android:flipInterval //设置View或ImageView之间切换的时间间隔
复制代码
常用方法:
setInAnimation:设置View或ImageView进入屏幕时使用的动画
setOutAnimation:设置View或ImageView退出屏幕时使用的动画
showNext:调用该方法来显示ViewFlipper里的下一个View或ImageView
showPrevious:调用该方法来显示ViewFlipper的上一个View或ImageView
setFilpInterval:设置View或ImageView之间切换的时间间隔
startFlipping:使用上面设置的时间间隔来开始切换所有的View或ImageView,切换会循环进行
stopFlipping:停止View或ImageView切换
复制代码
我们重写ViewFlipper
public class UPMarqueeView extends ViewFlipper
复制代码
完整代码
代码里面有注释
/**
* Created by JIULANG
*/
public class UPMarqueeView extends ViewFlipper {
private Context mContext;
private boolean isSetAnimDuration = false;
private int interval = 3000;//间隔时间
/**
* 动画时间
*/
private int animDuration = 500;
public UPMarqueeView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs, 0);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
this.mContext = context;
setFlipInterval(interval);
Animation animIn = AnimationUtils.loadAnimation(mContext, R.anim.anim_marquee_in);
if (isSetAnimDuration) animIn.setDuration(animDuration);
setInAnimation(animIn);
Animation animOut = AnimationUtils.loadAnimation(mContext, R.anim.anim_marquee_out);
if (isSetAnimDuration) animOut.setDuration(animDuration);
setOutAnimation(animOut);
}
/**
* 设置循环滚动的View数组
*
* @param views
*/
public void setViews(final List<View> views) {
if (views == null || views.size() == 0) return;
removeAllViews();
//遍历所有条目
for ( int i = 0; i < views.size(); i++) {
final int position=i;
//设置监听回调
views.get(i).setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
//绑定点击事件
if (onItemClickListener != null) {
onItemClickListener.onItemClick(position, views.get(position));
}
}
});
ViewGroup viewGroup = (ViewGroup) views.get(i).getParent();
if (viewGroup != null) {
viewGroup.removeAllViews();
}
addView(views.get(i));
}
startFlipping();
}
/**
* 点击
*/
private OnItemClickListener onItemClickListener;
/**
* 设置监听接口
* @param onItemClickListener
*/
public void setOnItemClickListener(OnItemClickListener onItemClickListener) {
this.onItemClickListener = onItemClickListener;
}
/**
* item_view的接口
*/
public interface OnItemClickListener {
void onItemClick(int position, View view);
}
}
复制代码
条目的布局
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:padding="8dp">
<ImageView
android:id="@+id/iv_cup"
android:layout_width="wrap_content"
android:layout_height="40dp"
android:src="@drawable/ic_vip5"
android:paddingTop="9dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
<TextView
android:id="@+id/name_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="@color/black"
android:textSize="16sp"
android:textStyle="bold"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/iv_cup"/>
<TextView
android:id="@+id/rank_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="14sp"
android:layout_marginLeft="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/name_type"/>
<TextView
android:id="@+id/no_data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hi"
android:textColor="@color/black"
android:textSize="14sp"
android:visibility="gone"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<ImageView
android:id="@+id/iv_portrait"
android:layout_width="26dp"
android:layout_height="26dp"
android:src="@drawable/ic_my"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
复制代码
使用方法
List<View> mViewList = new ArrayList<>();
UPMarqueeView mUPMarqueeView = findViewById(R.id.upMarqueeView);
//模拟加载数据
for (int i = 0; i < 9; i++) {
final View rankView = LayoutInflater.from(this).inflate(R.layout.view_main_rank, mUPMarqueeView, false);
TextView nameType = rankView.findViewById(R.id.name_type);
nameType.setText("九狼");
TextView rankType = rankView.findViewById(R.id.rank_type);
rankType.setText("点个赞吧!");
mViewList.add(rankView);
}
mUPMarqueeView.setViews(mViewList);
复制代码