編輯:關於Android編程
無限自動循環 = 無限循環 + 自動循環 無限循環 = 無限向左循環 + 無限向右循環
接下來我們通過demo一步步的實現無限向右循環–>無限向左循環–>自動循環
Demo中viewpager中放有5張圖片,我們可以向左向右滑動,但是
若當前頁是第一頁,則無法再向右滑動。
若當前頁是最後一頁,則無法再向左滑動。
一般情況:沒有循環,需手滑
activity_main.xml
MainActivity.java
public class MainActivity extends Activity {
protected static final String tag = "MainActivity";
private ViewPager viewpager;
private List imageList = new ArrayList();
private Context context;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
initData();
viewpager = (ViewPager) findViewById(R.id.viewpager);
viewpager.setAdapter(new MyAdapter());
}
private void initData() {
imageList.clear();
ImageView iva = new ImageView(context);
iva.setBackgroundResource(R.drawable.a);
ImageView ivb = new ImageView(context);
ivb.setBackgroundResource(R.drawable.b);
ImageView ivc = new ImageView(context);
ivc.setBackgroundResource(R.drawable.c);
ImageView ivd = new ImageView(context);
ivd.setBackgroundResource(R.drawable.d);
ImageView ive = new ImageView(context);
ive.setBackgroundResource(R.drawable.e);
imageList.add(iva);
imageList.add(ivb);
imageList.add(ivc);
imageList.add(ivd);
imageList.add(ive);
}
public class MyAdapter extends PagerAdapter{
//表示viewpager共存放了多少個頁面
@Override
public int getCount() {
return imageList.size();
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(imageList.get(position));
return imageList.get(position);
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
}
}
添加無限向左循環
可以無限次的向左滑動,需要對PagerAdapter的2個方法進行修改
return Integer.MAX_VALUE:viewpager裡面有幾乎無窮多個object
imageList.get(position % imageList.size());防止角標越界
//表示viewpager共存放了多少個頁面
@Override
public int getCount() {
return Integer.MAX_VALUE;//我們設置viewpager中有Integer.MAX_VALUE個頁面
}
/**
* position % imageList.size() 而不是position,是為了防止角標越界異常
* 因為我們設置了viewpager子頁面的數量有Integer.MAX_VALUE,而imageList的數量只是5。
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(imageList.get(position % imageList.size()));
return imageList.get(position % imageList.size());
}
但是這樣暴露一個缺點,就是可以向左滑動,但是當前頁是第一頁的時候,無法向右滑動,因為第一頁的position是0。
解決方法:
給viewpager設置當前頁是第1000頁,這樣當前頁的左邊還有999頁,右邊還有Integer.MAX_VALUE - 1000頁,
無論是999,還是(Integer.MAX_VALUE - 1000),一般情況下是滑不到第一頁或最後一頁的。
當然1000是自己設置的,也可以設置多加幾個0。
添加無限向右循環
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
initData();
viewpager = (ViewPager) findViewById(R.id.viewpager);
viewpager.setAdapter(new MyAdapter());
viewpager.setCurrentItem(1000);//當前頁是第1000頁
}
添加自動循環
上面只是實現了無限循環,但還是用手動的,我們需要它每個一段時間(2秒)滑動一次。這就需要用到handler
int msgWhat = 0;
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);//收到消息,指向下一個頁面
handler.sendEmptyMessageDelayed(msgWhat, 2000);//2S後在發送一條消息,由於在handleMessage()方法中,造成死循環。
Log.d(tag, "handleMessage");
};
};
同時在onCreat()方法中發送消息:handler.sendEmptyMessageDelayed(msgWhat, 2000);
出現的bug
Bug1:內存洩露
Bug:雖然我們實現了 無限自動循環功能,但當我們由MainActivity調轉到SecondActivity的時候,通過Log.d(tag, “handleMessage”);發現handler還在發送消息,這就是內存洩露,所以我們需要在ManiActivity不可見不可交互的時候移除message。
解決方法:在onStop()裡移除message
/**
* 當MainActivity不可見的時候讓handler停止發送消息
* 防止內存洩露
*/
@Override
protected void onStop() {
super.onStop();
handler.removeMessages(msgWhat);
}
Bug2:再次回到 當前頁,viewpager不再自動循環
由於我們把handler.sendEmptyMessageDelayed(msgWhat, 2000);寫在了onCreate(),當我們由MainActivity調轉到SecondActivity的時候,在回來MainActivity的時候,MainActivity並沒有被銷毀,onCreate()方法並不會再執行。
解決方法:寫在onResume()裡面
/**
* activity可見可交互的時候就開始發送消息,開啟循環
*/
@Override
protected void onResume() {
super.onResume();
handler.sendEmptyMessageDelayed(msgWhat, 2000);
}
所以,最後的完整代碼是:
public class MainActivity extends Activity {
protected static final String tag = "MainActivity";
private ViewPager viewpager;
private List imageList = new ArrayList();
private Context context;
int msgWhat = 0;
private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
viewpager.setCurrentItem(viewpager.getCurrentItem() + 1);//收到消息,指向下一個頁面
handler.sendEmptyMessageDelayed(msgWhat, 2000);//2S後在發送一條消息,由於在handleMessage()方法中,造成死循環。
Log.d(tag, "handleMessage");
};
};
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
context = this;
initData();
viewpager = (ViewPager) findViewById(R.id.viewpager);
viewpager.setAdapter(new MyAdapter());
viewpager.setCurrentItem(1000);//當前頁是第1000頁
// Button只是為了驗證內存洩露
btn = (Button) findViewById(R.id.btn);
btn.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(context, SecondActivity.class);
startActivity(intent);
}
});
}
private void initData() {
imageList.clear();
ImageView iva = new ImageView(context);
iva.setBackgroundResource(R.drawable.a);
ImageView ivb = new ImageView(context);
ivb.setBackgroundResource(R.drawable.b);
ImageView ivc = new ImageView(context);
ivc.setBackgroundResource(R.drawable.c);
ImageView ivd = new ImageView(context);
ivd.setBackgroundResource(R.drawable.d);
ImageView ive = new ImageView(context);
ive.setBackgroundResource(R.drawable.e);
imageList.add(iva);
imageList.add(ivb);
imageList.add(ivc);
imageList.add(ivd);
imageList.add(ive);
}
public class MyAdapter extends PagerAdapter{
//表示viewpager共存放了多少個頁面
@Override
public int getCount() {
return Integer.MAX_VALUE;//我們設置viewpager中有Integer.MAX_VALUE個頁面
}
@Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
/**
* position % imageList.size() 而不是position,是為了防止角標越界異常
* 因為我們設置了viewpager子頁面的數量有Integer.MAX_VALUE,而imageList的數量只是5。
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(imageList.get(position % imageList.size()));
return imageList.get(position % imageList.size());
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View)object);
}
}
/**
* activity可見可交互的時候就開始發送消息,開啟循環
*/
@Override
protected void onResume() {
super.onResume();
handler.sendEmptyMessageDelayed(msgWhat, 2000);
}
/**
* 當MainActivity不可見的時候讓handler停止發送消息
* 防止內存洩露
*/
@Override
protected void onStop() {
super.onStop();
handler.removeMessages(msgWhat);
}
}
作者:Mark Liu 下載樣本代碼 簡介 隨機旋轉 該選擇可支持渲染視頻的平面隨著橫、縱軸呈 3D 效果隨機旋轉。此外,它還可定期在屏幕上呈現
Android實現九宮格圖案解鎖,自帶將圖案轉化成數字密碼的功能,代碼如下:LockPatternView.javapackage com.jackie.lockpatt
當我們進行Android開發,配置安裝環境Eclispe&SDK&ADT過程中,在SDK在線安裝後,重新登錄Eclispe,會出現警告框:This And
開發設計搞了一個帶圓形進度的進度條,在GitHub上逛了一圈,發現沒有,自己撸吧。先看界面效果:主要思路是寫一個繼承ProgressBar的自定義View,不廢話,直接上