版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Common_it/article/details/80706917
Android开发中,大部分APP都缺不了一个推广或者广告的一个Banner位置,今天就和大家利用ViewPage打造一个简单的Banner控件(前面是按照步骤的代码,后面有整体代码,所有资源文件也都在后面)
效果
自定义控件老规矩
继承FrameLayout,加载一个界面到我们的自定义控件中
public class CustomBanner extends FrameLayout {
private Context mContext;
//ViewPager
private ViewPager mViewPage;
//指针显示容器
private LinearLayout mLinearLayout;
//指针控件容器
private List<View> mPointView = new ArrayList<>();
//指针个数
private int pointSize = 0;
//轮播间隔(ms)
private final int DIV_TIME = 2000;
private Handler mHandler = new Handler();
private MRunnable mMRunnable;
//滑动方向
private boolean isPageOrientation = true;
public CustomBanner(Context context) {
this(context, null);
}
public CustomBanner(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomBanner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initView();
}
}
初始化加载的控件
/**
* 初始化加载UI
*/
private void initView() {
View view = LayoutInflater.from(mContext).inflate(R.layout.custom_item, this);
mViewPage = view.findViewById(R.id.cu_viewPage);
mLinearLayout = view.findViewById(R.id.cu_pointer);
mLinearLayout.setGravity(Gravity.CENTER);
mViewPage.addOnPageChangeListener(new MPageChangeListener());
}
ViewPage滑动监听
在这里处理指针的显示、和ViewPage的滑动方向
/**
* ViewPage滑动监听
*/
private class MPageChangeListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position == 0) {
isPageOrientation = true;
}
if (position == (pointSize - 1)) {
isPageOrientation = false;
}
//将所有指针置为默认状态
for (int i = 0; i < pointSize; i++) {
mPointView.get(i).setSelected(false);
}
//将当前界面对面的指针置为选中状态
mPointView.get(position).setSelected(true);
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
设置轮播界面的UI
这里需要把要轮播显示的界面传过来
/**
* 设置轮播UI
*
* @param data
*/
public void setImageData(List<View> data) {
pointSize = data.size();
if (data != null && pointSize > 0) {
MPageAdapter mMaxPageAdapter = new MPageAdapter(data);
mViewPage.setAdapter(mMaxPageAdapter);
initPoint();
}
}
适配器
适配器很简单,基本操作
/**
* ViewPage适配器
*/
private class MPageAdapter extends PagerAdapter {
private List<View> data;
public MPageAdapter(List<View> data) {
this.data = data;
}
@Override
public int getCount() {
return data != null ? data.size() : 0;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View mView = data.get(position);
container.addView(mView);
return mView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
开启轮播
这里也交给使用者自己来控制
/**
* 开启轮播
*/
public void start() {
if (mMRunnable == null) {
mMRunnable = new MRunnable();
}
mHandler.postDelayed(mMRunnable, DIV_TIME);
}
停止轮播
/**
* 停止轮播
*/
public void stop() {
if (mMRunnable != null) {
mHandler.removeCallbacks(mMRunnable);
}
}
定时任务
根据时间间隔切换界面
/**
* 定时任务
*/
private class MRunnable implements Runnable {
@Override
public void run() {
mHandler.postDelayed(mMRunnable, DIV_TIME);
int mCurrentItem = mViewPage.getCurrentItem();
if (isPageOrientation) {
mCurrentItem++;
} else {
mCurrentItem--;
}
mViewPage.setCurrentItem(mCurrentItem);
}
}
R.layout.custom_item 界面
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v4.view.ViewPager
android:id="@+id/cu_viewPage"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<LinearLayout
android:layout_marginBottom="10dp"
android:layout_alignParentBottom="true"
android:id="@+id/cu_pointer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" />
</RelativeLayout>
R.drawable.point_background
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/item_circle_def" android:state_selected="false"/>
<item android:drawable="@drawable/item_circle_sel" android:state_selected="true"/>
</selector>
item_circle_def和item_circle_sel
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2.5dp"/>
<solid android:color="#B3FFFFFF"/>
</shape>
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners android:radius="2.5dp"/>
<solid android:color="#FF0000"/>
</shape>
整体代码
public class CustomBanner extends FrameLayout {
private Context mContext;
//ViewPager
private ViewPager mViewPage;
//指针显示容器
private LinearLayout mLinearLayout;
//指针控件容器
private List<View> mPointView = new ArrayList<>();
//指针个数
private int pointSize = 0;
//轮播间隔(ms)
private final int DIV_TIME = 2000;
private Handler mHandler = new Handler();
private MRunnable mMRunnable;
//滑动方向
private boolean isPageOrientation = true;
public CustomBanner(Context context) {
this(context, null);
}
public CustomBanner(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public CustomBanner(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
mContext = context;
initView();
}
/**
* 初始化加载UI
*/
private void initView() {
View view = LayoutInflater.from(mContext).inflate(R.layout.custom_item, this);
mViewPage = view.findViewById(R.id.cu_viewPage);
mLinearLayout = view.findViewById(R.id.cu_pointer);
mLinearLayout.setGravity(Gravity.CENTER);
mViewPage.addOnPageChangeListener(new MPageChangeListener());
}
/**
* 设置轮播UI
*
* @param data
*/
public void setImageData(List<View> data) {
pointSize = data.size();
if (data != null && pointSize > 0) {
MPageAdapter mMaxPageAdapter = new MPageAdapter(data);
mViewPage.setAdapter(mMaxPageAdapter);
initPoint();
}
}
/**
* 开启轮播
*/
public void start() {
if (mMRunnable == null) {
mMRunnable = new MRunnable();
}
mHandler.postDelayed(mMRunnable, DIV_TIME);
}
/**
* 停止轮播
*/
public void stop() {
if (mMRunnable != null) {
mHandler.removeCallbacks(mMRunnable);
}
}
/**
* 初始化指针
*/
private void initPoint() {
for (int i = 0; i < pointSize; i++) {
View view = new View(mContext);
int viewSize = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 5, getResources().getDisplayMetrics());
LinearLayout.LayoutParams mLayoutParams = new LinearLayout.LayoutParams(viewSize, viewSize);
mLayoutParams.leftMargin = mLayoutParams.rightMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, getResources().getDisplayMetrics());
view.setLayoutParams(mLayoutParams);
view.setBackground(ContextCompat.getDrawable(mContext, R.drawable.point_background));
view.setSelected(false);
mLinearLayout.addView(view);
mPointView.add(view);
}
mPointView.get(0).setSelected(true);
}
/**
* ViewPage适配器
*/
private class MPageAdapter extends PagerAdapter {
private List<View> data;
public MPageAdapter(List<View> data) {
this.data = data;
}
@Override
public int getCount() {
return data != null ? data.size() : 0;
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
View mView = data.get(position);
container.addView(mView);
return mView;
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
}
}
/**
* ViewPage滑动监听
*/
private class MPageChangeListener implements ViewPager.OnPageChangeListener {
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
if (position == 0) {
isPageOrientation = true;
}
if (position == (pointSize - 1)) {
isPageOrientation = false;
}
//将所有指针置为默认状态
for (int i = 0; i < pointSize; i++) {
mPointView.get(i).setSelected(false);
}
//将当前界面对面的指针置为选中状态
mPointView.get(position).setSelected(true);
}
@Override
public void onPageScrollStateChanged(int state) {
}
}
/**
* 定时任务
*/
private class MRunnable implements Runnable {
@Override
public void run() {
mHandler.postDelayed(mMRunnable, DIV_TIME);
int mCurrentItem = mViewPage.getCurrentItem();
if (isPageOrientation) {
mCurrentItem++;
} else {
mCurrentItem--;
}
mViewPage.setCurrentItem(mCurrentItem);
}
}
}
实现思路
- 基础需要
ViewPage
实现滚动,下面加一个容器来放置指针 - 利用
Handler
的postDelayed
方法实现定时滚动的