天天看點

QQ第三方登陸,上拉加載下拉重新整理XListView結合微信精選第三方分享加ImageLoad

//QQ第三方登陸,上拉加載下拉重新整理XListView結合微信精選第三方分享加ImageLoad

*******************抱歉的是有亂碼,還請見諒,開始建項目的時候要把GBK改成UTF-8就可以了*************

    ***********************配置XLIstView的string.xml檔案***************************

<string name="xlistview_header_hint_normal">下拉重新整理</string>
    <string name="xlistview_header_hint_ready">松開重新整理資料</string>
    <string name="xlistview_header_hint_loading">正在加載...</string>
    <string name="xlistview_header_last_time">上次更新時間:</string>
    <string name="xlistview_footer_hint_normal">檢視更多</string>
    <string name="xlistview_footer_hint_ready">松開載入更多</string>
           

*****************************配置第三方QQ登陸和分享********************************************

<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_LOGS" />
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
    <uses-permission android:name="android.permission.GET_TASKS" />
    <uses-permission android:name="android.permission.SET_DEBUG_APP" />
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
    <uses-permission android:name="android.permission.GET_ACCOUNTS" />
    <uses-permission android:name="android.permission.USE_CREDENTIALS" />
    <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.VIBRATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.WAKE_LOCK" />
    <uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
    <uses-permission android:name="android.permission.CAMERA" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.WRITE_SETTINGS" />
           
<activity
            android:name="com.tencent.tauth.AuthActivity"
            android:launchMode="singleTask"
            android:noHistory="true" >
            <intent-filter>
                <action android:name="android.intent.action.VIEW" />

                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />

                <data android:scheme="tencent100424468" />
            </intent-filter>
        </activity>
        <activity
            android:name="com.tencent.connect.common.AssistActivity"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent.NoTitleBar" />
        <activity
            android:name="com.umeng.socialize.editorpage.ShareActivity"
            android:excludeFromRecents="true"
            android:theme="@style/Theme.UMDefault" />

        <meta-data
            android:name="UMENG_APPKEY"
            android:value="4eaee02c527015373b000003" >
        </meta-data>
           

******************************Main函數中的全部代碼**************************************

import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.Map;
import java.util.Set;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
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.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.example.day17qq_weixin.WeiChatInfo.MyList;
import com.example.day17qq_weixin.view.XListView;
import com.example.day17qq_weixin.view.XListView.IXListViewListener;
import com.google.gson.Gson;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.umeng.socialize.ShareAction;
import com.umeng.socialize.UMAuthListener;
import com.umeng.socialize.UMShareAPI;
import com.umeng.socialize.UMShareListener;
import com.umeng.socialize.bean.SHARE_MEDIA;
import com.umeng.socialize.media.UMImage;

public class MainActivity extends Activity implements IXListViewListener{

	protected static final String TAG = "MainActivity";
	private UMShareAPI mShareAPI;
	protected static final int SUCEESS = 0;
	private XListView listView;
	private int index = 1;
	// 锟斤拷锟斤拷一锟斤拷锟斤拷锟斤拷
	private ArrayList<MyList> myList = new ArrayList<WeiChatInfo.MyList>();
	private MyBase myBase;
	Handler handler = new Handler() {

		public void handleMessage(android.os.Message msg) {
			if (msg.what == SUCEESS) {
				progressDialog.dismiss();
				WeiChatInfo chatInfo = (WeiChatInfo) msg.obj;
				// 展示锟斤拷listView锟較憋拷 锟斤拷莩曬锟�
				if (chatInfo.error_code == 0) {
					myList.addAll(chatInfo.result.list);
					if (myBase == null) {
						myBase = new MyBase(MainActivity.this,
								myList);
						listView.setAdapter(myBase);
					} else {
						myBase.notifyDataSetChanged();
					}
				}
			}
		};
	};
	private ProgressDialog progressDialog;
	private UMImage image;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		mShareAPI = UMShareAPI.get(this);
		platform = SHARE_MEDIA.QQ;
		imageView = (ImageView) findViewById(R.id.imageView);
		tv_name = (TextView) findViewById(R.id.tv_name);
	    listView = (XListView) findViewById(R.id.listView);
		listView.setPullLoadEnable(true);
		listView.setXListViewListener(this);
		
		
		initOptions = ImageLoaderUtils.initOptions();
		//AppKey锟斤拷654d512d807e422acc4e46a8e41af709
		image = new UMImage(this,
                BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher));
		
		listView.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				int lastVisiblePosition = view.getLastVisiblePosition();
				if (scrollState == OnScrollListener.SCROLL_STATE_IDLE
						&& lastVisiblePosition == myList.size() - 1) {
					// 锟斤拷锟斤拷锟斤拷锟�
					index++;
					getData();
					
				}
			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem,
					int visibleItemCount, int totalItemCount) {

			}
		});
		listView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
					long arg3) {
				// TODO Auto-generated method stub
				Intent intent = new Intent(MainActivity.this, ShowActivity.class);
				intent.putExtra("url", myList.get(arg2-1).url);
				startActivity(intent);
				
			}
		});
		//長按監聽
		listView.setOnItemLongClickListener(new OnItemLongClickListener() {

			private UMShareListener umShareListener;

			@Override
			public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
					int arg2, long arg3) {
				// TODO Auto-generated method stub
			
				//分享
				final SHARE_MEDIA[] displaylist = new SHARE_MEDIA[]
		                {
		                    SHARE_MEDIA.WEIXIN, SHARE_MEDIA.WEIXIN_CIRCLE,SHARE_MEDIA.SINA,
		                    SHARE_MEDIA.QQ, SHARE_MEDIA.QZONE,SHARE_MEDIA.DOUBAN
		                };
		        new ShareAction(MainActivity.this).setDisplayList( displaylist )
		                .withText( "锟角猴拷" )
		                .withTitle("title")
		                .withTargetUrl(myList.get(arg2).url)
		                .withMedia( image )
		                .setListenerList(umShareListener)
		                .open();

//		        new ShareAction(MainActivity.this)
//		        .setPlatform(SHARE_MEDIA.SINA)
//		        .setCallback(umShareListener)
//		        .withText("hello umeng video")
//		        .withTargetUrl("http://www.baidu.com")
//		        .withMedia(image)
//		        .share();
		        umShareListener=new UMShareListener() {
		            @Override
		            public void onResult(SHARE_MEDIA platform) {
		                Toast.makeText(MainActivity.this,platform + "分享成功啦", Toast.LENGTH_SHORT).show();
		            }

		            @Override
		            public void onError(SHARE_MEDIA platform, Throwable t) {
		                Toast.makeText(MainActivity.this,platform + " 分享失敗啦", Toast.LENGTH_SHORT).show();
		            }

		            @Override
		            public void onCancel(SHARE_MEDIA platform) {
		                Toast.makeText(MainActivity.this,platform + " 分享取消了", Toast.LENGTH_SHORT).show();
		            }
		        };
				return true;
			}
		});

		getData();
	}

	protected void getData() {
		// TODO Auto-generated method stub
		progressDialog = new ProgressDialog(this);
		progressDialog.setTitle("正在努力加載中...");
		progressDialog.show();
		new Thread() {
			public void run() {
				try {
					// http://v.juhe.cn/weixin/query?key=锟斤拷锟斤拷锟斤拷锟終EY
					// 0917c812f187b92e025c9b7c2d4e59b5 pno
					String path = "http://v.juhe.cn/weixin/query?key=518bccce2abaeb7f08101e47ed5f5891&pno="
							+ index;
					URL url = new URL(path);
					HttpURLConnection openConnection = (HttpURLConnection) url
							.openConnection();
					openConnection.setConnectTimeout(5000);
					openConnection.setReadTimeout(5000);
					int responseCode = openConnection.getResponseCode();
					if (responseCode == 200) {
						InputStream inputStream = openConnection
								.getInputStream();
						String parseSteam = StreamUtils.parseSteam(inputStream);
						Gson gson = new Gson();
						WeiChatInfo weiChatInfo = gson.fromJson(parseSteam,
								WeiChatInfo.class);
						// 發送消息
						handler.obtainMessage(SUCEESS, weiChatInfo)
								.sendToTarget();
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			};
		}.start();
	}

	public void login(View v) {
		mShareAPI.doOauthVerify(this, platform, umAuthListener);
	}

	public void sinaLogin(View v) {
		mShareAPI = UMShareAPI.get(this);
		SHARE_MEDIA platform = SHARE_MEDIA.SINA;
		// 锟餃詫拷去锟斤拷取平台锟斤拷息
		mShareAPI.doOauthVerify(this, platform, umAuthListener);
	}

	private boolean flag = true;

	private UMAuthListener umAuthListener = new UMAuthListener() {
		@Override
		public void onComplete(SHARE_MEDIA platform, int action,
				Map<String, String> data) {
			Toast.makeText(getApplicationContext(), "Authorize succeed",
					Toast.LENGTH_SHORT).show();
			// 锟叫斷碉拷前锟斤拷牽锟斤拷锟斤拷锟斤拷true锟斤拷锟酵斤拷锟叫碉拷锟斤拷..
			if (flag) {
				mShareAPI.getPlatformInfo(MainActivity.this, platform,
						umAuthListener);
				flag = false;
			}
			if (action == 2) {
				Set<String> keySet = data.keySet();
				for (String key : keySet) {
					String value = data.get(key);
					System.out.println("key-----" + key
							+ "value-----" + value);
					// Toast.makeText(getActivity(), "key-----" +
					// key + "value-----" + value, 0).show();
				}
				try {
					String names = data.get("screen_name")
							.toString();
					String image = data.get("profile_image_url")
							.toString();
					if (image.equals(null) || image.equals("")) {
						Toast.makeText(MainActivity.this, "锟斤拷取圖檔失锟傑o拷", 0)
								.show();
						return;
					}
				ImageLoader.getInstance().displayImage(image, imageView,initOptions);
				tv_name.setText(names);
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
			

		}

		@Override
		public void onError(SHARE_MEDIA platform, int action, Throwable t) {
			Toast.makeText(getApplicationContext(), "Authorize fail",
					Toast.LENGTH_SHORT).show();
		}

		@Override
		public void onCancel(SHARE_MEDIA platform, int action) {
			Toast.makeText(getApplicationContext(), "Authorize cancel",
					Toast.LENGTH_SHORT).show();
		}
	};
	private SHARE_MEDIA platform;
	private ImageView imageView;
	private TextView tv_name;
	private DisplayImageOptions initOptions;

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (mShareAPI != null)
			mShareAPI.onActivityResult(requestCode, resultCode, data);
		 UMShareAPI.get( this ).onActivityResult( requestCode, resultCode, data);
//			mShareAPI.onActivityResult(requestCode, resultCode, data);
	}

	@Override
	public void onRefresh() {
		// TODO Auto-generated method stub
		myList.clear();
		getData();
		onLoad();
		myBase.notifyDataSetChanged();
	}


	private void onLoad() {
		// TODO Auto-generated method stub
		listView.stopRefresh();
		listView.stopLoadMore();
		listView.setRefreshTime("剛剛");
	}

	@Override
	public void onLoadMore() {
		// TODO Auto-generated method stub
		myList.clear();
		getData();
		onLoad();
		myBase.notifyDataSetChanged();
	}
}
           

*****************************ImageLoaderUtils工具類*******************************

public static void initConfiguration(Context context) {
	 Builder builder = new ImageLoaderConfiguration.Builder(context);
		ImageLoader.getInstance().init(builder.build());
	}

	public static DisplayImageOptions initOptions() {
		DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder()
				.showImageOnLoading(R.drawable.ic_launcher)
				.showImageForEmptyUri(R.drawable.ic_launcher)
				.cacheInMemory(true).cacheOnDisk(true).build();
		return displayImageOptions;
	}
           

*************************************MyApplication*************************************

public class MyApplication extends Application {
	@Override
	public void onCreate() {
		// TODO Auto-generated method stub
		super.onCreate();
		PlatformConfig.setQQZone("100424468", "c7394704798a158208a74ab60104f0ba"); 
		//��ʼ������
				ImageLoaderUtils.initConfiguration(getApplicationContext());
		//http://v.juhe.cn/weixin/query?key=518bccce2abaeb7f08101e47ed5f5891

	}

}
           

*****************************************MyBaseAdapter擴充卡*****************************************

public class MyBase extends BaseAdapter {

	private MainActivity context;
	private ArrayList<MyList> list;
	private DisplayImageOptions initOptions;

	public MyBase(MainActivity mainActivity, ArrayList<MyList> list) {
		this.context = mainActivity;
		this.list = list;
		initOptions = ImageLoaderUtils.initOptions();
	}
	@Override
	public int getCount() {
		// TODO Auto-generated method stub
		return list.size();
	}

	@Override
	public Object getItem(int arg0) {
		// TODO Auto-generated method stub
		return list.get(arg0);
	}

	@Override
	public long getItemId(int arg0) {
		// TODO Auto-generated method stub
		return arg0;
	}

	@Override
	public View getView(int arg0, View arg1, ViewGroup arg2) {
		// TODO Auto-generated method stub
		View view = View.inflate(context, R.layout.list_item, null);
		ImageView iv_image = (ImageView) view.findViewById(R.id.iv_image);
		TextView tv_title = (TextView) view.findViewById(R.id.tv_title);
		tv_title.setText(list.get(arg0).title);
//		// ʵ��bitmapUtils
//		BitmapUtils bitmapUtils = new BitmapUtils(context);
//		// ��ͼƬ��ַ�����ͼƬչʾ���ؼ���
//		bitmapUtils.display(iv_image, list.get(arg0).firstImg);
		ImageLoader.getInstance().displayImage(list.get(arg0).firstImg, iv_image, initOptions);
		return view;
	}

}
           

******************************StreamUitls網絡擷取工具類**********************************

public class StreamUtils {
	public static String parseSteam(InputStream inputStream) {
		try {
			// ����һ���ֽ����������
			ByteArrayOutputStream arrayOutputStream = new ByteArrayOutputStream();
			// ����һ���ֽ�����
			byte[] buffer = new byte[1024];
			// �����ʼ����
			int len = 0;
			while ((len = inputStream.read(buffer)) != -1) {
				// ���������ݣ�д���ֽ������������
				arrayOutputStream.write(buffer, 0, len);
			}
			// ���ֽ������ת���ַ�
			return arrayOutputStream.toString("utf-8");
			// utf-8 ��Сд�����ԣ�gbk �����д
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}
}
           

**********************************微信精選的Bean類******************************

public class WeiChatInfo {
	public int error_code;
	public String reason;
	public WeiChatResult result;

	public class WeiChatResult {
		public int pno;
		public int ps;
		public int totalPage;
		public ArrayList<MyList> list;

	}
	public class MyList{
		public String firstImg;
		public String id;
		public String mark;
		public String title;
		public String source;
		public String url;
	}
}
           

******************************把QQ第三方登陸的所有的包和檔案導入dome******************************

******************************把XListView的三個工具類導入項目****************************************

*******************************XListView工具類******************************

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.TextView;

import com.example.day17qq_weixin.R;

public class XListView extends ListView implements OnScrollListener {

	private float mLastY = -1; // save event y
	private Scroller mScroller; // used for scroll back
	private OnScrollListener mScrollListener; // user's scroll listener

	// the interface to trigger refresh and load more.
	private IXListViewListener mListViewListener;
	// -- header view
	private XListViewHeader mHeaderView;
	// header view content, use it to calculate the Header's height. And hide it
	// when disable pull refresh.
	private RelativeLayout mHeaderViewContent;
	private TextView mHeaderTimeView;
	private int mHeaderViewHeight; // header view's height
	private boolean mEnablePullRefresh = true;
	private boolean mPullRefreshing = false; // is refreashing.

	// -- footer view
	private XListViewFooter mFooterView;
	private boolean mEnablePullLoad;
	private boolean mPullLoading;
	private boolean mIsFooterReady = false;

	// total list items, used to detect is at the bottom of listview.
	private int mTotalItemCount;

	// for mScroller, scroll back from header or footer.
	private int mScrollBack;
	private final static int SCROLLBACK_HEADER = 0;
	private final static int SCROLLBACK_FOOTER = 1;

	private final static int SCROLL_DURATION = 400; // scroll back duration
	private final static int PULL_LOAD_MORE_DELTA = 50; // when pull up >= 50px
														// at bottom, trigger
														// load more.
	private final static float OFFSET_RADIO = 1.8f; // support iOS like pull
													// feature.

	/**
	 * @param context
	 */
	public XListView(Context context) {
		super(context);
		initWithContext(context);
	}

	public XListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		initWithContext(context);
	}

	public XListView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initWithContext(context);
	}

	private void initWithContext(Context context) {
		mScroller = new Scroller(context, new DecelerateInterpolator());
		// XListView need the scroll event, and it will dispatch the event to
		// user's listener (as a proxy).
		super.setOnScrollListener(this);

		// init header view
		mHeaderView = new XListViewHeader(context);
		mHeaderViewContent = (RelativeLayout) mHeaderView
				.findViewById(R.id.xlistview_header_content);
		mHeaderTimeView = (TextView) mHeaderView
				.findViewById(R.id.xlistview_header_time);
		addHeaderView(mHeaderView);

		// init footer view
		mFooterView = new XListViewFooter(context);

		// init header height
		mHeaderView.getViewTreeObserver().addOnGlobalLayoutListener(
				new OnGlobalLayoutListener() {
					@Override
					public void onGlobalLayout() {
						mHeaderViewHeight = mHeaderViewContent.getHeight();
						getViewTreeObserver()
								.removeGlobalOnLayoutListener(this);
					}
				});
	}

	@Override
	public void setAdapter(ListAdapter adapter) {
		// make sure XListViewFooter is the last footer view, and only add once.
		if (mIsFooterReady == false) {
			mIsFooterReady = true;
			addFooterView(mFooterView);
		}
		super.setAdapter(adapter);
	}

	/**
	 * enable or disable pull down refresh feature.
	 * 
	 * @param enable
	 */
	public void setPullRefreshEnable(boolean enable) {
		mEnablePullRefresh = enable;
		if (!mEnablePullRefresh) { // disable, hide the content
			mHeaderViewContent.setVisibility(View.INVISIBLE);
		} else {
			mHeaderViewContent.setVisibility(View.VISIBLE);
		}
	}

	/**
	 * enable or disable pull up load more feature.
	 * 
	 * @param enable
	 */
	public void setPullLoadEnable(boolean enable) {
		mEnablePullLoad = enable;
		if (!mEnablePullLoad) {
			mFooterView.hide();
			mFooterView.setOnClickListener(null);
			// make sure "pull up" don't show a line in bottom when listview
			// with one page
			setFooterDividersEnabled(false);
		} else {
			mPullLoading = false;
			mFooterView.show();
			mFooterView.setState(XListViewFooter.STATE_NORMAL);
			// make sure "pull up" don't show a line in bottom when listview
			// with one page
			setFooterDividersEnabled(true);
			// both "pull up" and "click" will invoke load more.
			mFooterView.setOnClickListener(new OnClickListener() {
				@Override
				public void onClick(View v) {
					startLoadMore();
				}
			});
		}
	}

	/**
	 * stop refresh, reset header view.
	 */
	public void stopRefresh() {
		if (mPullRefreshing == true) {
			mPullRefreshing = false;
			resetHeaderHeight();
		}
	}

	/**
	 * stop load more, reset footer view.
	 */
	public void stopLoadMore() {
		if (mPullLoading == true) {
			mPullLoading = false;
			mFooterView.setState(XListViewFooter.STATE_NORMAL);
		}
	}

	/**
	 * set last refresh time
	 * 
	 * @param time
	 */
	public void setRefreshTime(String time) {
		mHeaderTimeView.setText(time);
	}

	private void invokeOnScrolling() {
		if (mScrollListener instanceof OnXScrollListener) {
			OnXScrollListener l = (OnXScrollListener) mScrollListener;
			l.onXScrolling(this);
		}
	}

	private void updateHeaderHeight(float delta) {
		mHeaderView.setVisiableHeight((int) delta
				+ mHeaderView.getVisiableHeight());
		if (mEnablePullRefresh && !mPullRefreshing) { // 未處于重新整理狀态,更新箭頭
			if (mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
				mHeaderView.setState(XListViewHeader.STATE_READY);
			} else {
				mHeaderView.setState(XListViewHeader.STATE_NORMAL);
			}
		}
		setSelection(0); // scroll to top each time
	}

	/**
	 * reset header view's height.
	 */
	private void resetHeaderHeight() {
		int height = mHeaderView.getVisiableHeight();
		if (height == 0) // not visible.
			return;
		// refreshing and header isn't shown fully. do nothing.
		if (mPullRefreshing && height <= mHeaderViewHeight) {
			return;
		}
		int finalHeight = 0; // default: scroll back to dismiss header.
		// is refreshing, just scroll back to show all the header.
		if (mPullRefreshing && height > mHeaderViewHeight) {
			finalHeight = mHeaderViewHeight;
		}
		mScrollBack = SCROLLBACK_HEADER;
		mScroller.startScroll(0, height, 0, finalHeight - height,
				SCROLL_DURATION);
		// trigger computeScroll
		invalidate();
	}

	private void updateFooterHeight(float delta) {
		int height = mFooterView.getBottomMargin() + (int) delta;
		if (mEnablePullLoad && !mPullLoading) {
			if (height > PULL_LOAD_MORE_DELTA) { // height enough to invoke load
				mFooterView.setState(XListViewFooter.STATE_READY);
			} else {
				mFooterView.setState(XListViewFooter.STATE_NORMAL);
			}
		}
		mFooterView.setBottomMargin(height);

		// setSelection(mTotalItemCount - 1); // scroll to bottom
	}

	private void resetFooterHeight() {
		int bottomMargin = mFooterView.getBottomMargin();
		if (bottomMargin > 0) {
			mScrollBack = SCROLLBACK_FOOTER;
			mScroller.startScroll(0, bottomMargin, 0, -bottomMargin,
					SCROLL_DURATION);
			invalidate();
		}
	}

	private void startLoadMore() {
		mPullLoading = true;
		mFooterView.setState(XListViewFooter.STATE_LOADING);
		if (mListViewListener != null) {
			mListViewListener.onLoadMore();
		}
	}

	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		if (mLastY == -1) {
			mLastY = ev.getRawY();
		}
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			mLastY = ev.getRawY();
			break;
		case MotionEvent.ACTION_MOVE:
			final float deltaY = ev.getRawY() - mLastY;
			mLastY = ev.getRawY();
			if (getFirstVisiblePosition() == 0
					&& (mHeaderView.getVisiableHeight() > 0 || deltaY > 0)) {
				// the first item is showing, header has shown or pull down.
				updateHeaderHeight(deltaY / OFFSET_RADIO);
				invokeOnScrolling();
			} else if (getLastVisiblePosition() == mTotalItemCount - 1
					&& (mFooterView.getBottomMargin() > 0 || deltaY < 0)) {
				// last item, already pulled up or want to pull up.
				updateFooterHeight(-deltaY / OFFSET_RADIO);
			}
			break;
		case MotionEvent.ACTION_CANCEL:
		case MotionEvent.ACTION_UP:
			mLastY = -1; // reset
			if (getFirstVisiblePosition() == 0) {
				// invoke refresh
				if (mEnablePullRefresh
						&& mHeaderView.getVisiableHeight() > mHeaderViewHeight) {
					mPullRefreshing = true;
					mHeaderView.setState(XListViewHeader.STATE_REFRESHING);
					if (mListViewListener != null) {
						mListViewListener.onRefresh();
					}
				}
				resetHeaderHeight();
				
			} else if (getLastVisiblePosition() == mTotalItemCount - 1) {
				// invoke load more.
				if (mEnablePullLoad
						&& mFooterView.getBottomMargin() > PULL_LOAD_MORE_DELTA
						&& !mPullLoading) {
					startLoadMore();
				}
				resetFooterHeight();
			}
			break;
		}
		return super.onTouchEvent(ev);
	}

	@Override
	public void computeScroll() {
		if (mScroller.computeScrollOffset()) {
			if (mScrollBack == SCROLLBACK_HEADER) {
				mHeaderView.setVisiableHeight(mScroller.getCurrY());
			} else {
				mFooterView.setBottomMargin(mScroller.getCurrY());
			}
			postInvalidate();
			invokeOnScrolling();
		}
		super.computeScroll();
	}

	@Override
	public void setOnScrollListener(OnScrollListener l) {
		mScrollListener = l;
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		if (mScrollListener != null) {
			mScrollListener.onScrollStateChanged(view, scrollState);
		}
	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		// send to user's listener
		mTotalItemCount = totalItemCount;
		if (mScrollListener != null) {
			mScrollListener.onScroll(view, firstVisibleItem, visibleItemCount,
					totalItemCount);
		}
	}

	public void setXListViewListener(IXListViewListener l) {
		mListViewListener = l;
	}

	/**
	 * you can listen ListView.OnScrollListener or this one. it will invoke
	 * onXScrolling when header/footer scroll back.
	 */
	public interface OnXScrollListener extends OnScrollListener {
		public void onXScrolling(View view);
	}

	/**
	 * implements this interface to get refresh/load more event.
	 */
	public interface IXListViewListener {
		public void onRefresh();

		public void onLoadMore();
	}
}
           

*******************************XListViewFooter工具類******************************

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.example.day17qq_weixin.R;

public class XListViewFooter extends LinearLayout {
	public final static int STATE_NORMAL = 0;
	public final static int STATE_READY = 1;
	public final static int STATE_LOADING = 2;

	private Context mContext;

	private View mContentView;
	private View mProgressBar;
	private TextView mHintView;
	
	public XListViewFooter(Context context) {
		super(context);
		initView(context);
	}
	
	public XListViewFooter(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
	}

	
	public void setState(int state) {
		mHintView.setVisibility(View.INVISIBLE);
		mProgressBar.setVisibility(View.INVISIBLE);
		mHintView.setVisibility(View.INVISIBLE);
		if (state == STATE_READY) {
			mHintView.setVisibility(View.VISIBLE);
			mHintView.setText(R.string.xlistview_footer_hint_ready);
		} else if (state == STATE_LOADING) {
			mProgressBar.setVisibility(View.VISIBLE);
		} else {
			mHintView.setVisibility(View.VISIBLE);
			mHintView.setText(R.string.xlistview_footer_hint_normal);
		}
	}
	
	public void setBottomMargin(int height) {
		if (height < 0) return ;
		LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
		lp.bottomMargin = height;
		mContentView.setLayoutParams(lp);
	}
	
	public int getBottomMargin() {
		LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
		return lp.bottomMargin;
	}
	
	
	/**
	 * normal status
	 */
	public void normal() {
		mHintView.setVisibility(View.VISIBLE);
		mProgressBar.setVisibility(View.GONE);
	}
	
	
	/**
	 * loading status 
	 */
	public void loading() {
		mHintView.setVisibility(View.GONE);
		mProgressBar.setVisibility(View.VISIBLE);
	}
	
	/**
	 * hide footer when disable pull load more
	 */
	public void hide() {
		LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
		lp.height = 0;
		mContentView.setLayoutParams(lp);
	}
	
	/**
	 * show footer
	 */
	public void show() {
		LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)mContentView.getLayoutParams();
		lp.height = LayoutParams.WRAP_CONTENT;
		mContentView.setLayoutParams(lp);
	}
	
	private void initView(Context context) {
		mContext = context;
		LinearLayout moreView = (LinearLayout)LayoutInflater.from(mContext).inflate(R.layout.xlistview_footer, null);
		addView(moreView);
		moreView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
		
		mContentView = moreView.findViewById(R.id.xlistview_footer_content);
		mProgressBar = moreView.findViewById(R.id.xlistview_footer_progressbar);
		mHintView = (TextView)moreView.findViewById(R.id.xlistview_footer_hint_textview);
	}
	
	
}
           

*******************************XListViewHeader工具類******************************

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.example.day17qq_weixin.R;

public class XListViewHeader extends LinearLayout {
	private LinearLayout mContainer;
	private ImageView mArrowImageView;
	private ProgressBar mProgressBar;
	private TextView mHintTextView;
	private int mState = STATE_NORMAL;

	private Animation mRotateUpAnim;
	private Animation mRotateDownAnim;

	private final int ROTATE_ANIM_DURATION = 180;

	public final static int STATE_NORMAL = 0;
	public final static int STATE_READY = 1;
	public final static int STATE_REFRESHING = 2;

	public XListViewHeader(Context context) {
		super(context);
		initView(context);
	}

	/**
	 * @param context
	 * @param attrs
	 */
	public XListViewHeader(Context context, AttributeSet attrs) {
		super(context, attrs);
		initView(context);
	}

	private void initView(Context context) {
		// 初始情況,設定下拉重新整理view高度為0
		LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
				LayoutParams.FILL_PARENT, 0);
		// 将下拉重新整理的view添加進來
		mContainer = (LinearLayout) LayoutInflater.from(context).inflate(
				R.layout.xlistview_header, null);
		addView(mContainer, lp);
		setGravity(Gravity.BOTTOM);

		mArrowImageView = (ImageView) findViewById(R.id.xlistview_header_arrow);
		mHintTextView = (TextView) findViewById(R.id.xlistview_header_hint_textview);
		mProgressBar = (ProgressBar) findViewById(R.id.xlistview_header_progressbar);
		// 準備向上和向下的動畫
		mRotateUpAnim = new RotateAnimation(0.0f, -180.0f,
				Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
				0.5f);
		// 設定旋轉時間間隔
		mRotateUpAnim.setDuration(ROTATE_ANIM_DURATION);
		mRotateUpAnim.setFillAfter(true);
		mRotateDownAnim = new RotateAnimation(-180.0f, 0.0f,
				Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
				0.5f);
		mRotateDownAnim.setDuration(ROTATE_ANIM_DURATION);
		mRotateDownAnim.setFillAfter(true);
	}

	public void setState(int state) {
		if (state == mState)
			return;
		// 如果目前狀态是正在重新整理
		if (state == STATE_REFRESHING) { // 顯示進度
			// 移除動畫
			mArrowImageView.clearAnimation();
			// 設定imageView不可見
			mArrowImageView.setVisibility(View.INVISIBLE);
			// 設定progressBar可見
			mProgressBar.setVisibility(View.VISIBLE);
		} else { // 顯示箭頭圖檔
			// 隻要不是正在重新整理,進度條可見,imageView不可見
			mArrowImageView.setVisibility(View.VISIBLE);
			mProgressBar.setVisibility(View.INVISIBLE);
		}

		switch (state) {
		case STATE_NORMAL:
			if (mState == STATE_READY) {
				mArrowImageView.startAnimation(mRotateDownAnim);
			}
			if (mState == STATE_REFRESHING) {
				mArrowImageView.clearAnimation();
			}
			mHintTextView.setText(R.string.xlistview_header_hint_normal);
			break;
		case STATE_READY:
			if (mState != STATE_READY) {
				mArrowImageView.clearAnimation();
				mArrowImageView.startAnimation(mRotateUpAnim);
				mHintTextView.setText(R.string.xlistview_header_hint_ready);
			}
			break;
		case STATE_REFRESHING:
			mHintTextView.setText(R.string.xlistview_header_hint_loading);
			break;
		default:
		}
		mState = state;
	}

	public void setVisiableHeight(int height) {
		if (height < 0)
			height = 0;
		LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContainer
				.getLayoutParams();
		lp.height = height;
		mContainer.setLayoutParams(lp);
	}

	public int getVisiableHeight() {
		return mContainer.getLayoutParams().height;
	}

}
           

***************************************activity_main.xml布局************************************

<RelativeLayout 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" >

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:src="@drawable/ic_launcher" />

    <TextView
        android:id="@+id/tv_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_marginTop="40dp"
        android:layout_toRightOf="@+id/imageView"
        android:text="使用者名"
        android:textColor="#ff00ff" />

    <Button
        android:id="@+id/login"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imageView"
        android:layout_alignParentRight="true"
        android:onClick="login"
        android:text="QQ登陸"
        android:textColor="#ff00ff" />

    <com.example.day17qq_weixin.view.XListView
        android:id="@+id/listView"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_below="@+id/imageView"
        android:layout_marginTop="17dp" >
    </com.example.day17qq_weixin.view.XListView>

</RelativeLayout>
           

*********************************ShowActivity詳情頁*************************************

public class ShowActivity extends Activity {

	private WebView webView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_show);
		
		webView = (WebView) findViewById(R.id.webView);
		// ������Ϊ�ͻ��˴��ڣ�������תֻ���Լ�Ӧ�ó�����
		Intent intent = getIntent();
		String string = intent.getStringExtra("url");
		webView.getSettings().setJavaScriptEnabled(true);
		webView.setWebViewClient(new WebViewClient());
		Toast.makeText(ShowActivity.this, "����Ŭ������...", 0).show();
		webView.loadUrl(string);
	}
}