您好,登錄后才能下訂單哦!
怎么在Android中利用Viewpager實(shí)現(xiàn)一個(gè)無限循環(huán)輪播圖?很多新手對此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
在網(wǎng)上找了很多viewpager實(shí)現(xiàn)圖片輪播的,但是大多數(shù)通過以下方式在PagerAdapter的getCount()返回一個(gè)無限大的數(shù),來實(shí)現(xiàn) 偽無限
@Override public int getCount() { return Integer.MAX_VALUE;//返回一個(gè)無限大的值,可以 無限循環(huán) }
雖然通過這種方式是能達(dá)到效果,但是從嚴(yán)格意義上來說并不是真正的無限。
假如有五張輪播圖 item的編號為(0,1,2,3,4) 要想實(shí)現(xiàn) 無限循環(huán) 我們在這五張的頭部和尾部各加一張即(5+2)張,item編號為(0,1,2,3,4,5,6)其中編號為0,6的兩張不做展示只是為了做循環(huán)輪播的鋪墊,使得播放更加平滑。
1、當(dāng)我們從編號為5 右滑的時(shí)候到了編號6 這時(shí)候就將當(dāng)前頁面設(shè)置為1
2、當(dāng)我們從編號為1左滑的時(shí)候到了編號0 這時(shí)候就將當(dāng)前頁面設(shè)置為5
這么做之后就可以實(shí)現(xiàn)無限輪播 怎么保證從編號6跳轉(zhuǎn)編號1的時(shí)候不出現(xiàn)頁面停頓 突然跳到下一頁的現(xiàn)象呢?
public Object instantiateItem (ViewGroup container, int position)
在指定的位置創(chuàng)建頁面;適配器負(fù)責(zé)添加view到這個(gè)容器中,然而它只保證在finishUpdate(ViewGroup)返回時(shí)才完成。
public void destroyItem (ViewGroup container, int position, Object object)
刪除指定位置的頁面;適配器負(fù)責(zé)從view容器中刪除view,然而它只保證在finishUpdate(ViewGroup)返回時(shí)才完成。
所以說 重點(diǎn)就在于finishUpdate(ViewGroup)這個(gè)方法 其實(shí)無論是創(chuàng)建view添加到容器中 還是 銷毀view 都是在此方法結(jié)束之后執(zhí)行的
換句話說 就是 我在這個(gè)方法里讓頁面完成從 編號5跳轉(zhuǎn)到編號1 或者從編號1跳轉(zhuǎn)到編號5,此方法完成時(shí) 視圖還未完成創(chuàng)建或者 銷毀 這樣也就不會(huì)出現(xiàn) 頁面停頓 突然跳到下一頁的現(xiàn)象。
@Override public void finishUpdate(ViewGroup container) { super.finishUpdate(container); int position = viewPager.getCurrentItem(); if (position == 0) { position = simpleDraweeViewList.size() - 2; viewPager.setCurrentItem(position,false); } else if (position == simpleDraweeViewList.size() - 1) { position = 1; viewPager.setCurrentItem(position,false); } }
話不多說,上代碼:
布局文件:
<?xml version="1.0" encoding="utf-8"?> <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <FrameLayout android:id="@+id/frameLayout" android:layout_width="0dp" android:layout_height="200dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0.0" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"> <android.support.v4.view.ViewPager android:id="@+id/viewPager" android:layout_width="match_parent" android:layout_height="match_parent" tools:layout_editor_absoluteX="8dp" tools:layout_editor_absoluteY="0dp" /> <LinearLayout android:layout_width="match_parent" android:layout_height="35dip" android:layout_gravity="bottom" android:background="#33000000" android:gravity="center_vertical" android:orientation="horizontal" android:weightSum="10"> <TextView android:id="@+id/tv_pager_title" android:layout_width="0dp" android:layout_height="35dip" android:layout_weight="8" android:gravity="center_vertical" android:paddingLeft="8dip" android:text="加載圖片輪播失敗" android:textColor="@android:color/white" /> <LinearLayout android:id="@+id/lineLayout_dot" android:layout_width="0dp" android:layout_height="match_parent" android:layout_marginRight="5dp" android:layout_weight="2" android:gravity="center|right" android:orientation="horizontal" android:paddingLeft="3dp" android:paddingRight="3dp" /> </LinearLayout> </FrameLayout> </android.support.constraint.ConstraintLayout>
最主要的PagerAdapter:
import android.content.Context; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.View; import android.view.ViewGroup; import com.facebook.drawee.view.SimpleDraweeView; import java.util.List; public class ImagesPagerAdapter extends PagerAdapter { private List<SimpleDraweeView> simpleDraweeViewList; private ViewPager viewPager; private Context context; private SimpleDraweeView simpleDraweeView; public ImagesPagerAdapter(List<SimpleDraweeView> simpleDraweeViewList, ViewPager viewPager, Context context) { this.simpleDraweeViewList = simpleDraweeViewList; this.viewPager = viewPager; this.context = context; } @Override public int getCount() { return simpleDraweeViewList.size(); } //刪除指定位置的頁面;適配器負(fù)責(zé)從view容器中刪除view,然而它只保證在finishUpdate(ViewGroup)返回時(shí)才完成。 @Override public void destroyItem(ViewGroup container, int position, Object object) { // 把ImageView從ViewPager中移除掉 viewPager.removeView(simpleDraweeViewList.get(position)); //super.destroyItem(container, position, object); } //是否獲取緩存 @Override public boolean isViewFromObject(View view, Object object) { return view == object; } //實(shí)例化Item //在指定的位置創(chuàng)建頁面;適配器負(fù)責(zé)添加view到這個(gè)容器中,然而它只保證在finishUpdate(ViewGroup)返回時(shí)才完成。 @Override public Object instantiateItem(ViewGroup container, int position) { simpleDraweeView = simpleDraweeViewList.get(position); viewPager.addView(simpleDraweeView); return simpleDraweeView; } @Override public int getItemPosition(Object object) { return POSITION_NONE; } //無論是創(chuàng)建view添加到容器中 還是 銷毀view 都是在此方法結(jié)束之后執(zhí)行的 @Override public void finishUpdate(ViewGroup container) { super.finishUpdate(container); int position = viewPager.getCurrentItem(); if (position == 0) { position = simpleDraweeViewList.size() - 2; viewPager.setCurrentItem(position,false); } else if (position == simpleDraweeViewList.size() - 1) { position = 1; viewPager.setCurrentItem(position,false); } } /* private int mChildCount = 0; @Override public void notifyDataSetChanged() { mChildCount = getCount(); super.notifyDataSetChanged(); } @Override public int getItemPosition(Object object) { if (mChildCount > 0) { mChildCount--; Log.e("image","getItemPosition"); return POSITION_NONE; } return super.getItemPosition(object); }*/ }
import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.widget.LinearLayout; import android.widget.TextView; import com.facebook.drawee.view.SimpleDraweeView; import java.util.ArrayList; import java.util.List; public class ImageCarousel { private Context context; private ViewPager viewPager; private TextView tvTitle; private LinearLayout dotsRoot; private int time; private List<View> dots;//小點(diǎn) private int previousPosition = 1;//前一個(gè)被選中的position private List<SimpleDraweeView> simpleDraweeViewList; private String[] titles;//標(biāo)題數(shù)組 private ImagesPagerAdapter adapter; private AutoPlayThread autoPlayThread; private volatile boolean isExit = true; private static final int FIRST_PAGE = 1; public ImageCarousel(Context context, ViewPager viewPager, TextView tvTitle, List<View> dots, int time) { this.context = context; this.viewPager = viewPager; this.tvTitle = tvTitle; this.dots = dots; this.time = time; Log.e("image", "構(gòu)造方法"); } /** * 傳入數(shù)據(jù) * * @param simpleDraweeViewList SimpleDraweeView集合 * @param titles 標(biāo)題數(shù)組 * @return this 本身 */ public ImageCarousel init(List<SimpleDraweeView> simpleDraweeViewList, String[] titles) { this.simpleDraweeViewList = simpleDraweeViewList; this.titles = titles; Log.e("image", "init"); autoPlayThread = new AutoPlayThread(); return this; } /** * 重新加載,有待考驗(yàn)... * * @param simpleDraweeViewList SimpleDraweeView集合 * @param titles 標(biāo)題數(shù)組 */ public void reload(List<SimpleDraweeView> simpleDraweeViewList, String[] titles) { init(simpleDraweeViewList, titles); previousPosition = 0; start(); } /** * 設(shè)置設(shè)配器,并實(shí)現(xiàn)輪播功能 */ public void start() { if (adapter != null) { adapter = null; } adapter = new ImagesPagerAdapter(this.simpleDraweeViewList, viewPager, context); viewPager.setAdapter(adapter); viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() { @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { } //當(dāng)被選擇 @Override public void onPageSelected(int position) { int currentPosition = 1; if (position == simpleDraweeViewList.size() - 1) { // 設(shè)置當(dāng)前值為1 currentPosition = FIRST_PAGE; } else if (position == 0) { // 如果索引值為0了,就設(shè)置索引值為倒數(shù)第二個(gè) currentPosition = simpleDraweeViewList.size() - 2; } else { currentPosition = position; } // 把當(dāng)前選中的點(diǎn)給切換了, 還有描述信息也切換 tvTitle.setText(titles[currentPosition]);//圖片下面設(shè)置顯示文本 //設(shè)置輪播點(diǎn) 可設(shè)置成傳入的圖 Log.d("dots", "previousPosition=" + previousPosition + " currentPosition=" + currentPosition); dots.get(previousPosition-1).setBackgroundResource(R.drawable.ic_dot_focused); dots.get(currentPosition-1).setBackgroundResource(R.drawable.ic_dot_normal); // 把當(dāng)前的索引賦值給前一個(gè)索引變量, 方便下一次再切換. previousPosition = currentPosition; } @Override public void onPageScrollStateChanged(int state) { // SCROLL_STATE_IDLE :空閑狀態(tài) // SCROLL_STATE_DRAGGING :滑動(dòng)狀態(tài) // SCROLL_STATE_SETTLING :滑動(dòng)后滑翔的狀態(tài) if (state == ViewPager.SCROLL_STATE_DRAGGING) { } else if(state == ViewPager.SCROLL_STATE_IDLE){ } } }); setFirstLocation(); //autoPlayThread.start(); } /** * 設(shè)置剛打開app時(shí)顯示的圖片和文字 */ private void setFirstLocation() { tvTitle.setText(titles[0]); dots.get(0).setBackgroundResource(R.drawable.ic_dot_normal); viewPager.setCurrentItem(1); } /** * 設(shè)置是否輪播 * * @param b */ private void setAutoPlay(boolean b) { /*if (b && suspendRequested) { autoPlayThread.requestResume(); } else if (!b){ autoPlayThread.requestSuspend(); }*/ } public void stopAutoPlay() { if (autoPlayThread != null) { Log.e("thrad", "暫停"); isExit = true; autoPlayThread.interrupt(); autoPlayThread = null; } } /** * 請求繼續(xù) */ public void startAutoPlay() { Log.e("thrad", "開始"); isExit = false; autoPlayThread = null; autoPlayThread = new AutoPlayThread(); autoPlayThread.start(); } /** * 自動(dòng)播放線程,添加暫停和繼續(xù)方法 */ class AutoPlayThread extends Thread { @Override public synchronized void run() { while (!isExit) { try { Thread.sleep(time); } catch (InterruptedException e) { Log.e("thrad", "強(qiáng)制請求退出線程"); break; } ((Activity) context).runOnUiThread(new Runnable() { @Override public void run() { viewPager.setCurrentItem(viewPager.getCurrentItem() + 1); } }); if (this.interrupted()) { Log.e("thrad", "已經(jīng)是停止?fàn)顟B(tài)了,我要退出了"); break; } } } } }
mainActivity.java:
import android.app.Activity; import android.content.Context; import android.graphics.drawable.Drawable; import android.net.Uri; import android.support.v4.content.ContextCompat; import android.support.v4.view.ViewPager; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.view.ViewGroup; import android.widget.AbsListView; import android.widget.LinearLayout; import android.widget.TextView; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.backends.pipeline.PipelineDraweeController; import com.facebook.drawee.drawable.ScalingUtils; import com.facebook.drawee.generic.GenericDraweeHierarchy; import com.facebook.drawee.generic.GenericDraweeHierarchyBuilder; import com.facebook.drawee.view.SimpleDraweeView; import com.facebook.imagepipeline.common.ResizeOptions; import com.facebook.imagepipeline.request.ImageRequest; import com.facebook.imagepipeline.request.ImageRequestBuilder; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener { // 圖片輪播控件 private ViewPager mViewPager; private TextView mTvPagerTitle; private LinearLayout mLineLayoutDot; private ImageCarousel imageCarousel; private List<View> dots;//小點(diǎn) // 圖片數(shù)據(jù),包括圖片標(biāo)題、圖片鏈接、數(shù)據(jù)、點(diǎn)擊要打開的網(wǎng)站(點(diǎn)擊打開的網(wǎng)頁或一些提示指令) private List<ImageInfo> imageInfoList; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initEvent(); imageStart(); } @Override public void onClick(View v) { } /** * 初始化事件 * 左右多添加一張圖片 */ private void initEvent() { imageInfoList = new ArrayList<>(); imageInfoList.add(new ImageInfo(1, "圖片5,公告5啦啦啦啦", "", "http://e.hiphotos.baidu.com/image/h%3D300/sign=73443062281f95cab9f594b6f9177fc5/72f082025aafa40fafb5fbc1a664034f78f019be.jpg", "")); imageInfoList.add(new ImageInfo(2, "圖片1,公告1啦啦啦啦", "", "http://d.hiphotos.baidu.com/image/pic/item/6159252dd42a2834a75bb01156b5c9ea15cebf2f.jpg", "")); imageInfoList.add(new ImageInfo(3, "圖片2,公告2啦啦啦啦", "", "http://c.hiphotos.baidu.com/image/h%3D300/sign=cfce96dfa251f3dedcb2bf64a4eff0ec/4610b912c8fcc3ce912597269f45d688d43f2039.jpg", "")); imageInfoList.add(new ImageInfo(4, "圖片3,公告3啦啦啦啦", "", "http://e.hiphotos.baidu.com/image/pic/item/6a600c338744ebf85ed0ab2bd4f9d72a6059a705.jpg", "")); imageInfoList.add(new ImageInfo(5, "圖片4,公告4啦啦啦啦", "", "http://b.hiphotos.baidu.com/image/h%3D300/sign=8ad802f3801001e9513c120f880e7b06/a71ea8d3fd1f4134be1e4e64281f95cad1c85efa.jpg", "")); imageInfoList.add(new ImageInfo(6, "圖片5,公告5啦啦啦啦", "", "http://e.hiphotos.baidu.com/image/h%3D300/sign=73443062281f95cab9f594b6f9177fc5/72f082025aafa40fafb5fbc1a664034f78f019be.jpg", "")); imageInfoList.add(new ImageInfo(7, "圖片1,公告1啦啦啦啦", "", "http://d.hiphotos.baidu.com/image/pic/item/6159252dd42a2834a75bb01156b5c9ea15cebf2f.jpg", "")); } /** * 初始化控件 */ private void initView() { mViewPager = findViewById(R.id.viewPager); mTvPagerTitle = findViewById(R.id.tv_pager_title); mLineLayoutDot = findViewById(R.id.lineLayout_dot); } private void imageStart() { //設(shè)置圖片輪播 int[] imgaeIds = new int[]{R.id.pager_image1, R.id.pager_image2, R.id.pager_image3, R.id.pager_image4, R.id.pager_image5, R.id.pager_image6, R.id.pager_image7, R.id.pager_image8}; String[] titles = new String[imageInfoList.size()]; List<SimpleDraweeView> simpleDraweeViewList = new ArrayList<>(); for (int i = 0; i < imageInfoList.size(); i++) { titles[i] = imageInfoList.get(i).getTitle(); SimpleDraweeView simpleDraweeView = new SimpleDraweeView(this); simpleDraweeView.setAspectRatio(1.78f); // 設(shè)置一張默認(rèn)的圖片 GenericDraweeHierarchy hierarchy = new GenericDraweeHierarchyBuilder(this.getResources()) .setPlaceholderImage(ContextCompat.getDrawable(this, R.drawable.defult), ScalingUtils.ScaleType.CENTER_CROP).build(); simpleDraweeView.setHierarchy(hierarchy); simpleDraweeView.setLayoutParams(new AbsListView.LayoutParams(AbsListView.LayoutParams.MATCH_PARENT, AbsListView.LayoutParams.WRAP_CONTENT)); //加載高分辨率圖片; ImageRequest imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(imageInfoList.get(i).getImage())) .setResizeOptions(new ResizeOptions(1280, 720)) .build(); PipelineDraweeController controller = (PipelineDraweeController) Fresco.newDraweeControllerBuilder() //.setLowResImageRequest(ImageRequest.fromUri(Uri.parse(listItemBean.test_pic_low))) //在加載高分辨率圖片之前加載低分辨率圖片 .setImageRequest(imageRequest) .setOldController(simpleDraweeView.getController()) .build(); simpleDraweeView.setController(controller); simpleDraweeView.setId(imgaeIds[i]);//給view設(shè)置id simpleDraweeView.setTag(imageInfoList.get(i)); simpleDraweeView.setOnClickListener(this); titles[i] = imageInfoList.get(i).getTitle(); simpleDraweeViewList.add(simpleDraweeView); } dots = addDots(mLineLayoutDot, fromResToDrawable(this, R.drawable.ic_dot_focused), simpleDraweeViewList.size()); imageCarousel = new ImageCarousel(this, mViewPager, mTvPagerTitle, dots, 5000); imageCarousel.init(simpleDraweeViewList, titles) .startAutoPlay(); imageCarousel.start(); } /** * 動(dòng)態(tài)添加一個(gè)點(diǎn) * * @param linearLayout 添加到LinearLayout布局 * @param backgount 設(shè)置 * @return 小點(diǎn)的Id */ private int addDot(final LinearLayout linearLayout, Drawable backgount) { final View dot = new View(this); LinearLayout.LayoutParams dotParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); dotParams.width = 16; dotParams.height = 16; dotParams.setMargins(4, 0, 4, 0); dot.setLayoutParams(dotParams); dot.setBackground(backgount); dot.setId(View.generateViewId()); ((Activity) this).runOnUiThread(new Runnable() { @Override public void run() { linearLayout.addView(dot); } }); return dot.getId(); } /** * 資源圖片轉(zhuǎn)Drawable * * @param context 上下文 * @param resId 資源ID * @return 返回Drawable圖像 */ public static Drawable fromResToDrawable(Context context, int resId) { return ContextCompat.getDrawable(context, resId); } /** * 添加多個(gè)輪播小點(diǎn)到橫向線性布局 * * @param linearLayout 線性橫向布局 * @param backgount 小點(diǎn)資源圖標(biāo) * @param number 數(shù)量 * @return 返回小點(diǎn)View集合 */ private List<View> addDots(final LinearLayout linearLayout, Drawable backgount, int number) { List<View> dots = new ArrayList<>(); for (int i = 2; i < number; i++) { // 注意這里的 i 從 2 開始,只畫出5個(gè)點(diǎn) int dotId = addDot(linearLayout, backgount); dots.add(findViewById(dotId)); } return dots; } }
ic_dot_focused.xml:
<vector android:height="5dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="5dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#c8ffffff" android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/> </vector>
ic_dot_normal.xml:
<vector android:height="5dp" android:viewportHeight="24.0" android:viewportWidth="24.0" android:width="5dp" xmlns:android="http://schemas.android.com/apk/res/android"> <path android:fillColor="#c8fd8888" android:pathData="M12,12m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"/> </vector>
Android是一種基于Linux內(nèi)核的自由及開放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,由美國Google公司和開放手機(jī)聯(lián)盟領(lǐng)導(dǎo)及開發(fā)。
看完上述內(nèi)容是否對您有幫助呢?如果還想對相關(guān)知識有進(jìn)一步的了解或閱讀更多相關(guān)文章,請關(guān)注億速云行業(yè)資訊頻道,感謝您對億速云的支持。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。