Android之ViewFlipper的使用与ListView的分页加载

时间:2021-05-31 19:37:27

先上图:

Android之ViewFlipper的使用与ListView的分页加载Android之ViewFlipper的使用与ListView的分页加载Android之ViewFlipper的使用与ListView的分页加载Android之ViewFlipper的使用与ListView的分页加载Android之ViewFlipper的使用与ListView的分页加载


MainActivity.java
package com.example.hdu;

import java.util.ArrayList;
import java.util.HashMap;

import com.example.hdu.MyViewFlipper.OnDisplayChangedListener;

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup.LayoutParams;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.SimpleAdapter;
import android.widget.Toast;
import android.widget.ViewFlipper;

public class MainActivity extends Activity implements OnScrollListener,
		android.view.GestureDetector.OnGestureListener {

	// 设置全局变量,监控自动播放时候图片浏览顺序
	private boolean flag = true;

	private SimpleAdapter mSimpleAdapter;
	private ListView lv;
	private Button btn;
	private ProgressBar pgb;
	private ArrayList<HashMap<String, String>> list;

	private MarkView markView;
	private MyViewFlipper viewFlipper;

	// ListView底部View
	private View moreView;
	private Handler handler;

	private int MaxDateNum;

	private int lastVisibleIndex;

	// 图片滑动
	private int[] imgs = { R.drawable.img1, R.drawable.img2, R.drawable.img3,
			R.drawable.img4, R.drawable.img5 };
	private Animation rInAnim;
	private Animation rOutAnim;
	private Animation lInAnim;
	private Animation lOutAnim;

	private GestureDetector gestureDetector = null;

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

		// 从左向右滑动(左进右出)
		rInAnim = AnimationUtils.loadAnimation(this, R.anim.push_right_in);
		rOutAnim = AnimationUtils.loadAnimation(this, R.anim.push_right_out);
		// 从右向左滑动(右进左出)
		lInAnim = AnimationUtils.loadAnimation(this, R.anim.push_left_in);
		lOutAnim = AnimationUtils.loadAnimation(this, R.anim.push_left_out);

		viewFlipper = (MyViewFlipper) findViewById(R.id.viewflipper);

		markView = (MarkView) findViewById(R.id.markView);
		// 声明检测手势事件
		gestureDetector = new GestureDetector(this);
		// 添加图片源
		for (int i = 0; i < imgs.length; i++) {
			ImageView iv = new ImageView(this);
			iv.setImageResource(imgs[i]);
			iv.setScaleType(ImageView.ScaleType.FIT_XY);
			viewFlipper.addView(iv, new LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.FILL_PARENT));
		}

		// 设置标记个数
		markView.setMarkCount(imgs.length);
		// 起始位置设置为0
		markView.setMark(0);

		// 初始播放模式
		viewFlipper.setInAnimation(lInAnim);
		viewFlipper.setOutAnimation(lOutAnim);
		// 设置自动播放功能(点击事件前自动播放)
		viewFlipper.setAutoStart(true);
		viewFlipper.setFlipInterval(3000);
		if (viewFlipper.isAutoStart() && !viewFlipper.isFlipping()) {
			viewFlipper.startFlipping();
		}

		// viewFlipper设置监听事件
		viewFlipper.setOnDisplayChangedListener(new OnDisplayChangedListener() {

			@Override
			public void OnDisplayChildChanging(ViewFlipper view, int index) {
				markView.setMark(index);
			}
		});

		MaxDateNum = 35;
		lv = (ListView) findViewById(R.id.lv);
		// 实例化底部布局
		moreView = getLayoutInflater().inflate(R.layout.moredata, null);

		btn = (Button) moreView.findViewById(R.id.btn_load);
		pgb = (ProgressBar) moreView.findViewById(R.id.pgb_load);
		handler = new Handler();

		// 用map来装载数据,初始化5条数据
		list = new ArrayList<HashMap<String, String>>();
		for (int i = 0; i < 5; i++) {
			HashMap<String, String> map = new HashMap<String, String>();
			map.put("ItemTitle", "第" + i + "行标题");
			map.put("ItemText", "第" + i + "行");
			list.add(map);
		}
		// 实例化SimpleAdapter
		mSimpleAdapter = new SimpleAdapter(this, list, R.layout.item,
				new String[] { "ItemTitle", "ItemText" }, new int[] {
						R.id.tv_title, R.id.tv_content });
		// 加上底部View,注意要放在setAdapter方法前
		lv.addFooterView(moreView);
		lv.setAdapter(mSimpleAdapter);
		// 绑定监听器
		lv.setOnScrollListener(this);

		btn.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				pgb.setVisibility(View.VISIBLE);// 将进度条可见
				btn.setVisibility(View.GONE);// 按钮不可见

				handler.postDelayed(new Runnable() {

					@Override
					public void run() {
						loadMoreDate();// 加载更多数据
						btn.setVisibility(View.VISIBLE);
						pgb.setVisibility(View.GONE);
						mSimpleAdapter.notifyDataSetChanged();
					}

				}, 500);
			}
		});

	}

	@Override
	// 点击事件后与松开事件后
	public boolean onTouchEvent(MotionEvent event) {
		Log.e("false", "false");
		if (event.getAction() == MotionEvent.ACTION_DOWN) {
			viewFlipper.stopFlipping();
			viewFlipper.setAutoStart(false);
		} else if (event.getAction() == MotionEvent.ACTION_UP) {
			viewFlipper.setAutoStart(true);
			viewFlipper.setFlipInterval(3000);
			if (viewFlipper.isAutoStart() && !viewFlipper.isFlipping()) {
				viewFlipper.startFlipping();
			}
		}
		// 注册手势事件,可以返回你之前手指滑动方向,返回到onFling()方法
		return gestureDetector.onTouchEvent(event);

	}

	private void loadMoreDate() {
		int count = mSimpleAdapter.getCount();
		if (count + 5 < MaxDateNum) {
			// 每次加载5条
			for (int i = count; i < count + 6; i++) {
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("ItemTitle", "新增第" + i + "行标题");
				map.put("ItemText", "新增第" + i + "行内容");
				list.add(map);
			}
		} else {
			// 数据已经不足5条
			for (int i = count; i < MaxDateNum; i++) {
				HashMap<String, String> map = new HashMap<String, String>();
				map.put("ItemTitle", "新增第" + i + "行标题");
				map.put("ItemText", "新增第" + i + "行内容");
				list.add(map);
			}

		}
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		// 滑到底部后自动加载,判断listview已经停止滚动并且最后可视的条目等于adapter的条目
		if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
				&& lastVisibleIndex == mSimpleAdapter.getCount()) {
			// 当滑到底部时自动加载
			pgb.setVisibility(View.VISIBLE);
			btn.setVisibility(View.GONE);
			handler.postDelayed(new Runnable() {

				@Override
				public void run() {
					loadMoreDate();
					btn.setVisibility(View.VISIBLE);
					pgb.setVisibility(View.GONE);
					mSimpleAdapter.notifyDataSetChanged();
				}
			}, 500);
		}

		if (lastVisibleIndex == MaxDateNum - 1) {
			Toast.makeText(this, "数据全部加载完成", Toast.LENGTH_SHORT).show();
		}
		// Log.e("", "lastVisibleIndex  " + lastVisibleIndex);
	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		// 计算最后可见条目的索引
		lastVisibleIndex = firstVisibleItem + visibleItemCount - 1;
		// 所有的条目已经和最大条数相等,则移除底部的View
		if (totalItemCount == MaxDateNum + 1) {
			lv.removeFooterView(moreView);
		}
	}

	@Override
	public boolean onDown(MotionEvent e) {
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		return false;
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		if (e2.getX() - e1.getX() > 120) {
			// 右滑
			/*
			 * 右滑手势,然后通过下面两行代码改变之后的自动播放方向,仅仅是方向而已, 并不改变图片浏览的顺序
			 */
			viewFlipper.setInAnimation(rInAnim);
			viewFlipper.setOutAnimation(rOutAnim);
			viewFlipper.setFlag(false);
			viewFlipper.showPrevious();
		} else if (e2.getX() - e1.getX() < -120) {
			// 左滑
			viewFlipper.setInAnimation(lInAnim);
			viewFlipper.setOutAnimation(lOutAnim);
			viewFlipper.setFlag(true);
			viewFlipper.showNext();
		}
		return true;
	}
}

MyViewFlipper.java
package com.example.hdu;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ViewFlipper;

public class MyViewFlipper extends ViewFlipper {

	private Context mContext;

	private boolean mFlag = true;

	private OnDisplayChangedListener mListener;

	public MyViewFlipper(Context context) {
		super(context);
		mContext = context;
	}

	public MyViewFlipper(Context context, AttributeSet attrs) {
		super(context, attrs);
		mContext = context;
	}

	public void setFlag(boolean flag) {
		this.mFlag = flag;
	}

	public void setOnDisplayChangedListener(OnDisplayChangedListener listener) {
		if (mListener != listener) {
			this.mListener = listener;
		}
	}

	@Override
	public void showNext() {
		/*
		 * 因为自动播放时默认调用该方法,所以使用标志mFlag,当滑动趋势为左滑时,使图片播放顺序颠倒,
		 * 这时mFlag变为false,这样自动播放模式就为往前播放。
		 */
		if (mFlag == true) {
			super.showNext();
		}else{
			showPrevious();
		}

		if (mListener != null) {
			mListener.OnDisplayChildChanging(this, super.getDisplayedChild());
		}
	}

	@Override
	public void showPrevious() {
		super.showPrevious();
		mListener.OnDisplayChildChanging(this, super.getDisplayedChild());
	}
	
	//OnDisplayChangedListener的接口
	public interface OnDisplayChangedListener {
		void OnDisplayChildChanging(ViewFlipper view, int index);
	}
}

MarkView.java
package com.example.hdu;

import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import android.widget.LinearLayout;

public class MarkView extends LinearLayout {

	private ImageView[] mImageView;
	private Context context;

	public MarkView(Context context) {
		super(context);
		this.context = context;
	}

	public MarkView(Context context, AttributeSet attrs) {
		super(context, attrs);
		this.context = context;
	}

	public void setMarkCount(int iCount) {
		mImageView = new ImageView[iCount];
		LinearLayout.LayoutParams p = new LinearLayout.LayoutParams(
				LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
		for (int i = 0; i < iCount; i++) {
			ImageView image = new ImageView(context);
			image.setImageResource(R.drawable.unselected_dot);
			image.setLayoutParams(p);
			mImageView[i] = image;
			image.setId(i);
			addView(image);
		}
	}
	
	public void setMark(int position) {
		for(int i = 0; i < mImageView.length; i++) {
			if(i == position) {
				mImageView[i].setImageResource(R.drawable.select_dot);
			}else {
				mImageView[i].setImageResource(R.drawable.unselected_dot);
			}
		}
	}
}

activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1"
        android:orientation="vertical" >

        <com.example.hdu.MyViewFlipper
            android:id="@+id/viewflipper"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" />

        <com.example.hdu.MarkView
            android:id="@+id/markView"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/viewflipper"
            android:layout_centerHorizontal="true"
            android:layout_marginBottom="30dp" />
    </RelativeLayout>

    <LinearLayout
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="2"
        android:orientation="vertical" >

        <ListView
            android:id="@+id/lv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content" >
        </ListView>
    </LinearLayout>

</LinearLayout>

item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/tv_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:textSize="25sp" />

    <TextView
        android:id="@+id/tv_content"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="5dp"
        android:textSize="15sp" />

</LinearLayout>

moredata.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <Button
        android:id="@+id/btn_load"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="上滑或点击加载更多数据" />

    <ProgressBar
        android:id="@+id/pgb_load"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        android:visibility="gone" />

</LinearLayout>


以上就是所有的源码,看网上各种源码,发现都没有自己想要的,所以自己写了个,功能有以下:
  1. 首先是使用ViewFlipper的图片浏览,其中有自动播放与手势控制播放,并且在手势结束后,根据之前手势滑动的趋势改变自动播放的顺序。使用MyViewFlipper类继承ViewFlipper并且重写showNext()与showPrevious()方法,添加OnDisplayChangedListener的接口用以监听图片切换状态并改变小点点显示图片切换下面的点。
  2. 使用MarkView类继承LinearLayout来使用小点点标志。
  3. ListView的分页加载功能。xml文件中的item.xml是分页加载的数据显示模式。moredata.xml是列表上拉刷新过程显示的按钮和进度条。
  4. 这段代码参考各种资料,在整合自己的想法弄了三天。因为一些小细节问题处理的比较久,网上其他的源码对细节处理的不够让我满意,所以自己写了这个。单单就小点点的跟随显示就弄了好久,后来还要考虑自动播放顺序变换后,图片的播放顺序也要改变。定义一个标记量flag来说明滑动趋势,因为自动播放默认都是调用showNext()方法。所以在重载后的showNext()方法中判断这一标志。如果正常左滑,则自动播放调用重载后showNext()方法中原来的super.showNext()方法。如果右滑,flag变为false,自动播放判断flag后调用的是showPrevious()方法。
  5. 头次写这种代码,可能还有些许瑕疵。仅供参考。