編輯:關於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 ListmImageList; /** 廣告條正下方的標語 */ 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,即停止循環播放!
1.錯誤描述今天在Android4.4 的小米4手機上運行我的程序的時候沒有報錯,而在Android 5.1的華為P7上運行我的程序的時候報了以下的錯誤,錯誤提示如下:E
先給大家展示下效果圖:不知道大家對效果圖感覺怎麼樣,個人覺還不錯,感興趣的朋友可以參考下實現代碼哦。public class ToggleButton extends V
一、源代碼源代碼及demo二、背景先看看Win10的加載動畫(找了很久才找到):每次打開電腦都會有這個加載動畫,看上挺cool的,就想著自己能否實現它。要實現這個動畫?首
一、實現ListView下拉刷新第一步:添加頂部下拉加載界面,即ListView的header頭布局1、創建layout布局文件head_layout2、創建一個自定義L