ViewPager 循环播放广告导航
这段时间,做android首页时候,看见很多应用都有这个自动播放的广告导航效果,于是就网上找了很多例子来参考。不过,别人的并不一定试用于自己的情况,不过参考价值还是很大的。
首先明确做这个广告导航的一点就是需要用viewpager,这个控件非常简单粗暴,在android studio里或者eclipse里创建android项目时候,我们可以在创建activity时候,选择让平台给我们自动创建一个应用viewpager(Tabbed Activity)的页面,简单浏览一下,你就会发现这个控件实现起来还是很简单的。
下面我们先来看一下,平台为我们自动生成的代码
Java代码分析
//activtiy的代码
public class MainActivity extends AppCompatActivity {
private SectionsPagerAdapter mSectionsPagerAdapter;//声明viewpager适配器
private ViewPager mViewPager;//声明viewpager控件
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 创建一个适配器然后会返回三个fragment中的其中一个
mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());
// 获取viewpager控件
mViewPager = (ViewPager) findViewById(R.id.container);
mViewPager.setAdapter(mSectionsPagerAdapter);
}
/**
* 自动创建的fragment例子
* 这里自动生成会加在activity里面,我们完全可以copy出去建一个新的fragment,copy后将static删掉就行
*/
public static class PlaceholderFragment extends Fragment {
private static final String ARG_SECTION_NUMBER = "section_number";
public PlaceholderFragment() {
}
/**
* 这里利用newInstance方法返回一个新的fragment
*
*/
public static PlaceholderFragment newInstance(int sectionNumber) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle args = new Bundle();
args.putInt(ARG_SECTION_NUMBER, sectionNumber);
fragment.setArguments(args);
return fragment;
}
//fragment对应的布局控件操作在这里实现
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
TextView textView = (TextView) rootView.findViewById(R.id.section_label);
textView.setText(getString(R.string.section_format, getArguments().getInt(ARG_SECTION_NUMBER)));
return rootView;
}
}
/**
* 这里就是viewpager的适配器
* 我们也可以copy出去,建一个新的adpater的java文件
*/
public class SectionsPagerAdapter extends FragmentPagerAdapter {
public SectionsPagerAdapter(FragmentManager fm) {
super(fm);
}
@Override
public Fragment getItem(int position) {
// 返回相应的position对应得fragment
return PlaceholderFragment.newInstance(position + 1);
}
//总共3个fragment页面
@Override
public int getCount() {
return 3;
}
//这里是设置Tab标题,当然后面我们可以在activtiy里去设置这些标题
@Override
public CharSequence getPageTitle(int position) {
switch (position) {
case 0:
return "SECTION 1";
case 1:
return "SECTION 2";
case 2:
return "SECTION 3";
}
return null;
}
}
}
xml布局代码
在activity的xml布局里加入ViewPager这个布局控件就可以了
<android.support.v4.view.ViewPager
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
对应的fragment也有一个xml布局这里就不贴了
从上面的代码可以看出,我们使用viewpager,需要用到适配器和fragment,其实fragment并不是必须要用到的,这里我们实现循环广告就并没用用到fragment,我们可以直接new一个布局,往里添加imageview就行了,但是适配器是必须要用的,就像实现ListView一样必须需要Adapter(SimpleAdapter,BaseAdapter…)的绑定。
有了前面代码的参考,接下来,就跟着我一起来实现自动循环播放的广告导航页面。
废话不多说,我们上代码:
首先我们把xml布局文件写好
<FrameLayout
android:id="@+id/ad_fragmentlayout"
android:layout_width="match_parent"
android:layout_height="160dp"
android:background="@android:color/darker_gray">
<android.support.v4.view.ViewPager
android:id="@+id/ad_continer"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v4.view.ViewPager>
<!--这里是导航点的布局,用Imageview来显示导航点,需要几个就布几个,之前看的网上的例子都是动态生成导航点,有点麻烦,反正导航点就几个,如果要动态,完全可以在这里布好后,设置隐藏属性gone掉或者显示就行-->
<RelativeLayout
android:gravity="center"
android:orientation="horizontal"
android:layout_gravity="bottom"
android:layout_width="match_parent"
android:layout_height="40dp">
<ImageView
android:layout_marginRight="5dp"
android:id="@+id/guide1"
android:background="@color/colorPrimary"
android:layout_width="8dp"
android:layout_height="8dp" />
<ImageView
android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/guide1"
android:id="@+id/guide2"
android:background="@color/colorWhite"
android:layout_width="8dp"
android:layout_height="8dp" />
<ImageView
android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/guide2"
android:id="@+id/guide3"
android:background="@color/colorWhite"
android:layout_width="8dp"
android:layout_height="8dp" />
<ImageView
android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/guide3"
android:id="@+id/guide4"
android:background="@color/colorWhite"
android:layout_width="8dp"
android:layout_height="8dp" />
<ImageView
android:layout_marginRight="5dp"
android:layout_toRightOf="@+id/guide4"
android:id="@+id/guide5"
android:background="@color/colorWhite"
android:layout_width="8dp"
android:layout_height="8dp" />
</RelativeLayout>
</FrameLayout>
布局写好后,我们就来写java代码了,实现循环播放广告导航页面的话,我只需要写三个java文件,一个是activity的java文件,一个是viewpager适配器的java文件,还有一个是支持手动滑动时候的循环滑动的changelistener监听java文件。
先来看activity的java代码:
public class MainActivity extends AppCompatActivity {
private SwipeRefreshLayout refresh_layout;
private final static String TAG="MainActivity";
private Handler handler;
public boolean isStop = false;
public Thread mThread=null;
public ViewPager mViewPager;
private FrameLayout btn_lessonhuide5;
@Override
protected void onCreate(Bundle savedInstanceState) {
isStop = false;
List<View> pagerViews=inintviews();
mViewPager = (ViewPager)findViewById(R.id.continer);
SectionsPagerAdapter mSectionsPagerAdapter=new SectionsPagerAdapter(pagerViews);
mViewPager.setAdapter(mSectionsPagerAdapter);
// 这里实现自动播放,开启新线程,4秒一次更新guide
//这里需要注意线程必须实例化,不然activity(fragment里遇到,activity会不会存在这个问题未知)销毁时候,线程还在运行,重建activity)(fragment)后,线程又新建了会导致自动播放加快
if (mThread==null){
mThread = new Thread(new Runnable() {
@Override
public void run() {
while(!isStop){
SystemClock.sleep(4000);
runOnUiThread(new Runnable() {
@Override
public void run() {
if(mViewPager.getCurrentItem()<6){
mViewPager.setCurrentItem(mViewPager.getCurrentItem()+1);
Log.e(TAG, "run: "+String.valueOf(mViewPager.getCurrentItem()));
}else if(mViewPager.getCurrentItem()==6){
mViewPager.setCurrentItem(1,false);
}
}
});
}
}
});
mThread.start();
}
//这里实现手动滑动时候的循环切换
mViewPager.addOnPageChangeListener(new PagerChangeListener(this,mViewPager));
}
//这里我们new几个imageview然后放入List<>中
public List<View> inintviews(){
List<View> pagerViews=new ArrayList<View>();
ImageView imageview0=new ImageView(this);
imageview0.setBackgroundResource(R.mipmap.viewguide5);//为了实现循环,我们在list中放的第一张图片其实是我们显示的第5张图片
pagerViews.add(imageview0);
ImageView imageview=new ImageView(this);
imageview.setBackgroundResource(R.mipmap.viewguide1);
pagerViews.add(imageview);
ImageView imageview2=new ImageView(this);
imageview2.setBackgroundResource(R.mipmap.viewguide2);
pagerViews.add(imageview2);
ImageView imageview3=new ImageView(this);
imageview3.setBackgroundResource(R.mipmap.viewguide3);
pagerViews.add(imageview3);
ImageView imageview4=new ImageView(this);
imageview4.setBackgroundResource(R.mipmap.viewguide4);
pagerViews.add(imageview4);
ImageView imageview5=new ImageView(this);
imageview5.setBackgroundResource(R.mipmap.viewguide5);
pagerViews.add(imageview5);
ImageView imageview6=new ImageView(this);
imageview6.setBackgroundResource(R.mipmap.viewguide1);
//为了循环显示,这里的第6张图片是我们要在广告页面里显示的第一张
pagerViews.add(imageview6);
//这里多放一个第六张图片,防止自动切换时,图片变灰
pagerViews.add(imageview6);
//所以5张循环广告页面总共需要list里放7张图片
/**
*对应关系是这样的
*其实我们要显示的是 1,2,3,4,5张图片
*但是实际为了循环我们放的0,1,2,3,4,5,6,7张图片
*第0张其实是我们显示的第5张,6,7张是我们显示的第一张
*
*/
return pagerViews;
}
}
下来是适配器代码
//适配器必须实现3个方法isViewFromObject,instantiateItem,destroyItem
public class SectionsPagerAdapter extends PagerAdapter {
private List<View> mList;
private View mView;
@Override//具体作用,我也不是很清楚,后面理解后会补上
public boolean isViewFromObject(View view, Object object) {
return view==object;
}
@Override//总共图片数
public int getCount() {
return mList.size();
}
//在这里我们传入List<>里的图片列表
public SectionsPagerAdapter (List<View> list) {
super();
this.mList=list;
}
@Override//这里加载图片
public Object instantiateItem(ViewGroup container, int position) {
if (position<mList.size()-1){
(container).addView(mList.get(position),0);
return mList.get(position);
}
return null;
}
@Override//这里销毁图片
public void destroyItem(ViewGroup container, int position, Object object) {
if(position<mList.size()-1){
(container).removeView(mList.get(position));
}
}
@Override
public CharSequence getPageTitle(int position) {
Log.e("getPageTitle",String.valueOf(position));
return " ";
}
}
//第三个 监听滑动页面切换java文件
public class PagerChangeListener implements ViewPager.OnPageChangeListener{
private final static String TAG="PagerChangeListener";
boolean isScrolled = false;
private ViewPager mViewPager;
private Context mContext;
public PagerChangeListener(Context context, ViewPager viewPager){
super();
this.mViewPager=viewPager;
this.mContext=context;
mViewPager.setCurrentItem(1);
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
}
@Override
public void onPageSelected(int position) {
Log.e(TAG, "onPageSelected: "+String.valueOf(position));
ImageView image1=(ImageView)mContext.findViewById(R.id.guide1);
ImageView image2=(ImageView)mContext.findViewById(R.id.guide2);
ImageView image3=(ImageView)mContext.findViewById(R.id.guide3);
ImageView image4=(ImageView)mContext.findViewById(R.id.guide4);
ImageView image5=(ImageView)mContext.findViewById(R.id.guide5);
//这里设置对应的导航点的颜色显示
switch (position){
case 0:
image1.setBackgroundResource(R.color.colorWhite);
image2.setBackgroundResource(R.color.colorWhite);
image3.setBackgroundResource(R.color.colorWhite);
image4.setBackgroundResource(R.color.colorWhite);
image5.setBackgroundResource(R.color.colorPrimary);
break;
case 1:
image1.setBackgroundResource(R.color.colorPrimary);
image2.setBackgroundResource(R.color.colorWhite);
image3.setBackgroundResource(R.color.colorWhite);
image4.setBackgroundResource(R.color.colorWhite);
image5.setBackgroundResource(R.color.colorWhite);
break;
case 2:
image1.setBackgroundResource(R.color.colorWhite);
image2.setBackgroundResource(R.color.colorPrimary);
image3.setBackgroundResource(R.color.colorWhite);
image4.setBackgroundResource(R.color.colorWhite);
image5.setBackgroundResource(R.color.colorWhite);
break;
case 3:
image1.setBackgroundResource(R.color.colorWhite);
image2.setBackgroundResource(R.color.colorWhite);
image3.setBackgroundResource(R.color.colorPrimary);
image4.setBackgroundResource(R.color.colorWhite);
image5.setBackgroundResource(R.color.colorWhite);
break;
case 4:
image1.setBackgroundResource(R.color.colorWhite);
image2.setBackgroundResource(R.color.colorWhite);
image3.setBackgroundResource(R.color.colorWhite);
image4.setBackgroundResource(R.color.colorPrimary);
image5.setBackgroundResource(R.color.colorWhite);
break;
case 5:
image1.setBackgroundResource(R.color.colorWhite);
image2.setBackgroundResource(R.color.colorWhite);
image3.setBackgroundResource(R.color.colorWhite);
image4.setBackgroundResource(R.color.colorWhite);
image5.setBackgroundResource(R.color.colorPrimary);
break;
case 6:
image1.setBackgroundResource(R.color.colorPrimary);
image2.setBackgroundResource(R.color.colorWhite);
image3.setBackgroundResource(R.color.colorWhite);
image4.setBackgroundResource(R.color.colorWhite);
image5.setBackgroundResource(R.color.colorWhite);
break;
default:
break;
}
}
//这里实现手势滑动循环,看懂了这里,你就能明白是如何实现循环的
@Override
public void onPageScrollStateChanged(int state) {
switch (state) {
case 1:// 手势滑动
isScrolled = false;
break;
case 2:// 界面切换
isScrolled = true;
break;
case 0:// 滑动结束
if (mViewPager.getCurrentItem() == 0) { //首位之前,跳转到末尾(N)
mViewPager.setCurrentItem(5, false);
} else if (mViewPager.getCurrentItem() == 6) { //末位之后,跳转到首位(1)
mViewPager.setCurrentItem(1, false); //false:不显示跳转过程的动画
}
break;
}
}
}
相信做完这几步后,我们的自动循环播放导航页面就完成了,总结一下,这里我们自动播放,是开启了一个线程,一直循环不停的让viewpager换页面实现的,对应得用的viewpager.setCurrentItem()方法,而页面的无限循环则是利用页面多张填充后,当页面滑到0张(此时显示的第5张图片)时,我们用viewpager.setCurrentItem()方法将当前页码改为第5张,当页面滑到6张(此时显示的第1张图片)时,我们用viewpager.setCurrentItem()方法将当前页码改为第1张。viewpager需要pageradpater绑定实现,具体的过程就是这样了
有什么问题欢迎留言,如果有地方不对,欢迎指出,毕竟我还是android小菜鸟。
by Lake
2016-4-20