[android] 瀑布流布局——分页加载(详细代码)

效果是这个样的:

技术分享技术分享


布局思路:
最外层父窗体是一个RelativeLayout(图里没画出来),从内层开始。
黑色:自定义ScrollView
红色:LinearLayout,为了盛放内层三个布局,orientation为水平。
绿色:三个LinearLayout,用来实现散列的瀑布流效果。orientation为垂直。
间隙:实际不存在,这里只是为了能看清结构。
技术分享

布局代码:

    <com.example.stream.SV
        android:id="@+id/sv"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >

        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <LinearLayout
                android:id="@+id/ll1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical" >
            </LinearLayout>

            <LinearLayout
                android:id="@+id/ll2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical" >
            </LinearLayout>

            <LinearLayout
                android:id="@+id/ll3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical" >
            </LinearLayout>
        </LinearLayout>
    </com.example.stream.SV>


自定义ScrollView

用的是自定义ScrollView,因为原生的ScrollView没有滑动监听事件。用到上一篇博客所讲的自定义View,重写onTouchEvent()方法。设置回调接口,用来分页加载。

<span style="font-size:18px;">public class SV extends ScrollView{
	private OnScrollListener listener;
	public SV(Context context) {
		super(context);
	}
	public SV(Context context, AttributeSet attrs) {
		super(context, attrs);
	}
<span style="color:#ff0000;">	//传进来一个接口对象
	public interface OnScrollListener{
		void loadMore();
	}</span>
	
<span style="color:#ff0000;">	//设置滑动监听
	public void setOnScrollListener(OnScrollListener listener){
		this.listener = listener;
	}</span>

	
	//手指对屏幕的触摸事件---》监听是否滑到底
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		View childView = getChildAt(0);
		//获取测量高度(总高度)
		int measuredHeight = childView.getMeasuredHeight();
		//获取画出屏幕高度
		int scrollY = getScrollY();
		//获取可视区域
		int height = getHeight();
<span style="white-space:pre">		</span>//判断位置
		if(measuredHeight==scrollY+height){
			Toast.makeText(getContext(), "到底了!", 0).show();
			listener.loadMore();
		}
		return super.onTouchEvent(ev);
	}
}</span>

技术分享

通过这样计算来判断ScrollView是否滑到了底部,是否可以继续请求数据。

getHeight()+getScrollY()==getMeasureHeight();


MainActivity

注释已经很清楚了

<span style="font-size:18px;">public class MainActivity extends Activity {
	private LinearLayout ll1, ll2, ll3;
	// 每一个ImageView的宽度,是屏幕宽度的1/3
	private int imgvWidth;
	// 每次加载多少个
	private int pageSize = 15;
	//加载次数,每加载一次,pageIndex++
	private int pageIndex = 0;

	private String[] imgName;
	//布局有三个,添加到数组里,以便更新UI的时候使用。
	private LinearLayout lls[] = new LinearLayout[3];

	// 自定义ScrollView SV
	private SV sv;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		init();
	}

	private void init() {
		sv = (SV) findViewById(R.id.sv);
		// 用来盛放屏幕信息
		DisplayMetrics outMetrics = new DisplayMetrics();
		getWindowManager().getDefaultDisplay().getMetrics(outMetrics);
		//设置每个LinearLayout的宽度为整个屏幕的1/3
		imgvWidth = outMetrics.widthPixels / 3;
		ll1 = (LinearLayout) findViewById(R.id.ll1);
		ll2 = (LinearLayout) findViewById(R.id.ll2);
		ll3 = (LinearLayout) findViewById(R.id.ll3);
		lls[0] = ll1;
		lls[1] = ll2;
		lls[2] = ll3;

		try {
			//获取所有文件名
			imgName = getAssets().list("imgs");
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 第一次加载图片
		loadImage();
		//设置scrollView的滚动监听
		sv.setOnScrollListener(new OnScrollListener() {
			@Override
			public void loadMore() {
				if (pageIndex * pageSize >= imgName.length) {
					Toast.makeText(getApplicationContext(), "数据加载完成", 0).show();
				} else {
					loadImage();
				}
			}
		});
	}

	// 进行图片加载
	private void loadImage() {
		//如果加载的数量比所有文件个数少,每次加载15张
		for (int i = pageIndex * pageSize; i < pageIndex * pageSize + pageSize
				&& i < imgName.length; i++) {
			// 加载图片,实例化一个ImageView
			ImageView imgv = new ImageView(MainActivity.this);
			// 宽度是屏幕的1/3
			LayoutParams lp = new LayoutParams(imgvWidth,
					LayoutParams.WRAP_CONTENT);
			imgv.setLayoutParams(lp);
			// 加载图片资源
			LoadImageFromAssets.load(MainActivity.this, imgName[i], imgv);
			//每次往不同的LinearLayout放一个带有图片的ImageView
			lls[i % 3].addView(imgv);
		}
		pageIndex++;
	}
}</span>



从assets加载数据


<span style="font-size:18px;">public class LoadImageFromAssets {
	public static void load(final Activity activity,final String name,final ImageView iv){
		new Thread(){
			public void run(){			
				try {
					//从assets/imgs里获取图片资源,传入图片名字
					InputStream stream = activity.getAssets().open("imgs/"+name);
					final Bitmap bitmap = BitmapFactory.decodeStream(stream);
					//主线程更新UI
					activity.runOnUiThread(new Runnable(){
						public void run(){
							//获取图片宽高
							int bitH = bitmap.getHeight();
							int bitW = bitmap.getWidth();
							//获取LayoutParams设置宽高,使图片填充整个ImageView
							LayoutParams lp = (LayoutParams) iv.getLayoutParams();
							/**
							 * 图片的宽高比等于ImageView的宽高比,因为ImageView宽度已经确定(1/3父窗体),通过计算
							 * 得到ImageView的高度
							 */
							lp.height = bitH*lp.width/bitW;
							//将参数设置到ImageView
							iv.setLayoutParams(lp);
							iv.setImageBitmap(bitmap);
						}
					});
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}.start();
	}
}</span>

文笔不好,好多东西只有在代码里注释才讲的出来,博客我会一直坚持,整理的过程中,也在思考如何写好博客。我在一直努力。

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。