现在的移动应用, 很常见的一个交互效果就是在首页顶部添加图片轮播的控件, 焦点图可以放入广告, 也可以放入文章的内容图片, 它们不断自动切换, 点击焦点图即跳至对应的界面. 交互效果很棒. 做图片轮播的效果, 方法并不少. 本文使用了常见的viewpager 去实现. 支持显示网络图片下载在缓存显示, 如果有SD卡则默认将图片下载至SD卡中再显示本地的图片.
其实网上这类代码已经很多, 应该也有很多写得比我好. 今天有点时间, 就做了个来练手, 顺便写下自己第一篇原创文章. 敲代码之前也参考了一些网上的例子, 感谢那些大神!
好了,不多说别的, 直接上代码.(为了减少类的数量, 将一些方法直接写在主类中, 多多见谅哈~)
MainActivity:
/** * 图片轮播器<br>支持显示网络图片以及将网络图片下载至本地显示 * @author Mr.ET * */ public class MainActivity extends Activity{ private List<ImageView> mImageViewList = null; private List<View> mViewList = null; private TextView mArticleTitle = null; private ViewPager mViewPager = null; private Handler mHandler = null; private LinearLayout mCustomSpace = null; private MyPagerAdapter adapter = null; private boolean loopPlayState = false; private View view; //private final String mySign = "url"; private List<String> tList,pList,nList; private List<Bitmap> bList; //private int p1 = -1,p2 = -1,p3 = -1,p4 = -1; private String name; //图片总数 private final int pAccount = 4; //控制图片变量 private int pNum = 0; private int readStyle = -1; private final static int readInNet = 0; private final static int readInSD = 1; private final static int readInCache = 2; private Handler handler = new Handler(){ @Override public void handleMessage(Message msg) { if(msg.what == 0x111){ if(bList != null && bList.size() > 0 && readStyle != readInNet) bList.clear(); if(mImageViewList != null && mImageViewList.size() > 0) mImageViewList.clear(); //图片已备齐,可以设置pager图片 for(int i=0;i<pList.size();i++){ ImageView imageView = new ImageView(MainActivity.this); imageView.setLayoutParams(new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); imageView.setScaleType(ScaleType.FIT_XY); imageView.setOnClickListener(new ClickListener(i)); mImageViewList.add(imageView); view = new View(MainActivity.this); LayoutParams layoutParams = new LayoutParams(14, 14); layoutParams.setMargins(3, 0, 3, 0); view.setLayoutParams(layoutParams); view.setBackgroundResource(R.drawable.dot_normal); mViewList.add(view); mCustomSpace.addView(view); if(readStyle != readInNet){ BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/demo/"+nList.get(i)+".jpg", options); bList.add(bm); } } adapter = new MyPagerAdapter(); mViewPager.setAdapter(adapter); mViewPager.setOnPageChangeListener(new MyPageChangeListener()); if (!loopPlayState) { mArticleTitle.setText(tList.get(0)); mViewPager.setCurrentItem(0); mHandler.postDelayed(loopPlay, 3000); loopPlayState = true; } } super.handleMessage(msg); } }; public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mViewPager = (ViewPager)findViewById(R.id.viewpager); mArticleTitle = (TextView)findViewById(R.id.article_title); mCustomSpace = (LinearLayout)findViewById(R.id.custom_space); mHandler = new Handler(); mImageViewList = new ArrayList<ImageView>(); mViewList = new ArrayList<View>(); tList = new ArrayList<String>(); pList = new ArrayList<String>(); nList = new ArrayList<String>(); bList = new ArrayList<Bitmap>(); for(int i=0;i<4;i++){ tList.add("这是标题"+i); } pList.add("http://b.hiphotos.baidu.com/image/pic/item/203fb80e7bec54e767710215bb389b504fc26a1f.jpg"); pList.add("http://d.hiphotos.baidu.com/image/pic/item/32fa828ba61ea8d37e6f6c0f950a304e251f586f.jpg"); pList.add("http://g.hiphotos.baidu.com/image/pic/item/e1fe9925bc315c605aeb75e48fb1cb13495477ba.jpg"); pList.add("http://h.hiphotos.baidu.com/image/pic/item/d000baa1cd11728bd0359429cafcc3cec3fd2ca4.jpg"); readyToImage(); } /** * 下载图片前的准备 <br>主要根据有无SD卡来准备图片是下载在本地还是放在内存中 */ public void readyToImage(){ if(Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())){ //有SD卡 String folderPath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/demo"; File demoFile = new File(folderPath); if(!demoFile.exists()){ //不存在这个文件夹,即不存在所需的图片. 就启动线程去下载图片 readStyle = readInSD; for(int p=0;p<pList.size();p++){ DLPThread mythread = new DLPThread(pList.get(p)); mythread.start(); } }else{ File[] files = demoFile.listFiles(); if(files.length >= 4 && isImage(getFileType(files[0].getName())) && isImage(getFileType(files[1].getName())) && isImage(getFileType(files[2].getName())) && isImage(getFileType(files[3].getName()))){ readStyle = readInCache; for(int i=0;i<4;i++){ nList.add(files[i].getName()); } mainSetImage(); }else{ //下载图片 readStyle = readInSD; for(int p=0;p<pList.size();p++){ DLPThread mythread = new DLPThread(pList.get(p)); mythread.start(); } } } }else{ //无SD卡 readStyle = readInNet; for(int p=0;p<pList.size();p++){ DLPThread mythread = new DLPThread(pList.get(p)); mythread.start(); } } } /** * 线程下载图片至本地 * @author Mr.ET * */ class DLPThread extends Thread{ private String url; public DLPThread(String url){ this.url = url; } public void run(){ try { Looper.prepare(); Bitmap bitmap = (Bitmap)utils.requestGet(this.url, Bitmap.class); name = String.valueOf(System.currentTimeMillis()); nList.add(name); //存放文件名 if(readStyle != readInNet){ File folder = new File(Environment.getExternalStorageDirectory().getAbsolutePath()+"/demo"); if(!folder.exists()){ folder.mkdir(); } String path = folder + "/"+name+".jpg"; File file = new File(path); FileOutputStream fileOutputStream = new FileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG, 90, fileOutputStream); fileOutputStream.flush(); fileOutputStream.close(); }else{ //无SD卡 bList.add(bitmap); } pNum ++; setImage(); Looper.loop(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } } } public void setImage(){ if(pNum == pAccount){ handler.sendEmptyMessage(0x111); } } private final class MyPagerAdapter extends PagerAdapter { @Override public int getCount() { return mImageViewList.size(); } @Override public void destroyItem(ViewGroup container, int position, Object object) { ((ViewPager) container).removeView(mImageViewList.get(position)); } @Override public Object instantiateItem(ViewGroup container, int position) { ImageView temp = mImageViewList.get(position); temp.setImageBitmap(bList.get(position)); ((ViewPager) container).addView(temp); return temp; } @Override public boolean isViewFromObject(View arg0, Object arg1) { return arg0 == arg1; } } /** * 当ViewPager中页面的状态发生改变时调用 * * @author Mr.ET * */ private class MyPageChangeListener implements OnPageChangeListener { private int historyPosition = 0; /** * 当ViewPager中页面的状态发生改变时调用 */ public void onPageSelected(int position) { mArticleTitle.setText(tList.get(position)); mViewList.get(historyPosition).setBackgroundResource( R.drawable.dot_normal); mViewList.get(position).setBackgroundResource( R.drawable.dot_focused); historyPosition = position; } public void onPageScrollStateChanged(int arg0) { } public void onPageScrolled(int arg0, float arg1, int arg2) { } } /** * 设置自动间隔3秒自动切换图片 */ Runnable loopPlay = new Runnable() { @Override public void run() { int position = mViewPager.getCurrentItem(); if(position == (pList.size()-1)){ position = 0; mViewPager.setCurrentItem(position); } else{ Log.i("position++", "position++="+position++); mViewPager.setCurrentItem(position++); } mHandler.postDelayed(loopPlay, 3000); } }; private class ClickListener implements OnClickListener{ private int location; public ClickListener(int location){ this.location = location; } @Override public void onClick(View v){ Toast.makeText(MainActivity.this, "你点击了第"+this.location+"张的图片", 1000).show(); } } /** * 获取文件类型 * @param fileName * @return */ public static String getFileType(String fileName) { if (fileName != null) { int typeIndex = fileName.lastIndexOf("."); if (typeIndex != -1) { String fileType = fileName.substring(typeIndex + 1) .toLowerCase(); return fileType; } } return ""; } /** * 判断是否图片 * @param type * @return */ public static boolean isImage(String type) { if (type != null && (type.equals("jpg") || type.equals("gif") || type.equals("png") || type.equals("jpeg") || type.equals("bmp") || type.equals("wbmp") || type.equals("ico") || type.equals("jpe"))) { return true; } return false; } /** * 直接从SD获取图片显示 */ public void mainSetImage(){ if(bList != null && bList.size() > 0) bList.clear(); if(mImageViewList != null && mImageViewList.size() > 0) mImageViewList.clear(); //图片已备齐,可以设置pager图片 for(int i=0;i<4;i++){ ImageView imageView = new ImageView(MainActivity.this); imageView.setLayoutParams(new LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); imageView.setScaleType(ScaleType.FIT_XY); imageView.setOnClickListener(new ClickListener(i)); mImageViewList.add(imageView); view = new View(MainActivity.this); LayoutParams layoutParams = new LayoutParams(14, 14); layoutParams.setMargins(3, 0, 3, 0); view.setLayoutParams(layoutParams); view.setBackgroundResource(R.drawable.dot_normal); mViewList.add(view); mCustomSpace.addView(view); BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 2; Bitmap bm = BitmapFactory.decodeFile(Environment.getExternalStorageDirectory().getAbsolutePath()+ "/demo/"+nList.get(i), options); bList.add(bm); } adapter = new MyPagerAdapter(); mViewPager.setAdapter(adapter); mViewPager.setOnPageChangeListener(new MyPageChangeListener()); if (!loopPlayState) { mArticleTitle.setText(tList.get(0)); mViewPager.setCurrentItem(0); mHandler.postDelayed(loopPlay, 3000); loopPlayState = true; } } }
utils, 里面也简单的封装一下httpclient.
public class utils { private static DefaultHttpClient httpClient; static{ if(null == httpClient){ HttpParams httpParams = new BasicHttpParams(); HttpProtocolParams.setVersion(httpParams, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(httpParams, HTTP.UTF_8); HttpProtocolParams.setUseExpectContinue(httpParams, true); ConnManagerParams.setMaxTotalConnections(httpParams, 10); ConnManagerParams.setTimeout(httpParams, 60000); ConnPerRouteBean connPerRoute = new ConnPerRouteBean(8); ConnManagerParams.setMaxConnectionsPerRoute(httpParams,connPerRoute); HttpConnectionParams.setConnectionTimeout(httpParams, 20000); HttpConnectionParams.setSoTimeout(httpParams, 30000); SchemeRegistry schreg = new SchemeRegistry(); schreg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schreg.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443)); ClientConnectionManager connManager = new ThreadSafeClientConnManager(httpParams, schreg); httpClient = new DefaultHttpClient(connManager, httpParams); } } public static HttpClient getHttpClient(){ return httpClient; } public static Object requestGet(String url,Class<?>c){ try { HttpGet httpGet = new HttpGet(url); HttpResponse response = httpClient.execute(httpGet); if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK){ byte[] b = readInputStream(response.getEntity().getContent()); if(c == String.class){ String resultStr = new String(b); return resultStr; } if(c == Bitmap.class){ Bitmap bitmap = BitmapFactory.decodeByteArray(b, 0, b.length); // BitmapFactory.Options options = new BitmapFactory.Options(); // options.inSampleSize = 10; // Bitmap bitmap = BitmapFactory.decodeStream(response.getEntity().getContent(), null, options); return bitmap; } }else{ //sorry, can not ask for the http server...... } } catch (ClientProtocolException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } catch (IllegalStateException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } private static byte[] readInputStream(InputStream in) throws Exception { ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] b = new byte[1024]; int len = 0; while ((len = in.read(b)) != -1) { baos.write(b, 0, len); } in.close(); return baos.toByteArray(); } }
下面是用到的资源文件
dot_focused.xml :
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <solid android:color="#aaFFFFFF" /> <corners android:radius="50dip" /> </shape>
dot_normal.xml
:
<?xml version="1.0" encoding="utf-8"?> <shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="oval" > <solid android:color="#33000000" /> <corners android:radius="5dip" /> </shape>
主要思路:
先判断手机是否有SD卡: 1, 有SD卡. 将图片下载至SD卡中, 图片轮播将图片转为bitmap, 显示在imageview中. 2, 无SD卡. 将图片下载至缓存中, 直接转为bitmap并显示在imageview中.
第二种方法很不好, 因为每次打开应用都要发HTTP请求去下载图片,再来显示, 而HTTP请求是相当耗资源的操作, 严重影响交互. 所以请尽量减少无谓的HTTP请求. 当你的应用第一次安装, 这个时候就去下载这四个图片放在本地, 这是必须的, 因为这时候本地一张图片都没有嘛. 然后当用户继续操作应用, 比如继续看新闻看别的文章的时候, 可以在后台启动个线程 去 检查这四张图片的接口有无更新, 如果有更新, 再启动线程将图片悄悄的下载在本地中
, 并更新图片轮播的内容. 这样, 当用户下次再启动应用的时候, 图片轮播加载图片的速度就快了哦. 这是其中之一的思路. 具体还要看应用的需求, 在实现上有所变化.
代码中有注释, 也很简单. 应该很容易看懂吧.
例子写的不够简洁, 也还有不少可以优化的地方, 奈何时间有限, 请多包涵. 咱们互相学习, 一起进步吧. ^^