这篇文章将为大家详细讲解有关使用VerticalBannerView怎么实现垂直轮播广告,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

专注于为中小企业提供做网站、成都网站制作服务,电脑端+手机端+微信端的三站合一,更高效的管理,为中小企业伊吾免费做网站提供优质的服务。我们立足成都,凝聚了一批互联网行业人才,有力地推动了上1000家企业的稳健成长,帮助中小企业通过网站建设实现规模扩充和转变。
一、项目使用
(1).添加项目依赖。
dependencies {
compile 'com.github.Rowandjj:VerticalBannerView:1.0'
}(2).添加布局。
(3).实现Adapter。
public class SampleAdapter extends BaseBannerAdapter{ private List mDatas; public SampleAdapter01(List datas) { super(datas); } @Override public View getView(VerticalBannerView parent) { return LayoutInflater.from(parent.getContext()).inflate(R.layout.your_item,null); } @Override public void setItem(final View view, final Model data) { TextView textView = (TextView) view.findViewById(R.id.text); textView.setText(data.title); // 你可以增加点击事件 view.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // TODO handle click event } }); } }
(4).为VerticalBannerView设置Adapter,并启动动画。
Listdatas = new ArrayList<>(); datas.add(new Model01("Note7发布了")); datas.add(new Model01("Note7被召回了")); SampleAdapter adapter = new SampleAdapter(datas); VerticalBannerView banner = (VerticalBannerView) findViewById(R.id.banner); banner.setAdapter(adapter); banner.start();
二、源码分析
实现原理:
VerticalBannerView本质上是一个垂直的LinearLayout。定义一个Adapter类,向LinearLayout提供子View。初始状态下往LinearLayout中添加两个子View,子View的高度同LinearLayout的高度一致,这样一来只有第1个子View显示出来,第2个子View在底部不显示。然后使用属性动画ObjectAnimator同时修改两个子View的translationY属性,动画执行过程中translationY从默认值0渐变到负的LinearLayout的高度,显示出来的效果就是第1个子View逐渐向上退出,第2个子View从底部向上逐渐显示。动画执行完毕后,移除第1个子View,这样第2个子View的索引变成0,并完全显示出来占据LinearLayout的高度。再将已经移除的第1个子View,添加到索引为1的位置,此时该子View超出父视图之外完全不显示。一轮动画执行完毕,再调用postDelay()方法重复上述动画,一直循环下去。
下面进入代码部分,主要是两个类BaseBannerAdapter和VerticalBannerView。
(1).BaseBannerAdapter类
BaseBannerAdapter类负责为广告栏提供数据。我们在使用时,需要写一个Adapter类继承BaseBannerAdapter,实现getView()和setItem()方法。在getView()方法中,我们需要把要添加到广告栏中的item view创建出来并返回,setItem()方法则负责为创建的item view绑定数据。
public abstract class BaseBannerAdapter{ private List mDatas; private OnDataChangedListener mOnDataChangedListener; public BaseBannerAdapter(List datas) { mDatas = datas; if (datas == null || datas.isEmpty()) { throw new RuntimeException("nothing to show"); } } public BaseBannerAdapter(T[] datas) { mDatas = new ArrayList<>(Arrays.asList(datas)); } // 设置banner填充的数据 public void setData(List datas) { this.mDatas = datas; notifyDataChanged(); } void setOnDataChangedListener(OnDataChangedListener listener) { mOnDataChangedListener = listener; } // 获取banner总数 public int getCount() { return mDatas == null ? 0 : mDatas.size(); } // 通知数据改变 void notifyDataChanged() { mOnDataChangedListener.onChanged(); } // 获取数据 public T getItem(int position) { return mDatas.get(position); } // 设置banner的ItemView public abstract View getView(VerticalBannerView parent); // 设置banner的数据 public abstract void setItem(View view, T data); // 数据变化的监听 interface OnDataChangedListener { void onChanged(); } }
(2).VerticalBannerView类
VerticalBannerView类继承自LinearLayout,并在构造方法中设定方向为垂直。同时VerticalBannerView类实现了OnDataChangedListener接口,实现onChanged()方法,这样当改变数据后调用BaseBannerAdapter的notifyDataChanged()时,VerticalBannerView的onChanged()方法被回调,执行setupAdapter()重新初始化数据。
public class VerticalBannerView extends LinearLayout implements BaseBannerAdapter.OnDataChangedListener {
public VerticalBannerView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
setOrientation(VERTICAL);
......
}
......
@Override
public void onChanged() {
setupAdapter();
}
......
}为VerticalBannerView添加item数据,需要调用setAdapter()方法,关键在于其中执行的setupAdapter()方法。
public void setAdapter(BaseBannerAdapter adapter) {
if (adapter == null) {
throw new RuntimeException("adapter must not be null");
}
if (mAdapter != null) {
throw new RuntimeException("you have already set an Adapter");
}
this.mAdapter = adapter;
mAdapter.setOnDataChangedListener(this);
setupAdapter();
}在setupAdapter()方法中,先移除所有的子View,然后调用Adapter的getView()方法创建两个子View,分别赋值给成员变量mFirstView和mSecondView,并为这两个子View绑定数据,最后再调用addView()添加进来。
// 初始化Child View
private void setupAdapter() {
// 先移除所有的子View
removeAllViews();
if (mAdapter.getCount() == 1) {
mFirstView = mAdapter.getView(this);
mAdapter.setItem(mFirstView, mAdapter.getItem(0));
addView(mFirstView);
} else {
// 调用Adapter的getView()方法,创建两个子View,分别赋值给mFirstView和mSecondView
mFirstView = mAdapter.getView(this);
mSecondView = mAdapter.getView(this);
// 使用索引0和1的数据,为mFirstView和mSecondView设置数据
mAdapter.setItem(mFirstView, mAdapter.getItem(0));
mAdapter.setItem(mSecondView, mAdapter.getItem(1));
// 将mFirstView和mSecondView添加到当前View
addView(mFirstView);
addView(mSecondView);
mPosition = 1;
isStarted = false;
}
setBackgroundDrawable(mFirstView.getBackground());
}为了实现子View之间的切换,需要把上面添加进来的子View的高度修改为与VerticalBannerView高度一致。这个操作在onMeasure()方法中完成。
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
// 成员变量mBannerHeight有一个默认值
if (LayoutParams.WRAP_CONTENT == getLayoutParams().height) {
// 如果当前View的高度设置为wrap_content,使用默认值
getLayoutParams().height = (int) mBannerHeight;
} else {
// 如果当前View设定了固定高度,则使用设定的高度
mBannerHeight = getHeight();
}
// 修改mFirstView和mSecondView的高度为其父视图的高度
if (mFirstView != null) {
mFirstView.getLayoutParams().height = (int) mBannerHeight;
}
if (mSecondView != null) {
mSecondView.getLayoutParams().height = (int) mBannerHeight;
}
}上面的准备工作完成后,就可以进入动画的执行了。VerticalBannerView通过调用start()方法启动切换动画。在start()方法中,调用postDelayed()执行AnimRunnable任务,在AnimRunnable的run()方法中,先调用performSwitch(),然后再次调用postDelayed()使AnimRunnable任务一直循环执行下去。两个子View之间的切换工作由performSwitch()负责执行。
public void start() {
if (mAdapter == null) {
throw new RuntimeException("you must call setAdapter() before start");
}
if (!isStarted && mAdapter.getCount() > 1) {
isStarted = true;
postDelayed(mRunnable, mGap);
}
}
private AnimRunnable mRunnable = new AnimRunnable();
private class AnimRunnable implements Runnable {
@Override
public void run() {
performSwitch();
// 调用postDelayed()延时再执行,一直循环下去
postDelayed(this, mGap);
}
}下面再进入performSwitch()方法,该方法是Item View之间产生切换效果的核心。
// 执行切换
private void performSwitch() {
// 动画在执行过程中,View的translationY属性从0一直减小到-mBannerHeight
// 因为translationY属性一直是负值,所以View向上移动
ObjectAnimator animator1 = ObjectAnimator.ofFloat(mFirstView, "translationY", -mBannerHeight);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(mSecondView, "translationY", -mBannerHeight);
AnimatorSet set = new AnimatorSet();
set.playTogether(animator1, animator2);
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
// 动画执行完成,把mFirstView和mSecondView的translationY恢复到默认状态
mFirstView.setTranslationY(0);
mSecondView.setTranslationY(0);
// 使用下一条数据,设置到第一个子View
View removedView = getChildAt(0);
mPosition++;
mAdapter.setItem(removedView, mAdapter.getItem(mPosition % mAdapter.getCount()));
// 移除第一个子View,此时当前LinearLayout的childCount==1
removeView(removedView);
// 移除的View,再添加到第2个位置
addView(removedView, 1);
}
});
set.setDuration(mAnimDuration);
set.start();
}关于使用VerticalBannerView怎么实现垂直轮播广告就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。