效果是这个样的:
布局思路:
最外层父窗体是一个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 > </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>
文笔不好,好多东西只有在代码里注释才讲的出来,博客我会一直坚持,整理的过程中,也在思考如何写好博客。我在一直努力。