編輯:關於Android編程
最近翻看以前的某項目時,發現了一個極其常用的效果——廣告條,或者也稱不上自定義組件,但是使用頻率還是相當普遍的。
打開市面上各大App主界面,或多或少會出現這樣的東西,甚至一個應用中出現N多個,這種展示廣告的效果,不僅動態效果好,而且眾所周知的“不占屏”,想想在手機設備這麼小的屏幕尺寸下,能放下幾頁甚至十幾頁的廣告循環播放,就知道這種廣告的使用頻率之大了。以下是我收集的部分APP中使用的效果截圖:



這些“千萬億”級別的APP都在使用的效果,為什麼我們不能效仿追隨一下呢,那下面我就開始動手做一個自己的廣告條;
要求如下:1,實現多圖展示
2,實現手勢切換
3,廣告圖片與廣告標語同時切換
4,循環切換,定時循環播放
以下是我的項目結構:

廣告條實際上用的是ViewPager來做的,布局中僅僅放了一個ViewPager而已,其它的圖片切換都是用ViewPager來展示的,布局如下:
package com.example.banner;
import java.util.ArrayList;
import java.util.List;
import android.os.Bundle;
import android.os.SystemClock;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.LinearLayout.LayoutParams;
import android.app.Activity;
public class MainActivity extends Activity {
private List mImageList;
/** 廣告條正下方的標語 */
private String[] imageDescriptionArray = { //
鞏俐不低俗,我就不能低俗, //
撲樹又回來啦!再唱經典老歌引萬人大合唱, //
揭秘北京電影如何升級, //
樂視網TV版大派送, //
熱血屌絲的反殺 };
/** 記錄上一次點的位置,默認為0 */
private int previousPointEnale = 0;
private ViewPager mViewPager;
private LinearLayout llPointGroup;
private TextView tvDescription;
/** 記錄是否停止循環播放 */
private boolean isStop = false;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
// 開啟子線程,讓廣告條以2秒的頻率循環播放
new Thread(new Runnable() {
@Override
public void run() {
while (!isStop) {
SystemClock.sleep(2000);
runOnUiThread(new Runnable() {
public void run() {
mViewPager.setCurrentItem(mViewPager.getCurrentItem() + 1);
}
});
}
}
}).start();
}
private void init() {
llPointGroup = (LinearLayout) findViewById(R.id.ll_point_group);
tvDescription = (TextView) findViewById(R.id.tv_image_description);
mImageList = new ArrayList();
int[] imageIds = new int[] { R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e };
ImageView mImageView;
LayoutParams params;
// 初始化廣告條資源
for (int id : imageIds) {
mImageView = new ImageView(this);
mImageView.setBackgroundResource(id);
mImageList.add(mImageView);
// 初始化廣告條正下方的點
View dot = new View(this);
dot.setBackgroundResource(R.drawable.point_background);
params = new LayoutParams(5, 5);
params.leftMargin = 10;
dot.setLayoutParams(params);
dot.setEnabled(false);
llPointGroup.addView(dot);
}
mViewPager = (ViewPager) findViewById(R.id.viewpager);
mViewPager.setAdapter(new MyAdapter());
// 設置廣告條跳轉時,廣告語和狀態語的變化
mViewPager.setOnPageChangeListener(new MyListener());
// 初始化廣告條,當前索引Integer.MAX_VALUE的一半
int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % mImageList.size());
mViewPager.setCurrentItem(index); // 設置當前選中的Page,會觸發onPageChangListener.onPageSelected方法
}
private class MyListener implements OnPageChangeListener {
@Override
public void onPageScrollStateChanged(int arg0) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int arg0) {
// 獲取新的位置
int newPosition = arg0 % imageDescriptionArray.length;
// 設置廣告標語
tvDescription.setText(imageDescriptionArray[newPosition]);
// 消除上一次的狀態點
llPointGroup.getChildAt(previousPointEnale).setEnabled(false);
// 設置當前的狀態點“點”
llPointGroup.getChildAt(newPosition).setEnabled(true);
// 記錄位置
previousPointEnale = newPosition;
}
}
/**
* ViewPager數據適配器
*/
private class MyAdapter extends PagerAdapter {
@Override
public int getCount() {
// 將viewpager頁數設置成Integer.MAX_VALUE,可以模擬無限循環
return Integer.MAX_VALUE;
}
/**
* 復用對象 true 復用view false 復用的是Object
*/
@Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return arg0 == arg1;
}
/**
* 銷毀對象
*
* @param position
* 被銷毀對象的索引位置
*/
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView(mImageList.get(position % mImageList.size()));
}
/**
* 初始化一個對象
*
* @param position
* 初始化對象的索引位置
*/
@Override
public Object instantiateItem(ViewGroup container, int position) {
container.addView(mImageList.get(position % mImageList.size()));
return mImageList.get(position % mImageList.size());
}
}
@Override
protected void onDestroy() {
// activity銷毀時候,關閉循環播放
isStop = true;
super.onDestroy();
}
}
到此還要注意的地方就是,因為getCount中返回Integer.MAX_VALUE這麼大數值,為了達到有圖循環的效果,避免Bug,所以其後每次涉及到position索引的地方都得用position和資源尺度取余的結果。
此外,在“點”的初始化的時候,應當設置“點”的索引為int index = (Integer.MAX_VALUE / 2) - (Integer.MAX_VALUE / 2 % mImageList.size());
而不能簡單設置成0,若是設置成0,就無法制造出循環播放的“假象”,不信試試設置0,往左滑動。
關於“點”的資源,沒有用到圖片,下面是資源代碼,貼出來:
廣告條獲得焦點:point_bg_enable.xml
以下是效果圖:


最後,還需要實現廣告的自動循環播放,這個很簡單,只要開啟一個新線程,在線程中每隔2000ms循環更新一下ViewPager就行。就是在ViewPager中獲取當前展示的Item的索引,加上1之後,設置展示這個值即可。還得注意程序的嚴謹性啊,當activity銷毀的時候,這個新線程裡負責循環播放的代碼是徐璈停止執行的。故設置一個boolean的變量isStop,在while循環的時候,判斷是否開啟/關閉,在activity的onDestory方法中,設置其為true,即停止循環播放!
我的Android進階之旅------Android 5.0中出現警告的解決方法: Service Intent must be explicit:
1.錯誤描述今天在Android4.4 的小米4手機上運行我的程序的時候沒有報錯,而在Android 5.1的華為P7上運行我的程序的時候報了以下的錯誤,錯誤提示如下:E
Android 仿蘋果IOS6開關按鈕
先給大家展示下效果圖:不知道大家對效果圖感覺怎麼樣,個人覺還不錯,感興趣的朋友可以參考下實現代碼哦。public class ToggleButton extends V
自定義動畫(仿Win10加載動畫)
一、源代碼源代碼及demo二、背景先看看Win10的加載動畫(找了很久才找到):每次打開電腦都會有這個加載動畫,看上挺cool的,就想著自己能否實現它。要實現這個動畫?首
ListView常用拓展
一、實現ListView下拉刷新第一步:添加頂部下拉加載界面,即ListView的header頭布局1、創建layout布局文件head_layout2、創建一個自定義L