Android瀑布流照片墻實現(xiàn),體驗不規(guī)則排列的美感Demo
作者:網(wǎng)絡(luò)整理
Android瀑布流照片墻實現(xiàn),體驗不規(guī)則排列的美感Demo。
源碼簡介
Android瀑布流照片墻實現(xiàn),體驗不規(guī)則排列的美感Demo。
源碼運行截圖
源碼片段
- /**
- * 自定義的ScrollView,在其中動態(tài)地對圖片進(jìn)行添加。
- *
- * @author guolin
- */
- public class MyScrollView extends ScrollView implements OnTouchListener {
- /**
- * 每頁要加載的圖片數(shù)量
- */
- public static final int PAGE_SIZE = 15;
- /**
- * 記錄當(dāng)前已加載到第幾頁
- */
- private int page;
- /**
- * 每一列的寬度
- */
- private int columnWidth;
- /**
- * 當(dāng)前第一列的高度
- */
- private int firstColumnHeight;
- /**
- * 當(dāng)前第二列的高度
- */
- private int secondColumnHeight;
- /**
- * 當(dāng)前第三列的高度
- */
- private int thirdColumnHeight;
- /**
- * 是否已加載過一次layout,這里onLayout中的初始化只需加載一次
- */
- private boolean loadOnce;
- /**
- * 對圖片進(jìn)行管理的工具類
- */
- private ImageLoader imageLoader;
- /**
- * 第一列的布局
- */
- private LinearLayout firstColumn;
- /**
- * 第二列的布局
- */
- private LinearLayout secondColumn;
- /**
- * 第三列的布局
- */
- private LinearLayout thirdColumn;
- /**
- * 記錄所有正在下載或等待下載的任務(wù)。
- */
- 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中進(jìn)行圖片可見性檢查的判斷,以及加載更多圖片的操作。
- */
- private static Handler handler = new Handler() {
- public void handleMessage(android.os.Message msg) {
- MyScrollView myScrollView = (MyScrollView) msg.obj;
- int scrollY = myScrollView.getScrollY();
- // 如果當(dāng)前的滾動位置和上次相同,表示已停止?jié)L動
- if (scrollY == lastScrollY) {
- // 當(dāng)滾動的最底部,并且當(dāng)前沒有正在下載的任務(wù)時,開始加載下一頁的圖片
- if (scrollViewHeight + scrollY >= scrollLayout.getHeight()
- && taskCollection.isEmpty()) {
- myScrollView.loadMoreImages();
- }
- myScrollView.checkVisibility();
- } else {
- lastScrollY = scrollY;
- Message message = new Message();
- message.obj = myScrollView;
- // 5毫秒后再次對滾動位置進(jìn)行判斷
- handler.sendMessageDelayed(message, 5);
- }
- };
- };
- /**
- * MyScrollView的構(gòu)造函數(shù)。
- *
- * @param context
- * @param attrs
- */
- public MyScrollView(Context context, AttributeSet attrs) {
- super(context, attrs);
- imageLoader = ImageLoader.getInstance();
- taskCollection = new HashSet<loadimagetask>();
- setOnTouchListener(this);
- }
- /**
- * 進(jìn)行一些關(guān)鍵性的初始化操作,獲取MyScrollView的高度,以及得到第一列的寬度值。并在這里開始加載第一頁的圖片。
- */
- @Override
- protected 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();
- }
- }
- /**
- * 監(jiān)聽用戶的觸屏事件,如果用戶手指離開屏幕則開始進(jìn)行滾動檢測。
- */
- @Override
- public 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(Images.imageUrls[i]);
- }
- page++;
- } else {
- Toast.makeText(getContext(), "已沒有更多圖片", Toast.LENGTH_SHORT)
- .show();
- }
- } else {
- Toast.makeText(getContext(), "未發(fā)現(xiàn)SD卡", Toast.LENGTH_SHORT).show();
- }
- }
- /**
- * 遍歷imageViewList中的每張圖片,對圖片的可見性進(jìn)行檢查,如果圖片已經(jīng)離開屏幕可見范圍,則將圖片替換成一張空圖。
- */
- 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(imageUrl);
- }
- } else {
- imageView.setImageResource(R.drawable.empty_photo);
- }
- }
- }
- /**
- * 判斷手機(jī)是否有SD卡。
- *
- * @return 有SD卡返回true,沒有返回false。
- */
- private boolean hasSDCard() {
- return Environment.MEDIA_MOUNTED.equals(Environment
- .getExternalStorageState());
- }
- /**
- * 異步下載圖片的任務(wù)。
- *
- * @author guolin
- */
- class LoadImageTask extends AsyncTask<string, void,="" bitmap=""> {
- /**
- * 圖片的URL地址
- */
- private String mImageUrl;
- /**
- * 可重復(fù)使用的ImageView
- */
- private ImageView mImageView;
- public LoadImageTask() {
- }
- /**
- * 將可重復(fù)使用的ImageView傳入
- *
- * @param imageView
- */
- public LoadImageTask(ImageView imageView) {
- mImageView = imageView;
- }
- @Override
- protected Bitmap doInBackground(String... params) {
- mImageUrl = params[0];
- Bitmap imageBitmap = imageLoader
- .getBitmapFromMemoryCache(mImageUrl);
- if (imageBitmap == null) {
- imageBitmap = loadImage(mImageUrl);
- }
- return imageBitmap;
- }
- @Override
- protected 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);
- }
- /**
- * 根據(jù)傳入的URL,對圖片進(jìn)行加載。如果這張圖片已經(jīng)存在于SD卡中,則直接從SD卡里讀取,否則就從網(wǎng)絡(luò)上下載。
- *
- * @param imageUrl
- * 圖片的URL地址
- * @return 加載到內(nèi)存的圖片。
- */
- 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);
- findColumnToAdd(imageView, imageHeight).addView(imageView);
- imageViewList.add(imageView);
- }
- }
- /**
- * 找到此時應(yīng)該添加圖片的一列。原則就是對三列的高度進(jìn)行判斷,當(dāng)前高度最小的一列就是應(yīng)該添加的一列。
- *
- * @param imageView
- * @param imageHeight
- * @return 應(yīng)該添加圖片的一列
- */
- 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) {
- if (Environment.getExternalStorageState().equals(
- Environment.MEDIA_MOUNTED)) {
- Log.d("TAG", "monted sdcard");
- } else {
- Log.d("TAG", "has no sdcard");
- }
- 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;
- }
- }
- }</string,></loadimagetask></imageview></imageview></loadimagetask>
源碼下載:http://down.51cto.com/data/1980596
責(zé)任編輯:chenqingxiang
來源:
網(wǎng)絡(luò)整理