首先是布局文件:
activity_main.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <!--footerDividersEnabled设成flase时,此ListView将不会在页脚视图前画分隔符。此属性缺省值为true --> <com.example.hdu.MyListView android:id="@+id/lv_main" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_weight="1" android:headerDividersEnabled="false" android:footerDividersEnabled="false" > </com.example.hdu.MyListView> </LinearLayout>
<?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="fill_parent" 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
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="205dp" > <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="20dp" /> </RelativeLayout>
在res文件下创建anim文件夹,实现viewflipper动画模式,anim文件下有如下四个xml文件
push_left_in.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="100%p" android:toXDelta="0" /> <alpha android:duration="500" android:fromAlpha="0.1" android:toAlpha="1.0" /> </set>push_left_out.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="0" android:toXDelta="-100%p" /> <alpha android:duration="500" android:fromAlpha="1.0" android:toAlpha="0.1" /> </set>push_right_in.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="-100%p" android:toXDelta="0" /> <alpha android:duration="500" android:fromAlpha="0.1" android:toAlpha="1.0" /> </set>push_right_out.xml
<?xml version="1.0" encoding="utf-8"?> <set xmlns:android="http://schemas.android.com/apk/res/android" > <translate android:duration="500" android:fromXDelta="0" android:toXDelta="100%p" /> <alpha android:duration="500" android:fromAlpha="1.0" android:toAlpha="0.1" /> </set>Java代码:
MainActivity.java
package com.example.hdu; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.ContextMenu; import android.view.ContextMenu.ContextMenuInfo; import android.view.GestureDetector; import android.view.GestureDetector.OnGestureListener; import android.view.MotionEvent; import android.view.View; import android.view.View.OnClickListener; import android.view.View.OnCreateContextMenuListener; 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.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.AdapterView.OnItemLongClickListener; import android.widget.Button; import android.widget.ImageView; import android.widget.ImageView.ScaleType; import android.widget.ProgressBar; import android.widget.Toast; import android.widget.ViewFlipper; import com.example.hdu.MyViewFlipper.OnDisplayChangedListener; public class MainActivity extends Activity implements OnScrollListener, OnGestureListener { // 设置全局变量,监控自动播放时候图片浏览顺序 private boolean Flag = true; private GestureDetector detector; private Adapter mSimpleAdapter; private MyListView lv_main; private Button btn; private ProgressBar pgb; private ArrayList<HashMap<String, String>> list; private MarkView markView; private MyViewFlipper viewFlipper; // ListView顶部View即ViewFlipper private View headView; // ListView底部View private View moreView; private Handler handler; private int MaxDateNum; private int lastVisibleIndex; // 图片动画 private Animation rInAnim; private Animation rOutAnim; private Animation lInAnim; private Animation lOutAnim; /** * 获取viewflipper图片资源 */ private ArrayList<Integer> getImageDate() { ArrayList<Integer> imgs = new ArrayList<Integer>(); imgs.add(R.drawable.img1); imgs.add(R.drawable.img2); imgs.add(R.drawable.img3); imgs.add(R.drawable.img4); imgs.add(R.drawable.img5); return imgs; } /** * 设置listview的适配器 */ private void setListViewAdapter() { // 用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 Adapter(MainActivity.this, list); } /** * 图片滑动 */ // viewflipper的孩子 private List<View> views; /** * 初始化小点点 */ void initPoint() { // 设置标记个数 markView.setMarkCount(views.size()); // // 起始位置设置为0 // markView.setMark(0); } /** * 初始化ViewFlipper */ void initViewFlipper() { views = new ArrayList<View>(); ArrayList<Integer> imgs = getImageDate(); // 图片加载进viewFlipper for (int i = 0; i < imgs.size(); i++) { ImageView imageView = new ImageView(this); imageView.setImageResource(imgs.get(i)); imageView.setScaleType(ScaleType.FIT_XY); viewFlipper.addView(imageView, new LayoutParams( LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT)); views.add(imageView); } // 初始化小点点 initPoint(); } /** * 初始化headview */ void initHeadView() { /* * 实例化顶部布局 inflate(resource, root, * attachToRoot)有root,attachToRoot为false则返回需要添加的布局 * attachToRoot为true则返回添加布局到根布局后的整个新布局 */ headView = getLayoutInflater().inflate(R.layout.viewflipper, lv_main, false); // 顶部布局headview里的控件 viewFlipper = (MyViewFlipper) headView.findViewById(R.id.viewflipper); markView = (MarkView) headView.findViewById(R.id.markView); // headview里的viewFlipper初始化 initViewFlipper(); // 初始播放模式 viewFlipper.setInAnimation(lInAnim); viewFlipper.setOutAnimation(lOutAnim); // 设置自动播放功能(点击事件前自动播放) viewFlipper.setAutoStart(true); viewFlipper.setFlipInterval(3000); if (viewFlipper.isAutoStart() && !viewFlipper.isFlipping()) { viewFlipper.startFlipping(); } // 默认首次进入 markView.setMark(0); // viewFlipper设置监听事件 viewFlipper.setOnDisplayChangedListener(new OnDisplayChangedListener() { @Override public void OnDisplayChildChanging(ViewFlipper view, int index) { // 小点点跟随图片切换 markView.setMark(index); } }); lv_main.addHeaderView(headView, null, false); } /** * 初始化moreview */ void initMoreView() { // 实例化底部布局 moreView = getLayoutInflater().inflate(R.layout.moredata, lv_main, false); // 底部布局moreview里的控件 btn = (Button) moreView.findViewById(R.id.btn_load); pgb = (ProgressBar) moreView.findViewById(R.id.pgb_load); 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); } }); lv_main.addFooterView(moreView); } /** * listview添加headView并初始化 */ void initListView() { lv_main = (MyListView) findViewById(R.id.lv_main); // 射入手势 lv_main.setGestureDetector(detector); // 设置点击事件 lv_main.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position != 0) { Toast.makeText(MainActivity.this, "第" + (position - 1) + "条", 0).show(); } else { int index = getPageIndex(viewFlipper.getCurrentView()); } } }); // 设置长点击事件 lv_main.setOnItemLongClickListener(new OnItemLongClickListener() { @Override public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) { if (position != 0) { Toast.makeText(MainActivity.this, "onItemLongClick" + "文字" + (position - 1), 0) .show(); } else { int index = getPageIndex(viewFlipper.getCurrentView()); } /** * 如果返回true,则表示该事件已被消耗,则手松开不会在执行onClick事件。 * 如果返回false则光标还在,手松开会执行onClick事件。 */ return true; } }); // 设置添加长按菜单 lv_main.setOnCreateContextMenuListener(new OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { } }); // 初始化headview initHeadView(); // 射入viewflipper lv_main.setViewFlipper(viewFlipper); // 初始化moreview initMoreView(); // 设置分隔符(画在列表中每个项目之间)的高度 lv_main.setDividerHeight(2); } /** * 定义viewflipper动画切换模式 */ void initAnimation() { // 从左向右滑动(左进右出) 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); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); detector = new GestureDetector(this); handler = new Handler(); // 定义viewflipper动画切换模式 initAnimation(); // 获取viewflipper图片资源 getImageDate(); // 初始化listView initListView(); // 设置ListView的最大数据数目 MaxDateNum = 35; // 设置listview适配器 setListViewAdapter(); // listView绑定适配器 lv_main.setAdapter(mSimpleAdapter); // 绑定listview的滑动监听器 lv_main.setOnScrollListener(this); } /** * 加载更多数据 */ private void loadMoreDate() { int count = mSimpleAdapter.getCount(); if (count + 5 < MaxDateNum) { // 每次加载5条 for (int i = count; i < count + 5; 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); } } } /** * 返回当前第几屏 */ private int getPageIndex(View view) { for (int i = 0; i < views.size(); i++) { if (view == views.get(i)) return i; } return 0; } @Override /** * listview点击事件 */ public boolean onTouchEvent(MotionEvent event) { return super.onTouchEvent(event); } @Override // 用户轻触触摸屏 public boolean onDown(MotionEvent e) { return false; } @Override /** * 执行图片单击,用户(轻触触摸屏后)松开 */ public boolean onSingleTapUp(MotionEvent e) { int index = getPageIndex(viewFlipper.getCurrentView()); Toast.makeText(MainActivity.this, "图" + index + "单击", 0).show(); // 单击切换下一个 viewFlipper.showNext(); return false; } @Override // 用户按下触摸屏,并拖动 public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { return false; } @Override public boolean dispatchTouchEvent(MotionEvent ev) { return super.dispatchTouchEvent(ev); } @Override /** * 执行图片长按,用户长按触摸屏 */ public void onLongPress(MotionEvent e) { int index = getPageIndex(viewFlipper.getCurrentView()); Toast.makeText(MainActivity.this, "图" + index + "长按", 0).show(); viewFlipper.stopFlipping(); viewFlipper.setAutoStart(false); } @Override // 用户轻触触摸屏,尚未松开或拖动 public void onShowPress(MotionEvent e) { } /** * 监听viewflipper滑动过程 */ @Override // 用户按下触摸屏、快速移动后松开 public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { try { 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(); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } return true; } /** * 监听listview滑动状态 */ @Override public void onScrollStateChanged(AbsListView view, int scrollState) { if (scrollState == 1) { // listView还在滑动 } // 滑到底部后自动加载,判断listview已经停止滚动并且最后可视的条目等于adapter的条目 if (scrollState == OnScrollListener.SCROLL_STATE_IDLE && lastVisibleIndex == (mSimpleAdapter.getCount() - 1)) { // 当滑到底部时自动加载 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 (scrollState == OnScrollListener.SCROLL_STATE_IDLE) { if (lastVisibleIndex == MaxDateNum) { Toast.makeText(this, "数据全部加载完成", Toast.LENGTH_SHORT).show(); } } else { } } /** * listview滑动过程 */ @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // 计算最后可见条目的索引 lastVisibleIndex = firstVisibleItem + visibleItemCount - 3; // 所有的条目已经和最大条数相等,则移除底部的View if (totalItemCount == MaxDateNum + 2) { lv_main.removeFooterView(moreView); MaxDateNum -= 1; } } }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); p.setMargins(10, 0, 10, 0); 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); } } } }MyListView.java
package com.example.hdu; import android.content.Context; import android.util.AttributeSet; import android.view.GestureDetector; import android.view.MotionEvent; import android.widget.ListView; import android.widget.ViewFlipper; public class MyListView extends ListView { private GestureDetector gestureDetector; private ViewFlipper viewFlipper; private Context mContext; public void setGestureDetector(GestureDetector gestureDetector) { this.gestureDetector = gestureDetector; } public void setViewFlipper(ViewFlipper viewFlipper) { this.viewFlipper = viewFlipper; } public MyListView(Context context) { super(context); this.mContext = context; } public MyListView(Context context, AttributeSet attrs) { super(context, attrs); this.mContext = context; } @Override public boolean onTouchEvent(MotionEvent ev) { viewFlipper.setFlipInterval(3000); viewFlipper.setAutoStart(true); // 此处ev代表listview传进来的手势动作的方法,只有按下,移动,松开是那种状态 int x = (int) ev.getX(); int y = (int) ev.getY(); // ev里面包含触屏时的位置转换为listview的下标 int position = pointToPosition(x, y); // 只有headview == 0才进行手势操作 if (position == 0) { if (ev.getAction() == MotionEvent.ACTION_UP) { if (viewFlipper.isAutoStart() && !viewFlipper.isFlipping()) { viewFlipper.startFlipping(); } } else { viewFlipper.stopFlipping(); viewFlipper.setAutoStart(false); } // 通过listview点击到headview时注入手势,监控headview里面的手势操作 // 可以返回你之前手指滑动方向,返回到onFling()方法 gestureDetector.onTouchEvent(ev); } //解决当手按住图片拖动到headview以外区域无法执行抬手自动播放操作 if(ev.getAction() == MotionEvent.ACTION_UP) { if (viewFlipper.isAutoStart() && !viewFlipper.isFlipping()) { viewFlipper.startFlipping(); } } return super.onTouchEvent(ev); } }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); } }Adapter.java
package com.example.hdu; import java.util.ArrayList; import java.util.HashMap; import com.example.hdu.R.layout; import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.BaseAdapter; import android.widget.TextView; public class Adapter extends BaseAdapter { Context mContext; ArrayList<HashMap<String, String>> mData; public Adapter(Context context, ArrayList<HashMap<String, String>> data) { mContext = context; mData = data; } @Override public int getCount() { // TODO Auto-generated method stub return mData.size(); } @Override public Object getItem(int position) { return null; } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { ViewHolder holder = null; if (convertView == null) { convertView = LayoutInflater.from(mContext).inflate(R.layout.item, null); holder = new ViewHolder(); holder.tvTitle = (TextView) convertView.findViewById(R.id.tv_title); holder.tvContent = (TextView) convertView .findViewById(R.id.tv_content); convertView.setTag(holder); }else{ holder = (ViewHolder) convertView.getTag(); } String content = mData.get(position).get("ItemText"); String title = mData.get(position).get("ItemTitle"); holder.tvContent.setText(content); holder.tvTitle.setText(title); return convertView; } class ViewHolder { TextView tvTitle; TextView tvContent; } }