先上图:
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()方法。
- 头次写这种代码,可能还有些许瑕疵。仅供参考。