android ScrollView判断滑动到底部的两种方式

package com.example.photowallfallsdemo;import java.io.BufferedInputStream;import java.io.BufferedOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.net.HttpURLConnection;import java.net.URL;import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set;import android.content.Context;import android.content.Intent;import android.graphics.Bitmap;import android.os.AsyncTask;import android.os.Environment;import android.os.Handler;import android.os.Message;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.view.View.OnTouchListener;import android.widget.ImageView;import android.widget.ImageView.ScaleType;import android.widget.LinearLayout;import android.widget.ScrollView;import android.widget.Toast;/*** @author guolin*/public class MyScrollView extends ScrollView implements OnTouchListener {/*** 每页要加载的图片数量*/public static final int PAGE_SIZE = 15;/*** 记录当前已加载到第几页*/private int page;/*** 每一列的宽度*/private int columnWidth;/*** 当前第一列的高度*/private int firstColumnHeight;/*** 当前第二列的高度*/private int secondColumnHeight;/*** 当前第三列的高度*/private int thirdColumnHeight;/*** 是否已加载过一次layout,这里onLayout中的初始化只需加载一次*/private boolean loadOnce;/*** 对图片进行管理的工具类*/private ImageLoader imageLoader;/*** 第一列的布局*/private LinearLayout firstColumn;/*** 第二列的布局*/private LinearLayout secondColumn;/*** 第三列的布局*/private LinearLayout thirdColumn;/*** 记录所有正在下载或等待下载的任务。*/private static Set<LoadImageTask> taskCollection;/*** MyScrollView下的直接子布局。*/private static View scrollLayout;/*** MyScrollView布局的高度。*/private static int scrollViewHeight;/*** 记录上垂直方向的滚动距离。*/private static int lastScrollY = -1;/*** 记录所有界面上的图片,用以可以随时控制对图片的释放。*/private List<ImageView> imageViewList = new ArrayList<ImageView>();/*** 在Handler中进行图片可见性检查的判断,以及加载更多图片的操作。*/private static Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {MyScrollView myScrollView = (MyScrollView) msg.obj;int scrollY = myScrollView.getScrollY();// 如果当前的滚动位置和上次相同,,表示已停止滚动if (scrollY == lastScrollY) {// 当滚动的最底部,并且当前没有正在下载的任务时,开始加载下一页的图片,这种只会是往下翻页的情况// scrollLayout.getHeight表示内容的高度,getScrollY()方法表示已经滑动了多少的坐标,是左上角的Y坐标if (scrollViewHeight + scrollY >= scrollLayout.getHeight()&& taskCollection.isEmpty()) {myScrollView.loadMoreImages();}myScrollView.checkVisibility();} else {lastScrollY = scrollY;Message message = new Message();message.obj = myScrollView;// 5毫秒后再次对滚动位置进行判断handler.sendMessageDelayed(message, 5);}};};/*** MyScrollView的构造函数。** @param context* @param attrs*/public MyScrollView(Context context, AttributeSet attrs) {super(context, attrs);imageLoader = ImageLoader.getInstance();taskCollection = new HashSet<LoadImageTask>();setOnTouchListener(this);}/*** 进行一些关键性的初始化操作,获取MyScrollView的高度,以及得到第一列的宽度值。并在这里开始加载第一页的图片。*/@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {super.onLayout(changed, l, t, r, b);if (changed && !loadOnce) {scrollViewHeight = getHeight();scrollLayout = getChildAt(0);firstColumn = (LinearLayout) findViewById(R.id.first_column);secondColumn = (LinearLayout) findViewById(R.id.second_column);thirdColumn = (LinearLayout) findViewById(R.id.third_column);columnWidth = firstColumn.getWidth();loadOnce = true;loadMoreImages();}} //这是第2种方式@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {// TODO Auto-generated method stubsuper.onScrollChanged(l, t, oldl, oldt);if (t + getHeight() >= computeVerticalScrollRange(){// ScrollView滑动到底部了}}/*** 监听用户的触屏事件,如果用户手指离开屏幕则开始进行滚动检测。*/@Overridepublic boolean onTouch(View v, MotionEvent event) {if (event.getAction() == MotionEvent.ACTION_UP) {Message message = new Message();message.obj = this;handler.sendMessageDelayed(message, 5);}return false;}/*** 开始加载下一页的图片,每张图片都会开启一个异步线程去下载。*/public void loadMoreImages() {if (hasSDCard()) {int startIndex = page * PAGE_SIZE;int endIndex = page * PAGE_SIZE + PAGE_SIZE;if (startIndex < Images.imageUrls.length) {Toast.makeText(getContext(), "正在加载…", Toast.LENGTH_SHORT).show();if (endIndex > Images.imageUrls.length) {endIndex = Images.imageUrls.length;}for (int i = startIndex; i < endIndex; i++) {LoadImageTask task = new LoadImageTask();taskCollection.add(task);task.execute(i);}page++;} else {Toast.makeText(getContext(), "已没有更多图片", Toast.LENGTH_SHORT).show();}} else {Toast.makeText(getContext(), "未发现SD卡", Toast.LENGTH_SHORT).show();}}/*** 遍历imageViewList中的每张图片,对图片的可见性进行检查,如果图片已经离开屏幕可见范围,则将图片替换成一张空图。*/public void checkVisibility() {for (int i = 0; i < imageViewList.size(); i++) {ImageView imageView = imageViewList.get(i);int borderTop = (Integer) imageView.getTag(R.string.border_top);int borderBottom = (Integer) imageView.getTag(R.string.border_bottom);if (borderBottom > getScrollY()&& borderTop < getScrollY() + scrollViewHeight) {String imageUrl = (String) imageView.getTag(R.string.image_url);Bitmap bitmap = imageLoader.getBitmapFromMemoryCache(imageUrl);if (bitmap != null) {imageView.setImageBitmap(bitmap);} else {LoadImageTask task = new LoadImageTask(imageView);task.execute(i);}} else {imageView.setImageResource(R.drawable.empty_photo);}}}/*** 判断手机是否有SD卡。** @return 有SD卡返回true,没有返回false。*/private boolean hasSDCard() {return Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState());}/*** 异步下载图片的任务。** @author guolin*/class LoadImageTask extends AsyncTask<Integer, Void, Bitmap> {/*** 图片的URL地址*/private String mImageUrl;/*** 可重复使用的ImageView*/private ImageView mImageView;private int mItemPosition;public LoadImageTask() {}/*** 将可重复使用的ImageView传入** @param imageView*/public LoadImageTask(ImageView imageView) {mImageView = imageView;}@Overrideprotected Bitmap doInBackground(Integer… params) {mItemPosition = params[0];mImageUrl = Images.imageUrls[mItemPosition];Bitmap imageBitmap = imageLoader.getBitmapFromMemoryCache(mImageUrl);if (imageBitmap == null) {imageBitmap = loadImage(mImageUrl);}return imageBitmap;}@Overrideprotected void onPostExecute(Bitmap bitmap) {if (bitmap != null) {double ratio = bitmap.getWidth() / (columnWidth * 1.0);int scaledHeight = (int) (bitmap.getHeight() / ratio);addImage(bitmap, columnWidth, scaledHeight);}taskCollection.remove(this);}/*** 根据传入的URL,对图片进行加载。如果这张图片已经存在于SD卡中,则直接从SD卡里读取,否则就从网络上下载。** @param imageUrl* 图片的URL地址* @return 加载到内存的图片。*/private Bitmap loadImage(String imageUrl) {File imageFile = new File(getImagePath(imageUrl));if (!imageFile.exists()) {downloadImage(imageUrl);}if (imageUrl != null) {Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(imageFile.getPath(), columnWidth);if (bitmap != null) {imageLoader.addBitmapToMemoryCache(imageUrl, bitmap);return bitmap;}}return null;}/*** 向ImageView中添加一张图片** @param bitmap* 待添加的图片* @param imageWidth* 图片的宽度* @param imageHeight* 图片的高度*/private void addImage(Bitmap bitmap, int imageWidth, int imageHeight) {LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(imageWidth, imageHeight);if (mImageView != null) {mImageView.setImageBitmap(bitmap);} else {ImageView imageView = new ImageView(getContext());imageView.setLayoutParams(params);imageView.setImageBitmap(bitmap);imageView.setScaleType(ScaleType.FIT_XY);imageView.setPadding(5, 5, 5, 5);imageView.setTag(R.string.image_url, mImageUrl);imageView.setOnClickListener(new OnClickListener() {@Overridepublic void onClick(View v) {Intent intent = new Intent(getContext(),ImageDetailsActivity.class);intent.putExtra("image_position", mItemPosition);getContext().startActivity(intent);}});findColumnToAdd(imageView, imageHeight).addView(imageView);imageViewList.add(imageView);}}/*** 找到此时应该添加图片的一列。原则就是对三列的高度进行判断,当前高度最小的一列就是应该添加的一列。** @param imageView* @param imageHeight* @return 应该添加图片的一列*/private LinearLayout findColumnToAdd(ImageView imageView,int imageHeight) {if (firstColumnHeight <= secondColumnHeight) {if (firstColumnHeight <= thirdColumnHeight) {imageView.setTag(R.string.border_top, firstColumnHeight);firstColumnHeight += imageHeight;imageView.setTag(R.string.border_bottom, firstColumnHeight);return firstColumn;}imageView.setTag(R.string.border_top, thirdColumnHeight);thirdColumnHeight += imageHeight;imageView.setTag(R.string.border_bottom, thirdColumnHeight);return thirdColumn;} else {if (secondColumnHeight <= thirdColumnHeight) {imageView.setTag(R.string.border_top, secondColumnHeight);secondColumnHeight += imageHeight;imageView.setTag(R.string.border_bottom, secondColumnHeight);return secondColumn;}imageView.setTag(R.string.border_top, thirdColumnHeight);thirdColumnHeight += imageHeight;imageView.setTag(R.string.border_bottom, thirdColumnHeight);return thirdColumn;}}/*** 将图片下载到SD卡缓存起来。** @param imageUrl* 图片的URL地址。*/private void downloadImage(String imageUrl) {HttpURLConnection con = null;FileOutputStream fos = null;BufferedOutputStream bos = null;BufferedInputStream bis = null;File imageFile = null;try {URL url = new URL(imageUrl);con = (HttpURLConnection) url.openConnection();con.setConnectTimeout(5 * 1000);con.setReadTimeout(15 * 1000);con.setDoInput(true);con.setDoOutput(true);bis = new BufferedInputStream(con.getInputStream());imageFile = new File(getImagePath(imageUrl));fos = new FileOutputStream(imageFile);bos = new BufferedOutputStream(fos);byte[] b = new byte[1024];int length;while ((length = bis.read(b)) != -1) {bos.write(b, 0, length);bos.flush();}} catch (Exception e) {e.printStackTrace();} finally {try {if (bis != null) {bis.close();}if (bos != null) {bos.close();}if (con != null) {con.disconnect();}} catch (IOException e) {e.printStackTrace();}}if (imageFile != null) {Bitmap bitmap = ImageLoader.decodeSampledBitmapFromResource(imageFile.getPath(), columnWidth);if (bitmap != null) {imageLoader.addBitmapToMemoryCache(imageUrl, bitmap);}}}/*** 获取图片的本地存储路径。** @param imageUrl* 图片的URL地址。* @return 图片的本地存储路径。*/private String getImagePath(String imageUrl) {int lastSlashIndex = imageUrl.lastIndexOf("/");String imageName = imageUrl.substring(lastSlashIndex + 1);String imageDir = Environment.getExternalStorageDirectory().getPath() + "/PhotoWallFalls/";File file = new File(imageDir);if (!file.exists()) {file.mkdirs();}String imagePath = imageDir + imageName;return imagePath;}}}

而开始追寻他内心世界的真正财富

android ScrollView判断滑动到底部的两种方式

相关文章:

你感兴趣的文章:

标签云: