PS:一個bug又折騰了一個下午....哎...java
學習內容:android
1.Android利用ViewPager和PagerAdapter實現圖片輪播...app
2.使用反射機制獲取Android的資源信息...ide
圖片輪播是很是常見的一種動畫效果,在app中也是很經常使用的一個效果,這裏就簡單的來實現一下這個功能,Android中想要實現圖片輪播,須要使用到ViewPager這個控件來實現,這個控件的主要功能是實現圖片的滑動效果...那麼有了滑動,在滑動的基礎上附上圖片也就實現了圖片輪播的效果...這個控件相似於ListView,須要使用到適配器這個東西,適配器在這裏的做用是爲輪播時設置一些效果...這裏須要使用到PagerAdapter適配器...下面來一個例子,這個例子的效果是在圖片輪播的同時顯示播放的是第幾張圖片的信息...而且下面的點也是會隨之進行變化的...函數
先上一下佈局文件的代碼...這個佈局文件其實仍是有點說道的...<android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_height="fill_parent" android:layout_width="fill_parent"/>這句話必需要引進...不然會出現錯誤...意思就是我設置了一個滑動的效果,這個效果填充整個FrameLayout...每個View表示一個控件,這個控件的顯示方式在另外的xml文件當中...下面是兩個xml文件...佈局
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#000000"> </solid> <corners android:radius="5dip"/> </shape>
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval"> <solid android:color="#00ffff"/> <corners android:radius="5dip"/> </shape>
上面經過配置xml文件來完成View的顯示方式,由於這五個點的形狀,大小,甚至是顯示方式基本都是相同的,若是再去找5個點圖片或者是一個點圖片,而後經過Drawable資源的調用完成圖片的顯示...經過加載5次的方式...這樣顯然是沒有必要的,會浪費沒必要要的資源..所以咱們可使用xml提供的自定義圖形來完成這個過程...xml爲咱們提供了shape屬性,自定義控件..這裏我定義了一個實心圓...這個實心圓來完成隨着圖像的滑動,這個點也隨之進行相應的變化...看起來並非什麼難理解的東西...
學習
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <FrameLayout android:layout_height="300dip" android:layout_width="fill_parent"> <android.support.v4.view.ViewPager android:id="@+id/vp" android:layout_height="fill_parent" android:layout_width="fill_parent"/> <LinearLayout android:layout_height="30dip" android:layout_width="fill_parent" android:gravity="center" android:layout_gravity="bottom" android:orientation="vertical" android:background="#20000000" > <TextView android:id="@+id/tv" android:layout_height="wrap_content" android:layout_width="wrap_content" android:textColor="@android:color/white" android:text="@string/hello_world" android:layout_gravity="center_horizontal" android:layout_marginTop="3dip"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" android:layout_marginTop="3dip"> <View android:id="@+id/dot_0" android:layout_width="5dip" android:layout_height="5dip" android:layout_marginRight="3dip" android:layout_marginLeft="3dip" android:background="@drawable/dot"/> <View android:id="@+id/dot_1" android:layout_height="5dip" android:layout_width="5dip" android:layout_marginRight="3dip" android:layout_marginLeft="3dip" android:background="@drawable/dot_1"/> <View android:id="@+id/dot_2" android:layout_height="5dip" android:layout_width="5dip" android:layout_marginRight="3dip" android:layout_marginLeft="3dip" android:background="@drawable/dot_1"/> <View android:id="@+id/dot_3" android:layout_height="5dip" android:layout_width="5dip" android:layout_marginRight="3dip" android:layout_marginLeft="3dip" android:background="@drawable/dot_1"/> <View android:id="@+id/dot_4" android:layout_height="5dip" android:layout_width="5dip" android:layout_marginRight="3dip" android:layout_marginLeft="3dip" android:background="@drawable/dot_1"/> </LinearLayout> </LinearLayout> </FrameLayout> </RelativeLayout>
重要的部分仍是如何去實現這個過程...這個過程的實現就再下面的代碼中,詳細解釋也在代碼當中...
動畫
package com.example.picture_change; import java.lang.reflect.Field; import java.util.ArrayList; import java.util.HashMap; import java.util.Map.Entry; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.annotation.SuppressLint; import android.app.Activity; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; /* * HashMap存儲的鍵是不容許重複的...可是值是能夠重複的... * * */ public class MainActivity extends Activity { ArrayList<ImageView> imageSource=null; //存放圖像控件... ArrayList<View> dots=null; //存放5個點... int []images=null; //存放圖像的資源... String []titles=null; //伴隨着圖像的變更,標題也會隨之變更... TextView tv=null; //TextView來來顯示title的變化... ViewPager viewpager; //ViewPager來完成滑動效果... MyPagerAdapter adapter; //適配器... Map<String, Object>map=new HashMap<String, Object>(); @SuppressLint("UseSparseArrays") Map<Integer,Object>mapValues=new HashMap<Integer, Object>(); private int curr=0; private int old=0; int o=0; int mapsize; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toast.makeText(MainActivity.this, "a", Toast.LENGTH_LONG).show(); /* 下面利用反射來完成Drawable的資源獲取... * 在這裏我獲取了5張圖片的資源數據..這5張圖片分別爲a.jpg b.jpg c.jpg d.jpg e.jpg * 這裏使用了一個length<=1來完成數據的獲取...其實這個方式並很差,是我本身想出來的... * 暫時沒有更好的方法...我這裏使用反射的目的在下面會進行介紹... * */ Field [] field=R.drawable.class.getFields(); for(Field f:field){ if(f.getName().length()<=1){ try { o++; String str="image"+"_"+o; map.put(str, f.getInt(R.drawable.class));//使用map以鍵值對的形式來保存圖片的數據資源... } catch (IllegalArgumentException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IllegalAccessException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } mapsize=map.size()-1; /* 這裏我再次使用了一個map以鍵值對的形式只保存上一個map的Value值... * 這麼作的目的在下面進行說明... * * */ for(Entry<String, Object> entry:map.entrySet()){ mapValues.put(mapsize, entry.getValue()); mapsize--; } init(); } public void init(){ //數據信息的初始化... images=new int[]{R.drawable.a,R.drawable.b,R.drawable.c,R.drawable.d,R.drawable.e}; titles=new String[]{"this is the one picture","this is two picture","this is three picture","this is four picture","this is five picture"}; imageSource=new ArrayList<ImageView>(); //這裏初始化imageSource... for(int i=0;i<images.length;i++){ ImageView iamgeview =new ImageView(this); iamgeview.setBackgroundResource(images[i]); imageSource.add(iamgeview); } //這裏使用了一個方法...咱們沒有必要一次一次的findViewById()...使用下面的方法頗有效的解決了屢次findViewById()函數的引用... dots=new ArrayList<View>(); for(int j=0;j<5;j++){ String dotid="dot"+"_"+j; int resId=getResources().getIdentifier(dotid, "id", "com.example.picture_change"); dots.add(findViewById(resId)); } tv=(TextView) findViewById(R.id.tv); tv.setText(titles[0]); viewpager=(ViewPager) findViewById(R.id.vp); adapter=new MyPagerAdapter(); //這裏定義了一個適配器對象... viewpager.setAdapter(adapter); //傳遞對象,綁定適配器... viewpager.setOnPageChangeListener(new onpagelistener()); //這裏設置了一個當圖片發生滑動後的一個監聽效果... ScheduledExecutorService scheduled = Executors.newSingleThreadScheduledExecutor();//這裏咱們開啓一個線程... scheduled.scheduleAtFixedRate(new Runnable() { @Override public void run() { // TODO Auto-generated method stub curr=(curr+1)%images.length; handler.sendEmptyMessage(0);//將信息發送給Handler,讓Handler處理數據,完成一些操做... } }, 2, 2, TimeUnit.SECONDS); //實現內部方法,設置播放時間... } private class MyPagerAdapter extends PagerAdapter{ @Override public int getCount() { // TODO Auto-generated method stub return images.length; } @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub //判斷先後兩張的顯示圖片是否相同... return arg0==arg1; } @Override public void destroyItem(ViewGroup container, int position, Object object) { //銷燬...釋放內存... container.removeView(imageSource.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { /* 這個方法表示的是滑動到了第幾張圖片的定位...經過傳遞一個ViewGroup來完成數據的傳遞... * 咱們上面使用到了一個Map來保存上一個Map的Value值,這個的真正目的就在這裏..目的是爲了 * 獲取當前顯示圖片的資源信息..說白了就是要獲取(R.drawable.屬性),爲何要實現這個目的 * 由於咱們要實現,當這個顯示的圖片被點擊的時候,咱們應該進行哪些操做... * */ ImageView v=imageSource.get(position);//獲取當前圖片... //position是從0-4的值...所以能夠獲取到Map中的值了... v.setClickable(true); //設置圖片是能夠點擊的... final int values=(Integer)mapValues.get(position); //這裏咱們獲取map中保存的Values值... System.out.println(values); //下面就是實現觸發圖片時的監聽... v.setOnClickListener(new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub switch(values){ case R.drawable.a: Toast.makeText(MainActivity.this, "a", Toast.LENGTH_LONG).show(); break; case R.drawable.b: Toast.makeText(MainActivity.this, "b", Toast.LENGTH_LONG).show(); break; case R.drawable.c: Toast.makeText(MainActivity.this, "c", Toast.LENGTH_LONG).show(); break; case R.drawable.d: Toast.makeText(MainActivity.this, "d", Toast.LENGTH_LONG).show(); break; case R.drawable.e: Toast.makeText(MainActivity.this, "e", Toast.LENGTH_LONG).show(); break; } } }); container.addView(imageSource.get(position)); //將全部的圖片都加載到了container中... return imageSource.get(position); } } //定義一個內部類實現圖片在變化的時候的監聽... class onpagelistener 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) { // TODO Auto-generated method stub //當發生滑動後,要完成的一些相應操做... tv.setText(titles[arg0]); dots.get(arg0).setBackgroundResource(R.drawable.dot); dots.get(old).setBackgroundResource(R.drawable.dot_1); old=arg0; curr=arg0; } } @SuppressLint("HandlerLeak") private Handler handler=new Handler(){ public void handleMessage(Message msg) { //接收到消息後,更新頁面 viewpager.setCurrentItem(curr); }; }; @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); return true; } }
這裏我使用了反射機制來獲取Drawable的圖像資源,而後經過switch方法來完成了當圖片被點擊的時候須要完成的操做...這是筆者我本身想出來的一種方法...由於Android沒有提供ImageClickListener()這類的方法,所以咱們只可以本身去進行書寫圖片被點擊的方法...至於更好的方法,我是尚未發現...也是確實是能力有限制了,這個方法今天也想了整整一個下午才折騰出來的...
this
注意:給本身的一個提醒,HashMap的鍵是絕對不可以重複保存的...可是值是能夠保存重複的數據的,若是保存了重複的鍵,那麼在map只會保存第一個數據,不會對後續數據進行保存...這個也是一個很大的注意點,本身就栽這裏好久,雖然很低級的錯誤,可是頗有可能在不注意的狀況下就犯下了...所以在這裏也算是給本身提個醒...下次不會再犯下這樣的錯誤的..spa
總而言之,上述代碼就完成了Android中圖片輪播的動畫效果...