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