国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

APP實用開發——廣告輪播圖

2019-11-09 16:37:18
字體:
來源:轉載
供稿:網友

這里寫圖片描述

ViewPager是一個常用的android組件,不過通常我們使用ViewPager的時候不能實現左右無限循環滑動,在滑到邊界的時候會看到一個不能翻頁的動畫,可能影響用戶體驗。此外,某些區域性的ViewPager(例如展示廣告或者公告之類的ViewPager),可能需要自動輪播的效果,即用戶在不用滑動的情況下就能夠看到其他頁面的信息。

循環滑動效果的實現:PagerAdapter 我們知道ViewPager自帶的滑動效果非常出色,因此我們基本不需要處理這個滑動,只處理內容的顯示。而內容的顯示是由Adapter控制的,因此這里重點就是這個Adapter了。為簡單起見,本例的每個View直接是一張圖片。下面是Adapter的代碼:

PRivate class ImageAdapter extends PagerAdapter{ private ArrayList<ImageView> viewlist; public ImageAdapter(ArrayList<ImageView> viewlist) { this.viewlist = viewlist; } @Override public int getCount() { //設置成最大,使用戶看不到邊界 return Integer.MAX_VALUE; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0==arg1; } @Override public void destroyItem(ViewGroup container, int position, Object object) { //Warning:不要在這里調用removeView } @Override public Object instantiateItem(ViewGroup container, int position) { //對ViewPager頁號求模取出View列表中要顯示的項 position %= viewlist.size(); if (position<0){ position = viewlist.size()+position; } ImageView view = viewlist.get(position); //如果View已經在之前添加到了一個父組件,則必須先remove,否則會拋出IllegalStateException。 ViewParent vp =view.getParent(); if (vp!=null){ ViewGroup parent = (ViewGroup)vp; parent.removeView(view); } container.addView(view); //add listeners here if necessary return view; } }

這里有幾個地方需要注意:

getCount() 方法的返回值:這個值直接關系到ViewPager的“邊界”,因此當我們把它設置為Integer.MAX_VALUE之后,用戶基本就看不到這個邊界了(估計滑到這里的時候電池已經掛了吧o_O)。當然,通常情況下設置為100倍實際內容個數也是可以的,之前看的某個實現就是這么干的。

instantiateItem() 方法position的處理:由于我們設置了count為 Integer.MAX_VALUE,因此這個position的取值范圍很大很大,但我們實際要顯示的內容肯定沒這么多(往往只有幾項),所以這里肯定會有求模操作。但是,簡單的求模會出現問題:考慮用戶向左滑的情形,則position可能會出現負值。所以我們需要對負值再處理一次,使其落在正確的區間內。

destroyItem() 方法:由于我們在instantiateItem()方法中已經處理了remove的邏輯,因此這里并不需要處理。實際上,實驗表明這里如果加上了remove的調用,則會出現ViewPager的內容為空的情況。

輪播效果的實現:使用Handler進行更新

這里我定義了一個Handler來處理ViewPager的輪播。所謂的“輪播”效果實現起來是這樣的:每隔一定時間(這里是3秒)切換一次顯示的頁面。通過控制各頁面以一定順序循環播放,就達到了輪播的效果。為此,我們可以使用Handler的sendEmptyMessageDelayed()方法來實現定時更新,并 注意用戶也可能會對帶有輪播效果的ViewPager手動進行滑動操作,因此我認為用戶這時候是希望查看指定頁面的,這時候應該取消輪播。下面是這個Handler的實現:

案例1

這里寫圖片描述

一、ViewPager填充圖片 1.1 布局中申明 由于是顯示廣告條,所以高度要固定住

<android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="120dp"/>

1.2 代碼中設置頁面數據 準備顯示圖片控件的集合

// 準備顯示的圖片集合 mList = new ArrayList<>(); for (int i = 0; i < mImages.length; i++) { ImageView imageView = new ImageView(this); // 將圖片設置到ImageView控件上 imageView.setImageResource(mImages[i]); // 將ImageView控件添加到集合 mList.add(imageView); }

自定義類書寫適配器

@Override public Object instantiateItem(ViewGroup container, int position) { // return super.instantiateItem(container, position); // 將圖片控件添加到容器 container.addView(mList.get(position)); // 返回 return mList.get(position); }

二、底部小圓點顯示邏輯 原理分析:底部的小圓點時浮動在ViewPager上面的的,所以應該是一個RelativeLayout布局。 ViewPager頁面切換時小圓點的顏色不一樣,所以需要對小圓點做選擇器,并且對ViewPager進行監聽。

2.1 布局申明

需要用一個RelativeLayout將ViewPager和包裹圓點的LinearLayout包裹起來

<RelativeLayout android:layout_width="match_parent" android:layout_height="120dp"> <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="120dp"/> <LinearLayout android:id="@+id/pointgroup" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="3dp" android:orientation="horizontal"> </LinearLayout> </RelativeLayout>

2.2 制作小圓點顏色選擇器

選擇器的選中狀態應該設置為selected,因為對ViewPager監聽時可以設置selected的屬性

<selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:drawable="@drawable/shape_point_normal" android:state_selected="false"/> <item android:drawable="@drawable/shape_point_selected" android:state_selected="true"/> </selector> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#66000000"/> </shape <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#FFFFFF"/> </shape>

2.3 將小圓點添加到LinearLayout容器

小圓點其實就是一個ImageView,所以在做出ViewPager的頁面圖片時,一起把小圓點也做了 初始化ImageView添加到LinearLayout之前,需要設置小圓點的布局參數,包括位置和大小

LinearLayout pointGroup = (LinearLayout) findViewById(R.id.pointgroup); for (int i = 0; i < mImages.length; i++) { // 制作底部小圓點 ImageView pointImage = new ImageView(this); pointImage.setImageResource(R.drawable.shape_point_selector); // 設置小圓點的布局參數 int PointSize = getResources().getDimensionPixelSize(R.dimen.point_size); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(PointSize, PointSize); if (i > 0) { params.leftMargin = getResources().getDimensionPixelSize(R.dimen.point_margin); pointImage.setSelected(false); } else { pointImage.setSelected(true); } pointImage.setLayoutParams(params); // 添加到容器里 pointGroup.addView(pointImage); }

三、小圓點隨著ViewPager切換移動

其實就是對ViewPager設置滑動監聽,當滑動到每一頁時就設置小圓點為選中狀態,這樣小圓點就顯示白色,其他頁面就設置為未選中狀態顯示灰色。

// 對ViewPager設置滑動監聽 viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } int lastPosition; @Override public void onPageSelected(int position) { // 頁面被選中 // 設置當前頁面選中 pointGroup.getChildAt(position).setSelected(true); // 設置前一頁不選中 pointGroup.getChildAt(lastPosition).setSelected(false); // 替換位置 lastPosition = position; } @Override public void onPageScrollStateChanged(int state) { } });

經過前面的三步設置后就能顯示一個簡單的廣告條了,這里再對其添加一個滑動到最后一頁后再滑還能滑動到首頁的功能。 四、無限滑動的ViewPager 實現原理: ViewPager之所以滑動到左右能顯示頁面,其實是因為左右都存在即將要顯示的頁面。當左右有很多頁面時我們就能一直滑動,沒有時就不能滑動。所以原理就是讓ViewPager的左右都有很多的頁面。 4.1 修改getCount方法

ViewPager能顯示多少個頁面全由getCount方法說了算,所以我們首先要改造它。

@Override public int getCount() { // 返回整數的最大值 return Integer.MAX_VALUE; }

4.2 修改instantiateItem方法

因為position變了,所以顯示的位置也變了,這里需要進行取%運算,來還原position。

// 修改position position = position % mList.size();

4.3 修改ViewPager監聽器里的onPageSelected

用到了position就要修改。

position = position % mList.size();

修改之后,ViewPager當前頁的右邊就有了無數的頁面,但是因為%了mList.size(),就只會顯示mList.size()的大小,這樣就實現了無限滑動輪播 五、無限自動輪播的廣告圖 實現原理:在前面四步的基礎上,在代碼里添加一個Handler,不斷的給自己發消息就好了。

mHandler.postDelayed(new Runnable() { @Override public void run() { int currentPosition = viewPager.getCurrentItem(); if(currentPosition == viewPager.getAdapter().getCount() - 1){ // 最后一頁 viewPager.setCurrentItem(0); }else{ viewPager.setCurrentItem(currentPosition + 1); } // 一直給自己發消息 mHandler.postDelayed(this,5000); } },5000);

案例2

這里寫圖片描述

1.設置VIewPager的adapter private void showMsg(NewBean newBean) { //1.ViewPager的數據 if (newBean.data.topnews.size() > 0) { .... //1.2.通過viewpager展示數據 if (myadapter == null) { myadapter = new Myadapter(); mViewPager.setAdapter(myadapter); }else{ myadapter.notifyDataSetChanged(); } } //2.ListView的數據 }2.adapter的操作 @Override public Object instantiateItem(ViewGroup container, int position) { View rootView = View.inflate(activity, R.layout.menunewsceteritem_viewpager_item, null); ImageView mIcon = (ImageView) rootView.findViewById(R.id.item_iv_icon); //因為圖片是在服務器中,不在本地,所以需要從服務器獲取圖片,展示在imageView //通過圖片的路徑請求服務器中的圖片,存放到相應的imageView中 Glide.with(activity.getapplicationContext()).load(imagerUrls.get(position)).into(mIcon); //將圖片所在的布局添加到ViewPager中展示 container.addView(rootView); return rootView; }

ViewPager的界面點和文本的初始化操作

private void showMsg(NewBean newBean) { //1.ViewPager的數據 if (newBean.data.topnews.size() > 0) { ... //1.3.將viewpager和點的indicator關聯 mIndicator.setViewPager(mViewPager); mIndicator.setSnap(true);//快照,使用快照的方式顯示點 //1.4.設置默認顯示第一張圖片,第一個文本,第一個點 mTitle.setText(titles.get(0)); mIndicator.onPageSelected(0); mViewPager.setCurrentItem(0);//設置viewpager當前顯示的界面,item:條目的索引 } //2.ListView的數據}

填充listview的數據將ViewPager的布局作為listView的頭條目展示

1.將ViewPager的布局作為listview的頭條目展示 private void showMsg(NewBean newBean) { //1.ViewPager的數據 if (newBean.data.topnews.size() > 0) { .... //1.5.將ViewPager所在的布局,添加到listView中 //獲取listview的頭條目的個數 if (mListView.getHeaderViewsCount()<1) { mListView.addHeaderView(mViewPagerView);//給listview添加頭條目 } } //2.ListView的數據 }2.填充listview數據 private void showMsg(NewBean newBean) { ..... //2.ListView的數據 if (newBean.data.news.size() > 0) { mNews = newBean.data.news; //設置listview的adapter展示數據 if (listViewAdapter == null) { listViewAdapter = new MyListViewAdapter(); mListView.setAdapter(listViewAdapter); }else{ listViewAdapter.notifyDataSetChanged(); } } }

ViewPager自動滑動操作

核心理念:每個一段時間,viewpager切換到下一個界面1.通過handler設置viewpager的自動滑動操作 //因為showMsg方法實在processjson方法中調用的,而processJson是在緩存和獲取最新數據的時候都會調用,最終會造成發送兩個延遲消息,但是只需要一個延遲消息就可以了 if (handler == null) { handler = new Handler(){ public void handleMessage(android.os.Message msg) { //viewpager切換下一個界面的操作 //首先需要知道當前顯示的界面 int currentItem = mViewPager.getCurrentItem();//獲取當前顯示界面的索引 //然后計算下一個界面的索引 //判斷是否切換到最后一個界面,如果是最后一個界面了,切換回第一個界面 if (currentItem == imagerUrls.size()-1) { currentItem=0; }else{ currentItem++; } //設置viewpager顯示下一個界面 mViewPager.setCurrentItem(currentItem); //切換一次完成,還要緊接著切換第二次 handler.sendEmptyMessageDelayed(0, 3000); }; }; handler.sendEmptyMessageDelayed(0, 3000);//只有執行此方法,才會發送延遲消息,不執行就不發送 }2.設置viewpager的界面切換監聽,實現切換界面顯示界面對應的文本 //監聽viewpager的界面切換,實現切換一個界面顯示一個界面對應的文本 mViewPager.addOnPageChangeListener(new OnPageChangeListener() { @Override public void onPageSelected(int position) { mTitle.setText(titles.get(position)); } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // TODO Auto-generated method stub } @Override public void onPageScrollStateChanged(int state) { // TODO Auto-generated method stub } });

viewpager的手動滑動

當滑動到小viewpager的最后一個界面的時候,外面的viewpager要將小的viewpager的觸摸事件攔截,當滑動小的viewpager的不是最后一個界面的時候,外面的viewpager不攔截小viewpager的觸摸事件讓小viewpager進行滑動操作創建自定義Viewpager進行操作//事件分發的@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) { //請求父控件不要攔截事件,true:不攔截,false:攔截 //getParent().requestDisallowInterceptTouchEvent(disallowIntercept); //1.需要判斷是左右滑動還是上下滑動,因為只有左右才是viewpager手動滑動的操作 switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //getParent().requestDisallowInterceptTouchEvent(false); //獲取按下的x和y的坐標 downX = (int) ev.getX(); downY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: //獲取移動的x和y的坐標 int moveX = (int) ev.getX(); int moveY = (int) ev.getY(); //判斷是上下還是左右滑動 if (Math.abs(moveX-downX) > Math.abs(moveY-downY)) { //左右 //從右往左,如果是最后一個條目,父控件攔截事件,實現切換界面的操作,如果不是最后一個條目,切換下一張圖片 //getAdapter() : 獲取ViewPager設置的adapter if (downX - moveX > 0 && getCurrentItem() == getAdapter().getCount()-1) { getParent().requestDisallowInterceptTouchEvent(false); }else if(downX - moveX > 0 && getCurrentItem() < getAdapter().getCount()-1){ getParent().requestDisallowInterceptTouchEvent(true); } //從左往右,如果是第一個條目,父控件攔截事件,打開側拉菜單,如果不是第一個條目,切換到上一張圖片 else if(downX - moveX < 0 && getCurrentItem() == 0){ getParent().requestDisallowInterceptTouchEvent(false); }else if(downX - moveX < 0 && getCurrentItem() > 0){ getParent().requestDisallowInterceptTouchEvent(true); } }else{ //上下 getParent().requestDisallowInterceptTouchEvent(false); } break; case MotionEvent.ACTION_UP: break; } return super.dispatchTouchEvent(ev);}

ViewPager和View的事件響應規則

如果是緩慢的移動很短的距離,viewpager和view的事件都會執行如果是快速滑動很長的距離,view的事件會執行cancel事件,結束view的觸摸操作,只去viewpager的事件具體操作 //設置view的觸摸事件事件,實現按下viewpager停止自動滑動,抬起,viewpager重新進行自動滑動操作 rootView.setOnTouchListener(new OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: //按下viewpager停止滑動 handler.removeCallbacksAndMessages(null);//取消handler發送延遲消息,如果是null,全部handler都會被取消發送消息 break; case MotionEvent.ACTION_UP: //抬起viewpager重新滑動 handler.sendEmptyMessageDelayed(0, 3000); break; case MotionEvent.ACTION_CANCEL: //view的事件取消執行的操作 handler.sendEmptyMessageDelayed(0, 3000); break; } //如果想要事件執行,返回true,返回事件不執行 return true; } });

自定義RoolViewPager

public class RoolViewPager extends ViewPager { private int downX; private int downY; public RoolViewPager(Context context, AttributeSet attrs) { super(context, attrs); // TODO Auto-generated constructor stub } public RoolViewPager(Context context) { super(context); // TODO Auto-generated constructor stub } //事件分發的 @Override public boolean dispatchTouchEvent(MotionEvent ev) { //請求父控件不要攔截事件,true:不攔截,false:攔截 //getParent().requestDisallowInterceptTouchEvent(disallowIntercept); //1.需要判斷是左右滑動還是上下滑動,因為只有左右才是viewpager手動滑動的操作 switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: //getParent().requestDisallowInterceptTouchEvent(false); //獲取按下的x和y的坐標 downX = (int) ev.getX(); downY = (int) ev.getY(); break; case MotionEvent.ACTION_MOVE: //獲取移動的x和y的坐標 int moveX = (int) ev.getX(); int moveY = (int) ev.getY(); //判斷是上下還是左右滑動 if (Math.abs(moveX-downX) > Math.abs(moveY-downY)) { //左右 //從右往左,如果是最后一個條目,父控件攔截事件,實現切換界面的操作,如果不是最后一個條目,切換下一張圖片 //getAdapter() : 獲取ViewPager設置的adapter if (downX - moveX > 0 && getCurrentItem() == getAdapter().getCount()-1) { getParent().requestDisallowInterceptTouchEvent(false); }else if(downX - moveX > 0 && getCurrentItem() < getAdapter().getCount()-1){ getParent().requestDisallowInterceptTouchEvent(true); } //從左往右,如果是第一個條目,父控件攔截事件,打開側拉菜單,如果不是第一個條目,切換到上一張圖片 else if(downX - moveX < 0 && getCurrentItem() == 0){ getParent().requestDisallowInterceptTouchEvent(false); }else if(downX - moveX < 0 && getCurrentItem() > 0){ getParent().requestDisallowInterceptTouchEvent(true); } }else{ //上下 getParent().requestDisallowInterceptTouchEvent(false); } break; case MotionEvent.ACTION_UP: break; } return super.dispatchTouchEvent(ev); }}

xml使用

布局文件中使用<com.itheima.zhbj97.ui.RoolViewPager android:id="@+id/menunewscenteritem_vp_viewpager" android:layout_width="match_parent" android:layout_height="185dp" ></com.itheima.zhbj97.ui.RoolViewPager>
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 公主岭市| 遂宁市| 株洲县| 纳雍县| 武清区| 介休市| 石林| 花莲市| 延庆县| 罗江县| 五台县| 英超| 井陉县| 昌图县| 天柱县| 凉城县| 广饶县| 松滋市| 柘城县| 太原市| 敦煌市| 额尔古纳市| 阿图什市| 丹寨县| 岳阳县| 漳州市| 石楼县| 绥滨县| 金华市| 桃源县| 绥德县| 镇赉县| 景谷| 克拉玛依市| 新野县| 民县| 耿马| 保康县| 贺州市| 辽源市| 武鸣县|