android 应用中,如欢迎指引页面, 和图片轮播功能, 或者更多的内容在一页显示不了,要分成多个页面,这时候viewpager是很好用的。
首先看下效果:
下面是一个例子,带异步网络加载图片,并带导航小圆点
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384 | package com.example.viewpagertest; import java.io.IOException; import java.lang.ref.SoftReference; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.params.CoreConnectionPNames; import android.annotation.SuppressLint; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager.OnPageChangeListener; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.example.viewpagertest.MainActivity.AsyncImageLoader.ImageCallback; /*** * * 说明:ViewPager ,带小圆点导航,适配器采用PagerAdapter,基本可以满足需求 * 也可以采用FragmentPagerAdapter,有人说,Fragment可以更好的适应平板和手机, * 并且可以更好的代码重用,具体这些好处大家试一下就知道了。 * * @author andylaw * * 更多内容请查看博客:http://blog.csdn.net/lyc66666666666 * */ @SuppressLint ( "NewApi" ) public class MainActivity extends Activity { private ViewPager view_pager; private LayoutInflater inflater; // 图片的地址,这里可以从服务器获取 String[] urls = new String[]{ "http://a.hiphotos.baidu.com/image/pic/item/3bf33a87e950352ad6465dad5143fbf2b2118b6b.jpg" , "http://a.hiphotos.baidu.com/image/pic/item/c8177f3e6709c93d002077529d3df8dcd0005440.jpg" , "http://f.hiphotos.baidu.com/image/pic/item/7aec54e736d12f2ecc3d90f84dc2d56285356869.jpg" , "http://e.hiphotos.baidu.com/image/pic/item/9c16fdfaaf51f3de308a87fc96eef01f3a297969.jpg" , "http://d.hiphotos.baidu.com/image/pic/item/f31fbe096b63f624b88f7e8e8544ebf81b4ca369.jpg" , "http://h.hiphotos.baidu.com/image/pic/item/11385343fbf2b2117c2dc3c3c88065380cd78e38.jpg" , "http://c.hiphotos.baidu.com/image/pic/item/3801213fb80e7bec5ed8456c2d2eb9389b506b38.jpg" }; private ImageView image; private View item ; private MyAdapter adapter ; private ImageView[] indicator_imgs = new ImageView[ 7 ]; //存放引到图片数组 @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); view_pager = (ViewPager) findViewById(R.id.view_pager); List<view> list = new ArrayList<view>(); inflater = LayoutInflater.from( this ); /** * 创建多个item (每一条viewPager都是一个item) * 从服务器获取完数据(如文章标题、url地址) 后,再设置适配器 */ for ( int i = 0 ; i < 7 ; i++) { item = inflater.inflate(R.layout.item, null ); ((TextView) item.findViewById(R.id.text_view)).setText( "第 " + i+ " 个 viewPager" ); list.add(item); } //创建适配器, 把组装完的组件传递进去 adapter = new MyAdapter(list); view_pager.setAdapter(adapter); //绑定动作监听器:如翻页的动画 view_pager.setOnPageChangeListener( new MyListener()); initIndicator(); } /** * 初始化引导图标 * 动态创建多个小圆点,然后组装到线性布局里 */ private void initIndicator(){ ImageView imgView; View v = findViewById(R.id.indicator); // 线性水平布局,负责动态调整导航图标 for ( int i = 0 ; i < 7 ; i++) { imgView = new ImageView( this ); LinearLayout.LayoutParams params_linear = new LinearLayout.LayoutParams( 10 , 10 ); params_linear.setMargins( 7 , 10 , 7 , 10 ); imgView.setLayoutParams(params_linear); indicator_imgs[i] = imgView; if (i == 0 ) { // 初始化第一个为选中状态 indicator_imgs[i].setBackgroundResource(R.drawable.indicator_focused); } else { indicator_imgs[i].setBackgroundResource(R.drawable.indicator); } ((ViewGroup)v).addView(indicator_imgs[i]); } } /** * 适配器,负责装配 、销毁 数据 和 组件 。 */ private class MyAdapter extends PagerAdapter { private List<view> mList; private AsyncImageLoader asyncImageLoader; public MyAdapter(List<view> list) { mList = list; asyncImageLoader = new AsyncImageLoader(); } /** * Return the number of views available. */ @Override public int getCount() { // TODO Auto-generated method stub return mList.size(); } /** * Remove a page for the given position. * 滑动过后就销毁 ,销毁当前页的前一个的前一个的页! * instantiateItem(View container, int position) * This method was deprecated in API level . Use instantiateItem(ViewGroup, int) */ @Override public void destroyItem(ViewGroup container, int position, Object object) { // TODO Auto-generated method stub container.removeView(mList.get(position)); } @Override public boolean isViewFromObject(View arg0, Object arg1) { // TODO Auto-generated method stub return arg0==arg1; } /** * Create the page for the given position. */ @Override public Object instantiateItem( final ViewGroup container, final int position) { Drawable cachedImage = asyncImageLoader.loadDrawable( urls[position], new ImageCallback() { public void imageLoaded(Drawable imageDrawable, String imageUrl) { View view = mList.get(position); image = ((ImageView) view.findViewById(R.id.image)); image.setBackground(imageDrawable); container.removeView(mList.get(position)); container.addView(mList.get(position)); // adapter.notifyDataSetChanged(); } }); View view = mList.get(position); image = ((ImageView) view.findViewById(R.id.image)); image.setBackground(cachedImage); container.removeView(mList.get(position)); container.addView(mList.get(position)); // adapter.notifyDataSetChanged(); return mList.get(position); } } /** * 动作监听器,可异步加载图片 * */ private class MyListener implements OnPageChangeListener{ @Override public void onPageScrollStateChanged( int state) { // TODO Auto-generated method stub if (state == 0 ) { //new MyAdapter(null).notifyDataSetChanged(); } } @Override public void onPageScrolled( int arg0, float arg1, int arg2) { // TODO Auto-generated method stub } @Override public void onPageSelected( int position) { // 改变所有导航的背景图片为:未选中 for ( int i = 0 ; i < indicator_imgs.length; i++) { indicator_imgs[i].setBackgroundResource(R.drawable.indicator); } // 改变当前背景图片为:选中 indicator_imgs[position].setBackgroundResource(R.drawable.indicator_focused); } } /** * 异步加载图片 */ static class AsyncImageLoader { // 软引用,使用内存做临时缓存 (程序退出,或内存不够则清除软引用) private HashMap<string, softreference<drawable= "" >> imageCache; public AsyncImageLoader() { imageCache = new HashMap<string, softreference<drawable= "" >>(); } /** * 定义回调接口 */ public interface ImageCallback { public void imageLoaded(Drawable imageDrawable, String imageUrl); } /** * 创建子线程加载图片 * 子线程加载完图片交给handler处理(子线程不能更新ui,而handler处在主线程,可以更新ui) * handler又交给imageCallback,imageCallback须要自己来实现,在这里可以对回调参数进行处理 * * @param imageUrl :须要加载的图片url * @param imageCallback: * @return */ public Drawable loadDrawable( final String imageUrl, final ImageCallback imageCallback) { //如果缓存中存在图片 ,则首先使用缓存 if (imageCache.containsKey(imageUrl)) { SoftReference<drawable> softReference = imageCache.get(imageUrl); Drawable drawable = softReference.get(); if (drawable != null ) { imageCallback.imageLoaded(drawable, imageUrl); //执行回调 return drawable; } } /** * 在主线程里执行回调,更新视图 */ final Handler handler = new Handler() { public void handleMessage(Message message) { imageCallback.imageLoaded((Drawable) message.obj, imageUrl); } }; /** * 创建子线程访问网络并加载图片 ,把结果交给handler处理 */ new Thread() { @Override public void run() { Drawable drawable = loadImageFromUrl(imageUrl); // 下载完的图片放到缓存里 imageCache.put(imageUrl, new SoftReference<drawable>(drawable)); Message message = handler.obtainMessage( 0 , drawable); handler.sendMessage(message); } }.start(); return null ; } /** * 下载图片 (注意HttpClient 和httpUrlConnection的区别) */ public Drawable loadImageFromUrl(String url) { try { HttpClient client = new DefaultHttpClient(); client.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, 1000 * 15 ); HttpGet get = new HttpGet(url); HttpResponse response; response = client.execute(get); if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) { HttpEntity entity = response.getEntity(); Drawable d = Drawable.createFromStream(entity.getContent(), "src" ); return d; } else { return null ; } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null ; } //清除缓存 public void clearCache() { if ( this .imageCache.size() > 0 ) { this .imageCache.clear(); } } } } </drawable></drawable></string,></string,></view></view></view></view> |
下面是layout主文件:
1234567891011121314 | <span style= "font-size: 14px;" ><linearlayout android:paddingtop= "@dimen/activity_vertical_margin" android:paddingright= "@dimen/activity_horizontal_margin" android:paddingleft= "@dimen/activity_horizontal_margin" android:paddingbottom= "@dimen/activity_vertical_margin" android:layout_height= "match_parent" android:layout_width= "match_parent" xmlns:tools= "http://schemas.android.com/tools" xmlns:android= "http://schemas.android.com/apk/res/android" > <relativelayout android:layout_height= "fill_parent" android:layout_width= "fill_parent" > </android.support.v4.view.viewpager> <linearlayout android:id= "@+id/indicator" android:layout_height= "100px" android:layout_width= "fill_parent" android:orientation= "horizontal" android:gravity= "center_horizontal" android:layout_margintop= "500px" > </linearlayout> </relativelayout> </linearlayout> </span> |
下面是每一条item文件:
1234567 | <span style= "font-size: 14px;" ><linearlayout android:paddingtop= "@dimen/activity_vertical_margin" android:paddingright= "@dimen/activity_horizontal_margin" android:paddingleft= "@dimen/activity_horizontal_margin" android:paddingbottom= "@dimen/activity_vertical_margin" android:layout_height= "match_parent" android:layout_width= "match_parent" xmlns:tools= "http://schemas.android.com/tools" xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" > <textview android:id= "@+id/text_view" android:layout_height= "wrap_content" android:layout_width= "fill_parent" > <imageview android:id= "@+id/image" android:layout_height= "wrap_content" android:layout_width= "fill_parent" > </imageview></textview></linearlayout></span> |