Android模仿QQ的左右滑动切换界面和下拉更新的效果

转自http://www.linuxidc.com/Linux/2012-08/67207.htm

主布局main.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:Android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <HorizontalScrollView  
  8.         android:id="@+id/horizontalscrollview"  
  9.         android:layout_width="match_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:background="@drawable/item"  
  12.         android:fadingEdge="@null"  
  13.         android:scrollbars="none" >  
  14.   
  15.         <LinearLayout  
  16.             android:id="@+id/linearlayout"  
  17.             android:layout_width="match_parent"  
  18.             android:layout_height="match_parent"  
  19.             android:orientation="horizontal"  
  20.             >  
  21.         </LinearLayout>  
  22.     </HorizontalScrollView>  
  23.   
  24.     <android.support.v4.view.ViewPager  
  25.         android:id="@+id/viewpaper"  
  26.         android:layout_width="fill_parent"  
  27.         android:layout_height="match_parent"  
  28.         android:layout_weight="1" >  
  29.     </android.support.v4.view.ViewPager>  
  30.   
  31. </LinearLayout>  

2,接着看看QQonline.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical"   
  6.     android:background="@drawable/image2">  
  7.   
  8.       
  9. <ExpandableListView   
  10.     android:id="@+id/elistview"  
  11.     android:layout_width="fill_parent"   
  12.     android:layout_height="wrap_content"   
  13.     android:layout_marginLeft="5dp"  
  14.      
  15.       
  16.     />  
  17.   
  18. </LinearLayout>  

3.接着看看下拉更新的布局pullrefresh.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:background="@drawable/image1"  
  6.     android:orientation="vertical" >  
  7.   
  8.     <com.wang.pullrefresh.MyListView  
  9.         android:id="@+id/listView"  
  10.         android:layout_width="fill_parent"  
  11.         android:layout_height="fill_parent" />  
  12.   
  13.   
  14. </LinearLayout>  
4.下拉更新过程实现的布局refresh.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="wrap_content" >  
  5.   
  6.     <RelativeLayout  
  7.         android:id="@+id/head_contentLayout"  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:paddingLeft="30dp" >  
  11.   
  12.         <FrameLayout  
  13.             android:layout_width="wrap_content"  
  14.             android:layout_height="wrap_content"  
  15.             android:layout_alignParentLeft="true"  
  16.             android:layout_centerVertical="true" >  
  17.   
  18.             <ImageView  
  19.                 android:id="@+id/head_arrowImageView"  
  20.                 android:layout_width="wrap_content"  
  21.                 android:layout_height="wrap_content"  
  22.                 android:layout_gravity="center"  
  23.                 android:src="@drawable/down" />  
  24.   
  25.             <ProgressBar  
  26.                 android:id="@+id/head_progressBar"  
  27.                 style="?android:attr/progressBarStyleSmall"  
  28.                 android:layout_width="wrap_content"  
  29.                 android:layout_height="wrap_content"  
  30.                 android:layout_gravity="center"  
  31.                 android:visibility="gone" />  
  32.         </FrameLayout>  
  33.   
  34.         <LinearLayout  
  35.             android:layout_width="wrap_content"  
  36.             android:layout_height="wrap_content"  
  37.             android:layout_centerHorizontal="true"  
  38.             android:gravity="center_horizontal"  
  39.             android:orientation="vertical" >  
  40.   
  41.             <TextView  
  42.                 android:id="@+id/head_tipsTextView"  
  43.                 android:layout_width="wrap_content"  
  44.                 android:layout_height="wrap_content"  
  45.                 android:text="下拉可以刷新"  
  46.                 android:textSize="15dp" />  
  47.   
  48.             <TextView  
  49.                 android:id="@+id/head_lastUpdatedTextView"  
  50.                 android:layout_width="wrap_content"  
  51.                 android:layout_height="wrap_content"  
  52.                 android:text="上次更新时间:"  
  53.                 android:textSize="12dp" />  
  54.         </LinearLayout>  
  55.     </RelativeLayout>  
  56.   
  57. </LinearLayout>  
5.下拉更新的列表显示的布局list_item.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:gravity="center_vertical"  
  6.     android:orientation="horizontal" >  
  7.   
  8.     <ImageView  
  9.         android:id="@+id/imageView_item"  
  10.         android:layout_width="60dp"  
  11.         android:layout_height="60dp"  
  12.         android:layout_marginLeft="5dp"  
  13.         android:src="@drawable/qq" />  
  14.   
  15.     <TextView  
  16.         android:id="@+id/textView_item"  
  17.         android:layout_width="wrap_content"  
  18.         android:layout_height="wrap_content"  
  19.         android:layout_marginLeft="10dp"  
  20.         android:textColor="#FFFFFF"  
  21.         />  
  22.   
  23. </LinearLayout>  
6.接着看看还没有完善的QQ聊天信息的布局main3.xml
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical"   
  6.     android:background="@drawable/image3">  
  7.   
  8.        
  9.   
  10. </LinearLayout>  

7.接着看看主活动的实现过程ViewPaper1Activity.java

  1. package com.wang;  
  2.   
  3. import java.util.ArrayList;  
  4.   
  5. import android.app.ActivityGroup;  
  6. import android.content.Intent;  
  7. import android.graphics.Bitmap;  
  8. import android.graphics.BitmapFactory;  
  9. import android.graphics.drawable.BitmapDrawable;  
  10. import android.os.Bundle;  
  11. import android.support.v4.view.PagerAdapter;  
  12. import android.support.v4.view.ViewPager;  
  13. import android.support.v4.view.ViewPager.OnPageChangeListener;  
  14. import android.view.Gravity;  
  15. import android.view.View;  
  16. import android.view.Window;  
  17. import android.view.WindowManager;  
  18. import android.view.View.OnClickListener;  
  19. import android.widget.HorizontalScrollView;  
  20. import android.widget.LinearLayout;  
  21. import android.widget.RadioButton;  
  22. import android.widget.RadioGroup;  
  23. import android.widget.TextView;  
  24. import android.widget.LinearLayout.LayoutParams;  
  25.   
  26. public class ViewPaper1Activity extends ActivityGroup implements  
  27.         OnClickListener {  
  28.     private RadioGroup radioGroup;  
  29.   
  30.     private String array[] = { "QQ空间""QQ""QQ消息" };  
  31.     private LinearLayout linearLayout;  
  32.     private ArrayList<TextView> textViews;  
  33.     private ViewPager viewPager;  
  34.     private ArrayList<View> pageViews;  
  35.     private HorizontalScrollView horizontalScrollView;  
  36.   
  37.     /*** 
  38.      *初始化视图 
  39.      *  
  40.      *  
  41.      */  
  42.     void InItView() {  
  43.         // 构造一个新的ArrayList实例对象   
  44.         pageViews = new ArrayList<View>();  
  45.         /** 
  46.          *   开始一个新的活动中运行的组织。 每一个活动你开始必须有一个独一无二的字符串标识与其相关联 
  47.          * **/  
  48.         View view1 = getLocalActivityManager().startActivity("main1",  
  49.                 new Intent(this, pullrefreshtest.class)).getDecorView();  
  50.         View view2 = getLocalActivityManager().startActivity("main2",  
  51.                 new Intent(this, QQonline.class)).getDecorView();  
  52.         View view3 = getLocalActivityManager().startActivity("main3",  
  53.                 new Intent(this, main3.class)).getDecorView();  
  54.         // 添加指定的对象在文章末尾的ArrayList。   
  55.         pageViews.add(view1);  
  56.         pageViews.add(view2);  
  57.         pageViews.add(view3);  
  58.     }  
  59.   
  60.     /*** 
  61.      * 初始化话标题栏 
  62.      */  
  63.     void InItTitle() {  
  64.         // 获取窗口管理器显示自定义窗口,去掉默认显示对象。得到1/3屏幕宽度   
  65.         int width = getWindowManager().getDefaultDisplay().getWidth() / 3;  
  66.   
  67.         for (int i = 0; i < array.length; i++) {  
  68.             // 声明一个radioButton对象   
  69.             RadioButton radioButton = new RadioButton(thisnull);  
  70.             radioButton.setText(array[i]);  
  71.             radioButton.setWidth(width);  
  72.             radioButton.setHeight(70);  
  73.             // 集水平对齐文本和垂直重力的时候将会使用有额外的空间在TextView超出要求的文本本身   
  74.             radioButton.setGravity(Gravity.CENTER);  
  75.             // 添加子视图。如果没有布局参数对孩子已经设置,默认参数对于这个ViewGroup上设置的孩子。   
  76.             radioGroup.addView(radioButton);  
  77.         }  
  78.     }  
  79.   
  80.     /*** 
  81.      * 初始化文本 
  82.      */  
  83.     void initTextView() {  
  84.         // 声明一个ArrayList对象   
  85.         textViews = new ArrayList<TextView>();  
  86.         // 获取窗口管理器显示自定义窗口,去掉默认显示对象。得到1/3屏幕宽度   
  87.         int width = getWindowManager().getDefaultDisplay().getWidth() / 3;  
  88.         int height = 60;  
  89.         for (int i = 0; i < array.length; i++) {  
  90.             TextView textView = new TextView(this);  
  91.             textView.setText(array[i]);  
  92.             textView.setTextSize(17);  
  93.             textView.setWidth(width);  
  94.             textView.setHeight(height - 30);  
  95.             textView.setGravity(Gravity.CENTER);  
  96.             textView.setId(i);  
  97.             // 设置文本的监听事件   
  98.             textView.setOnClickListener(this);  
  99.             textViews.add(textView);  
  100.             LinearLayout.LayoutParams layoutParams = new LayoutParams(  
  101.                     LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);  
  102.             layoutParams.width = 1;  
  103.             layoutParams.height = height - 40;  
  104.             layoutParams.gravity = Gravity.CENTER;  
  105.             // 添加子视图。如果没有布局参数对孩子已经设置,默认参数对于这个ViewGroup上设置的孩子。   
  106.             linearLayout.addView(textView);  
  107.   
  108.         }  
  109.     }  
  110.   
  111.     /*** 
  112.      * 选中后的处理 
  113.      */  
  114.     public void select(int id) {  
  115.         for (int i = 0; i < array.length; i++) {  
  116.             if (id == i) {  
  117.                 // 得到图片的资源   
  118.                 Bitmap bitmap = BitmapFactory.decodeResource(getResources(),  
  119.                         R.drawable.itembg);  
  120.                 // 设置背景图   
  121.                 textViews.get(id).setBackgroundDrawable(  
  122.                         new BitmapDrawable(bitmap));  
  123.                 viewPager.setCurrentItem(i);  
  124.             }  
  125.   
  126.             else {  
  127.                 textViews.get(i).setBackgroundDrawable(new BitmapDrawable());  
  128.             }  
  129.         }  
  130.     }  
  131.   
  132.     @Override  
  133.     public void onCreate(Bundle savedInstanceState) {  
  134.         super.onCreate(savedInstanceState);  
  135.         // 去除标题栏   
  136.         this.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  137.         // 取消状态栏,充满全屏   
  138.         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  139.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  140.   
  141.         setContentView(R.layout.main);  
  142.         // 实例化组件   
  143.         linearLayout = (LinearLayout) findViewById(R.id.linearlayout);  
  144.         viewPager = (ViewPager) findViewById(R.id.viewpaper);  
  145.         horizontalScrollView = (HorizontalScrollView) findViewById(R.id.horizontalscrollview);  
  146.         // 调用方法实现   
  147.         initTextView();  
  148.         select(0);  
  149.         InItView();  
  150.   
  151.         viewPager.setAdapter(new PagerAdapter() {  
  152.             // 得到数目   
  153.             public int getCount() {  
  154.                 return pageViews.size();  
  155.             }  
  156.   
  157.             @Override  
  158.             public boolean isViewFromObject(View view, Object object) {  
  159.                 return view == object;  
  160.             }  
  161.   
  162.             @Override  
  163.             public int getItemPosition(Object object) {  
  164.                 // TODO Auto-generated method stub   
  165.                 return super.getItemPosition(object);  
  166.             }  
  167.   
  168.             @Override  
  169.             public void destroyItem(View view, int id, Object arg2) {  
  170.                 // TODO Auto-generated method stub   
  171.                 ((ViewPager) view).removeView(pageViews.get(id));  
  172.             }  
  173.   
  174.             // 获取每一个item的id   
  175.             @Override  
  176.             public Object instantiateItem(View view, int id) {  
  177.                 ((ViewPager) view).addView(pageViews.get(id));  
  178.                 return pageViews.get(id);  
  179.             }  
  180.   
  181.         });  
  182.         // 页面改变时候的监听事件   
  183.         viewPager.setOnPageChangeListener(new OnPageChangeListener() {  
  184.   
  185.             @Override  
  186.             public void onPageSelected(int arg0) {  
  187.                 select(arg0);  
  188.             }  
  189.   
  190.             @Override  
  191.             public void onPageScrolled(int arg0, float arg1, int arg2) {  
  192.   
  193.             }  
  194.   
  195.             @Override  
  196.             public void onPageScrollStateChanged(int arg0) {  
  197.   
  198.             }  
  199.         });  
  200.     }  
  201.   
  202.     @Override  
  203.     public void onClick(View v) {  
  204.         select(v.getId());  
  205.     }  
  206.   
  207. }  

8.接着看看QQonline.java 的实现

  1. package com.wang;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.view.ContextMenu;  
  6. import android.view.View;  
  7. import android.view.Window;  
  8. import android.view.WindowManager;  
  9. import android.view.ContextMenu.ContextMenuInfo;  
  10. import android.widget.ExpandableListAdapter;  
  11. import android.widget.ExpandableListView;  
  12. import android.widget.Toast;  
  13. import android.widget.ExpandableListView.OnChildClickListener;  
  14. import android.widget.ExpandableListView.OnGroupClickListener;  
  15. import android.widget.ExpandableListView.OnGroupCollapseListener;  
  16. import android.widget.ExpandableListView.OnGroupExpandListener;  
  17.   
  18. public class QQonline extends Activity {  
  19.     // 创建一个上下文菜单的方法   
  20.     public void onCreateContextMenu(ContextMenu menu, View v,  
  21.             ContextMenuInfo menuInfo) {  
  22.   
  23.         super.onCreateContextMenu(menu, v, menuInfo);  
  24.   
  25.         // 一个垂直滚动的两级列表。取得菜单项   
  26.         ExpandableListView.ExpandableListContextMenuInfo info = (ExpandableListView.ExpandableListContextMenuInfo) menuInfo;  
  27.         // 获得这个类型 的位置   
  28.         int type = ExpandableListView  
  29.                 .getPackedPositionType(info.packedPosition);  
  30.         // 取得所在组的索引   
  31.         int group = ExpandableListView  
  32.                 .getPackedPositionGroup(info.packedPosition);  
  33.         // 取得子菜单的索引   
  34.         int child = ExpandableListView  
  35.                 .getPackedPositionGroup(info.packedPosition);  
  36.   
  37.         Toast.makeText(QQonline.this,  
  38.                 "类型 =" + type + "  分组:" + group + "  子选项:" + child,  
  39.                 Toast.LENGTH_LONG).show();  
  40.   
  41.     }  
  42.   
  43.     private ExpandableListView eListView = null;  
  44.     private ExpandableListAdapter adapter = null;  
  45.   
  46.     @Override  
  47.     public void onCreate(Bundle savedInstanceState) {  
  48.   
  49.         // 去除标题,   
  50.         this.requestWindowFeature(Window.FEATURE_NO_TITLE);  
  51.         // 取消状态栏,充满全屏   
  52.         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  53.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  54.   
  55.         super.onCreate(savedInstanceState);  
  56.         super.setContentView(R.layout.qqonline);  
  57.   
  58.         // 实例化组件   
  59.         this.eListView = (ExpandableListView) findViewById(R.id.elistview);  
  60.   
  61.         // 声明一个adapter对象   
  62.         adapter = new myExpendableadapler(this);  
  63.         // 设置适配器提供了数据   
  64.         this.eListView.setAdapter(this.adapter);  
  65.   
  66.         //  注册一个上下文菜单显示给定的视图(多个视图可以显示上下文菜单)。   
  67.         super.registerForContextMenu(this.eListView);  
  68.   
  69.         // 设置点击时候触发的事件 1,子选项点击事件 2。父选项单击事件 3.分组打开事件 4.分组关闭事件   
  70.         this.eListView.setOnChildClickListener(new ChildClickListener());  
  71.         this.eListView.setOnGroupClickListener(new GroupClickListener());  
  72.         this.eListView.setOnGroupExpandListener(new GroupExpandListener());  
  73.         this.eListView.setOnGroupCollapseListener(new GroupCollapseListener());  
  74.   
  75.     }  
  76.   
  77.     // /1,子选项点击事件   
  78.     private class ChildClickListener implements OnChildClickListener {  
  79.   
  80.         public boolean onChildClick(ExpandableListView parent, View v,  
  81.                 int groupPosition, int childPosition, long id) {  
  82.             Toast  
  83.                     .makeText(  
  84.                             QQonline.this,  
  85.                             "子选项被选中,所的组:" + groupPosition + "  子选项的位置:"  
  86.                                     + childPosition, Toast.LENGTH_LONG).show();  
  87.             return false;  
  88.         }  
  89.   
  90.     }  
  91.   
  92.     // 2。父选项单击事件   
  93.     private class GroupClickListener implements OnGroupClickListener {  
  94.   
  95.         public boolean onGroupClick(ExpandableListView parent, View v,  
  96.                 int groupPosition, long id) {  
  97.             Toast.makeText(QQonline.this"分组选项被选中,所在组: " + groupPosition,  
  98.                     Toast.LENGTH_LONG).show();  
  99.             return false;  
  100.         }  
  101.   
  102.     }  
  103.   
  104.     // 3.分组打开事件   
  105.     private class GroupExpandListener implements OnGroupExpandListener {  
  106.   
  107.         public void onGroupExpand(int groupPosition) {  
  108.             // TODO Auto-generated method stub   
  109.             Toast.makeText(QQonline.this"打开分组,所在组:" + groupPosition,  
  110.                     Toast.LENGTH_LONG).show();  
  111.         }  
  112.   
  113.     }  
  114.   
  115.     // 4.分组关闭事件   
  116.     private class GroupCollapseListener implements OnGroupCollapseListener {  
  117.   
  118.         public void onGroupCollapse(int groupPosition) {  
  119.             Toast.makeText(QQonline.this"关闭分组,所在组:" + groupPosition,  
  120.                     Toast.LENGTH_LONG).show();  
  121.         }  
  122.   
  123.     }  
  124.   
  125. }  
9.接着需要myExpendableadapler.java
  1. package com.wang;  
  2.   
  3. import android.content.Context;  
  4. import android.view.Gravity;  
  5. import android.view.View;  
  6. import android.view.ViewGroup;  
  7. import android.widget.AbsListView;  
  8. import android.widget.BaseExpandableListAdapter;  
  9. import android.widget.TextView;  
  10.   
  11. public class myExpendableadapler extends BaseExpandableListAdapter {  
  12.     // 组名称   
  13.     private String[] group = new String[] { "在线好友""高中同学""南阳理工同学""寝室哥们" };  
  14.     // 子选项的名字   
  15.     private String[][] child = new String[][] {  
  16.             { "李彦宏""马云""雷军""周鸿祎""唐骏""赵威威""李冕""马海刚""李斌""刘洪刚",  
  17.                     "马玉龙""刘慧敏""王文龙" },  
  18.             { "赵威威""李冕""马海刚""李斌""刘洪刚""马玉龙""刘慧敏""王文龙" },  
  19.             { "张紫阳""王亚光""刘一鸣""崔芳芳""董卫杰""刘永乐" },  
  20.             { "武云册""王俊伟""王杰""付永振""杜新峰""应志超" } };  
  21.     private Context context = null;  
  22.   
  23.     // 构造函数   
  24.     public myExpendableadapler(Context context) {  
  25.   
  26.         this.context = context;  
  27.     }  
  28.   
  29.     public Object getChild(int groupPosition, int childPosition) {  
  30.   
  31.         return this.child[groupPosition][childPosition];  
  32.     }  
  33.   
  34.     public long getChildId(int groupPosition, int childPosition) {  
  35.   
  36.         return childPosition;  
  37.     }  
  38.   
  39.     private TextView buildTextView() {  
  40.         // LayoutParams AbsListView扩展提供一个位置来保存视图类型。   
  41.         AbsListView.LayoutParams params = new AbsListView.LayoutParams(  
  42.                 ViewGroup.LayoutParams.FILL_PARENT, 40);  
  43.   
  44.         TextView textView = new TextView(this.context);  
  45.         textView.setLayoutParams(params);  
  46.         // 大小   
  47.         textView.setTextSize(15.0f);  
  48.         textView.setGravity(Gravity.LEFT + 3);  
  49.         textView.setPadding(40833);  
  50.         return textView;  
  51.     }  
  52.   
  53.     public View getChildView(int groupPosition, int childPosition,  
  54.             boolean isLastChild, View convertView, ViewGroup parent) {  
  55.         TextView textView = new TextView(this.context);  
  56.         // 得到每组的子选项并转换成字符串   
  57.         textView  
  58.                 .setText(this.getChild(groupPosition, childPosition).toString());  
  59.   
  60.         return textView;  
  61.     }  
  62.   
  63.     // 统计子选项的个数   
  64.     public int getChildrenCount(int groupPosition) {  
  65.         // TODO Auto-generated method stub   
  66.         return this.child[groupPosition].length;  
  67.     }  
  68.   
  69.     // 得到复选项的位置   
  70.     public Object getGroup(int groupPosition) {  
  71.         // TODO Auto-generated method stub   
  72.         return this.group[groupPosition];  
  73.     }  
  74.   
  75.     // 得到复选项的个数   
  76.     public int getGroupCount() {  
  77.         // TODO Auto-generated method stub   
  78.         return this.group.length;  
  79.     }  
  80.   
  81.     // 得到复选项的id   
  82.     public long getGroupId(int groupPosition) {  
  83.         // TODO Auto-generated method stub   
  84.         return groupPosition;  
  85.     }  
  86.   
  87.     public View getGroupView(int groupPosition, boolean isExpanded,  
  88.             View convertView, ViewGroup parent) {  
  89.         // TODO Auto-generated method stub   
  90.         TextView textView = this.buildTextView();  
  91.         textView.setText(this.getGroup(groupPosition).toString());  
  92.         return textView;  
  93.     }  
  94.   
  95.     // 是否子选项和父选项id是稳定在改变底层数据。   
  96.     public boolean hasStableIds() {  
  97.         // TODO Auto-generated method stub   
  98.         return true;  
  99.     }  
  100.   
  101.     // p判断子选项是否可以选择   
  102.     public boolean isChildSelectable(int groupPosition, int childPosition) {  
  103.         // TODO Auto-generated method stub   
  104.         return true;  
  105.     }  
  106.   
  107. }  

10.有两个界面还没有添加功能pullrefreshtest.java    

  1. package com.wang;  
  2.   
  3. import java.util.LinkedList;  
  4.   
  5. import com.wang.pullrefresh.MyListView;  
  6. import com.wang.pullrefresh.MyListView.OnRefreshListener;  
  7.   
  8. import android.app.Activity;  
  9. import android.os.AsyncTask;  
  10. import android.os.Bundle;  
  11. import android.view.LayoutInflater;  
  12. import android.view.View;  
  13. import android.view.ViewGroup;  
  14. import android.view.Window;  
  15. import android.view.WindowManager;  
  16. import android.widget.BaseAdapter;  
  17. import android.widget.TextView;  
  18.   
  19. public class pullrefreshtest extends Activity {  
  20.     private LinkedList<String> data;  
  21.     private BaseAdapter adapter;  
  22.   
  23.     public void onCreate(Bundle savedInstanceState) {  
  24.         // 去除标题栏   
  25.         requestWindowFeature(Window.FEATURE_NO_TITLE);  
  26.         // 设置全屏,取消状态栏   
  27.         this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,  
  28.                 WindowManager.LayoutParams.FLAG_FULLSCREEN);  
  29.         super.onCreate(savedInstanceState);  
  30.         setContentView(R.layout.pullrefresh);  
  31.   
  32.         data = new LinkedList<String>();  
  33.         for (int i = 40; i < 50; i++) {  
  34.             // 输出list——item上的数据   
  35.             data.add(String.valueOf("暑假第" + i + "天,在南阳理工,想家ing ..."));  
  36.         }  
  37.   
  38.         final MyListView listView = (MyListView) findViewById(R.id.listView);  
  39.         adapter = new BaseAdapter() {  
  40.   
  41.             // 得到一个视图,显示在指定位置上的数据在数据集,可以创建一个视图从XML布局文件   
  42.             public View getView(int position, View convertView, ViewGroup parent) {  
  43.                 // 上下文全局应用程序对象   
  44.                 convertView = LayoutInflater.from(getApplicationContext())  
  45.                         .inflate(R.layout.list_item, null);  
  46.                 // 实例化组件   
  47.                 TextView textView = (TextView) convertView  
  48.                         .findViewById(R.id.textView_item);  
  49.                 // 设置文本本内容   
  50.                 textView.setText(data.get(position));  
  51.                 return convertView;  
  52.             }  
  53.   
  54.             // 得到行相关联id列表中指定的位置。   
  55.             public long getItemId(int position) {  
  56.                 return position;  
  57.             }  
  58.   
  59.             // 获得相关的数据项中的指定位置的数据集   
  60.             public Object getItem(int position) {  
  61.                 return data.get(position);  
  62.             }  
  63.   
  64.             // 获得项目在数据集适配器的个数。   
  65.             public int getCount() {  
  66.                 return data.size();  
  67.             }  
  68.   
  69.         };  
  70.   
  71.         listView.setAdapter(adapter);  
  72.   
  73.         listView.setonRefreshListener(new OnRefreshListener() {  
  74.             public void onRefresh() {  
  75.   
  76.                 new AsyncTask<Void, Void, Void>() {  
  77.                     // ...b表示多个参数   
  78.                     protected Void doInBackground(Void... params) {  
  79.                         try {  
  80.                             //    
  81.                             Thread.sleep(1000);  
  82.                         } catch (Exception e) {  
  83.                             e.printStackTrace();  
  84.                         }  
  85.   
  86.                         // 增加一条数据到list中   
  87.                         data.addFirst("刷新后内容:每天都是新的一天!!!,親!要努力奋斗哦!!!");  
  88.   
  89.                         return null;  
  90.                     }  
  91.   
  92.                     protected void onPostExecute(Void result) {  
  93.                         adapter.notifyDataSetChanged();  
  94.                         listView.onRefreshComplete();  
  95.                     }  
  96.   
  97.                 }.execute(null);  
  98.             }  
  99.         });  
  100.     }  
  101. }  

11.接着是下拉列表更新的实现过程MyListView.java

  1. package com.wang.pullrefresh;  
  2.   
  3. import java.text.SimpleDateFormat;  
  4. import java.util.Date;  
  5.   
  6. import com.wang.R;  
  7.   
  8. import android.content.Context;  
  9. import android.util.AttributeSet;  
  10. import android.util.Log;  
  11. import android.view.LayoutInflater;  
  12. import android.view.MotionEvent;  
  13. import android.view.View;  
  14. import android.view.ViewGroup;  
  15. import android.view.View.MeasureSpec;  
  16. import android.view.animation.LinearInterpolator;  
  17. import android.view.animation.RotateAnimation;  
  18. import android.widget.AbsListView;  
  19. import android.widget.BaseAdapter;  
  20. import android.widget.ImageView;  
  21. import android.widget.LinearLayout;  
  22. import android.widget.ListView;  
  23. import android.widget.ProgressBar;  
  24. import android.widget.TextView;  
  25. import android.widget.AbsListView.OnScrollListener;  
  26.   
  27. public class MyListView extends ListView implements OnScrollListener {  
  28.   
  29.     private static final String TAG = "listview";  
  30.   
  31.     private final static int RELEASE_To_REFRESH = 0;  
  32.     private final static int PULL_To_REFRESH = 1;  
  33.     private final static int REFRESHING = 2;  
  34.     private final static int DONE = 3;  
  35.     private final static int LOADING = 4;  
  36.   
  37.     // 实际的padding的距离与界面上偏移距离的比例   
  38.     private final static int RATIO = 3;  
  39.   
  40.     private LayoutInflater inflater;  
  41.   
  42.     private LinearLayout headView;  
  43.   
  44.     private TextView tipsTextview;  
  45.     private TextView lastUpdatedTextView;  
  46.     private ImageView arrowImageView;  
  47.     private ProgressBar progressBar;  
  48.   
  49.     private RotateAnimation animation;  
  50.     private RotateAnimation reverseAnimation;  
  51.   
  52.     // 用于保证startY的值在一个完整的touch事件中只被记录一次   
  53.     private boolean isRecored;  
  54.   
  55.     private int headContentWidth;  
  56.     private int headContentHeight;  
  57.   
  58.     private int startY;  
  59.     private int firstItemIndex;  
  60.   
  61.     private int state;  
  62.   
  63.     private boolean isBack;  
  64.   
  65.     private OnRefreshListener refreshListener;  
  66.   
  67.     private boolean isRefreshable;  
  68.   
  69.     public MyListView(Context context) {  
  70.         super(context);  
  71.         // 调用下面初始化的函数   
  72.         init(context);  
  73.     }  
  74.   
  75.     public MyListView(Context context, AttributeSet attrs) {  
  76.         super(context, attrs);  
  77.         // 调用下面初始化的函数   
  78.         init(context);  
  79.     }  
  80.   
  81.     private void init(Context context) {  
  82.   
  83.         // 获得LayoutInflater从给定的上下文。   
  84.         inflater = LayoutInflater.from(context);  
  85.   
  86.         // 实例化布局XML文件转换成相应的视图对象。   
  87.         headView = (LinearLayout) inflater.inflate(R.layout.refresh, null);  
  88.   
  89.         arrowImageView = (ImageView) headView  
  90.                 .findViewById(R.id.head_arrowImageView);  
  91.         // 设置最小宽度 和高度   
  92.         arrowImageView.setMinimumWidth(70);  
  93.         arrowImageView.setMinimumHeight(50);  
  94.         // 实例化布局XML文件转换成相应的视图对象。   
  95.         progressBar = (ProgressBar) headView  
  96.                 .findViewById(R.id.head_progressBar);  
  97.         tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);  
  98.         lastUpdatedTextView = (TextView) headView  
  99.                 .findViewById(R.id.head_lastUpdatedTextView);  
  100.   
  101.         // 调用下拉刷新的方法   
  102.         measureView(headView);  
  103.         // d得到原始高度和宽度   
  104.         headContentHeight = headView.getMeasuredHeight();  
  105.         headContentWidth = headView.getMeasuredWidth();  
  106.   
  107.         // 设置填充。视图可能添加的空间要求显示滚动条,这取决于风格和知名度的滚动条   
  108.         headView.setPadding(0, -1 * headContentHeight, 00);  
  109.         headView.invalidate();  
  110.   
  111.         // 标签用来识别一个日志消息的来源。标识类或活动日志调用发生   
  112.         Log.v("size""width:" + headContentWidth + " height:"  
  113.                 + headContentHeight);  
  114.   
  115.         // 添加一个固定视图出现在列表的顶部   
  116.         addHeaderView(headView, nullfalse);  
  117.         // 设置监听事件   
  118.         setOnScrollListener(this);  
  119.   
  120.         // 动画效果实现下拉和松开时候图片的 180度 旋转 注意0, -180,和他是有区别的 -180, 0,   
  121.         animation = new RotateAnimation(0, -180,  
  122.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  123.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  124.         // 设置加速度曲线为这个动画。默认值为一个线性插值。   
  125.         animation.setInterpolator(new LinearInterpolator());  
  126.         animation.setDuration(300);  
  127.         // 如果fillAfter是真的,转换,该动画执行完成时将会持续下去   
  128.         animation.setFillAfter(true);  
  129.   
  130.         reverseAnimation = new RotateAnimation(-1800,  
  131.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f,  
  132.                 RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  133.         // 设置加速度曲线为这个动画。默认值为一个线性插值。   
  134.         reverseAnimation.setInterpolator(new LinearInterpolator());  
  135.         reverseAnimation.setDuration(300);  
  136.         // 如果fillAfter是真的,转换,该动画执行完成时将会持续下去   
  137.         reverseAnimation.setFillAfter(true);  
  138.   
  139.         // 设置状态   
  140.         state = DONE;  
  141.         // 设置不可刷新状态   
  142.         isRefreshable = false;  
  143.     }  
  144.   
  145.     // 回调方法时要调用的列表或网格已经滚动。这将完成之后调用的滚动方法   
  146.     public void onScroll(AbsListView arg0, int firstVisiableItem, int arg2,  
  147.             int arg3) {  
  148.         firstItemIndex = firstVisiableItem;  
  149.     }  
  150.   
  151.     /* 
  152.      * 回调方法调用而列表视图或网格视图被滚动。 如果这个视图被滚动,将调用此方法在接下来的一局画卷的呈现 * 
  153.      */  
  154.     public void onScrollStateChanged(AbsListView arg0, int arg1) {  
  155.     }  
  156.   
  157.     // 触摸事件监听   
  158.     public boolean onTouchEvent(MotionEvent event) {  
  159.   
  160.         // 判断是否可以刷新   
  161.         if (isRefreshable) {  
  162.             // 根据动作相应不同的方法   
  163.             switch (event.getAction()) {  
  164.   
  165.             // 当按住屏幕向下拉屏幕的时候   
  166.             case MotionEvent.ACTION_DOWN:  
  167.                 if (firstItemIndex == 0 && !isRecored) {  
  168.                     isRecored = true;  
  169.                     startY = (int) event.getY();  
  170.                     Log.v(TAG, "在下拉的时候记录当前位置‘");  
  171.                 }  
  172.                 break;  
  173.   
  174.             // 当按住屏幕向上松屏幕的时候   
  175.             case MotionEvent.ACTION_UP:  
  176.   
  177.                 if (state != REFRESHING && state != LOADING) {  
  178.                     if (state == DONE) {  
  179.   
  180.                     }  
  181.                     if (state == PULL_To_REFRESH) {  
  182.                         state = DONE;  
  183.                         changeHeaderViewByState();  
  184.   
  185.                         Log.v(TAG, "由下拉刷新状态,到done状态");  
  186.                     }  
  187.                     if (state == RELEASE_To_REFRESH) {  
  188.                         state = REFRESHING;  
  189.                         changeHeaderViewByState();  
  190.                         onRefresh();  
  191.   
  192.                         Log.v(TAG, "由松开刷新状态,到done状态");  
  193.                     }  
  194.                 }  
  195.   
  196.                 isRecored = false;  
  197.                 isBack = false;  
  198.   
  199.                 break;  
  200.   
  201.             // 当按住屏幕移动时候   
  202.             case MotionEvent.ACTION_MOVE:  
  203.                 int tempY = (int) event.getY();  
  204.   
  205.                 if (!isRecored && firstItemIndex == 0) {  
  206.                     Log.v(TAG, "在move时候记录下位置");  
  207.                     isRecored = true;  
  208.                     startY = tempY;  
  209.                 }  
  210.   
  211.                 if (state != REFRESHING && isRecored && state != LOADING) {  
  212.   
  213.                     /*** 
  214.                      * , 当前的位置一直是在head,否则如果当列表超出屏幕的话, 当在上推的时候,列表会同时进行滚动 
  215.                      */  
  216.                     // 可以松手去刷新了   
  217.                     if (state == RELEASE_To_REFRESH) {  
  218.   
  219.                         setSelection(0);  
  220.   
  221.                         // 往上推了,推到了屏幕足够掩盖head的程度,但是还没有推到全部掩盖的地步   
  222.                         if (((tempY - startY) / RATIO < headContentHeight)  
  223.                                 && (tempY - startY) > 0) {  
  224.                             state = PULL_To_REFRESH;  
  225.                             changeHeaderViewByState();  
  226.   
  227.                             Log.v(TAG, "由松开刷新状态转变到下拉刷新状态");  
  228.                         }  
  229.                         // 一下子推到顶了   
  230.                         else if (tempY - startY <= 0) {  
  231.                             state = DONE;  
  232.                             // 调用改变时候的方法,更新UI   
  233.                             changeHeaderViewByState();  
  234.   
  235.                             Log.v(TAG, "由松开刷新状态转变到done状态");  
  236.                         } else {  
  237.                         }  
  238.                     }  
  239.                     // 还没有到达显示松开刷新的时候   
  240.                     if (state == PULL_To_REFRESH) {  
  241.   
  242.                         setSelection(0);  
  243.   
  244.                         // 下拉到可以进入RELEASE_TO_REFRESH的状态   
  245.                         if ((tempY - startY) / RATIO >= headContentHeight) {  
  246.                             state = RELEASE_To_REFRESH;  
  247.                             isBack = true;  
  248.                             // 调用改变时候的方法,更新UI   
  249.                             changeHeaderViewByState();  
  250.   
  251.                             Log.v(TAG, "由done或者下拉刷新状态转变到松开刷新");  
  252.                         }  
  253.                         // 上推到顶了   
  254.                         else if (tempY - startY <= 0) {  
  255.                             state = DONE;  
  256.                             // 调用改变时候的方法,更新UI   
  257.                             changeHeaderViewByState();  
  258.   
  259.                             Log.v(TAG, "由DOne或者下拉刷新状态转变到done状态");  
  260.                         }  
  261.                     }  
  262.   
  263.                     // done状态下   
  264.                     if (state == DONE) {  
  265.                         if (tempY - startY > 0) {  
  266.                             state = PULL_To_REFRESH;  
  267.                             // 调用改变时候的方法,更新UI   
  268.                             changeHeaderViewByState();  
  269.                         }  
  270.                     }  
  271.   
  272.                     // 更新headView的size   
  273.                     if (state == PULL_To_REFRESH) {  
  274.                         headView.setPadding(0, -1 * headContentHeight  
  275.                                 + (tempY - startY) / RATIO, 00);  
  276.   
  277.                     }  
  278.   
  279.                     // 更新headView的paddingTop   
  280.                     if (state == RELEASE_To_REFRESH) {  
  281.                         headView.setPadding(0, (tempY - startY) / RATIO  
  282.                                 - headContentHeight, 00);  
  283.                     }  
  284.   
  285.                 }  
  286.   
  287.                 break;  
  288.             }  
  289.         }  
  290.   
  291.         return super.onTouchEvent(event);  
  292.     }  
  293.   
  294.     // 当状态改变时候,调用该方法,以更新界面   
  295.     private void changeHeaderViewByState() {  
  296.         // 根据当前的状态进行判断   
  297.         switch (state) {  
  298.   
  299.         // 下拉时候,松开既可刷新   
  300.         case RELEASE_To_REFRESH:  
  301.             // 设置视图 VISIBLE 可见 ,GONE 不可见   
  302.             arrowImageView.setVisibility(View.VISIBLE);  
  303.             progressBar.setVisibility(View.GONE);  
  304.             tipsTextview.setVisibility(View.VISIBLE);  
  305.             lastUpdatedTextView.setVisibility(View.VISIBLE);  
  306.   
  307.             // 现在开始指定的动画。   
  308.             arrowImageView.clearAnimation();  
  309.             arrowImageView.startAnimation(animation);  
  310.   
  311.             tipsTextview.setText("松开既可刷新");  
  312.   
  313.             Log.v(TAG, "当前状态,松开即可刷新");  
  314.             break;  
  315.   
  316.         // 开始时候,下拉刷新   
  317.         case PULL_To_REFRESH:  
  318.             // 设置视图 VISIBLE 可见 ,GONE 不可见   
  319.             progressBar.setVisibility(View.GONE);  
  320.             tipsTextview.setVisibility(View.VISIBLE);  
  321.             lastUpdatedTextView.setVisibility(View.VISIBLE);  
  322.             // 现在开始指定的动画。   
  323.             arrowImageView.clearAnimation();  
  324.             arrowImageView.setVisibility(View.VISIBLE);  
  325.   
  326.             if (isBack) {  
  327.                 isBack = false;  
  328.                 // 现在开始指定的动画。   
  329.                 arrowImageView.clearAnimation();  
  330.                 arrowImageView.startAnimation(reverseAnimation);  
  331.   
  332.                 tipsTextview.setText("下拉刷新");  
  333.             } else {  
  334.                 tipsTextview.setText("下拉刷新");  
  335.             }  
  336.             Log.v(TAG, "当前状态,下拉刷新");  
  337.             break;  
  338.   
  339.         case REFRESHING:  
  340.   
  341.             headView.setPadding(0000);  
  342.             // 设置视图 VISIBLE 可见 ,GONE 不可见   
  343.             progressBar.setVisibility(View.VISIBLE);  
  344.             // 现在开始指定的动画。   
  345.             arrowImageView.clearAnimation();  
  346.             arrowImageView.setVisibility(View.GONE);  
  347.             tipsTextview.setText("正在刷新...");  
  348.             lastUpdatedTextView.setVisibility(View.VISIBLE);  
  349.   
  350.             Log.v(TAG, "当前状态,正在刷新...");  
  351.             break;  
  352.         case DONE:  
  353.             // 设置填充。视图可能添加的空间要求显示滚动条   
  354.             headView.setPadding(0, -1 * headContentHeight, 00);  
  355.             // 设置视图 VISIBLE 可见 ,GONE 不可见   
  356.             progressBar.setVisibility(View.GONE);  
  357.             // 现在开始指定的动画。   
  358.             arrowImageView.clearAnimation();  
  359.             arrowImageView.setImageResource(R.drawable.down);  
  360.             tipsTextview.setText("下拉刷新");  
  361.             lastUpdatedTextView.setVisibility(View.VISIBLE);  
  362.   
  363.             Log.v(TAG, "当前状态");  
  364.             break;  
  365.         }  
  366.     }  
  367.   
  368.     public void setonRefreshListener(OnRefreshListener refreshListener) {  
  369.         this.refreshListener = refreshListener;  
  370.         isRefreshable = true;  
  371.     }  
  372.   
  373.     public interface OnRefreshListener {  
  374.         public void onRefresh();  
  375.     }  
  376.   
  377.     // 设置更新时间   
  378.     public void onRefreshComplete() {  
  379.         state = DONE;  
  380.         //   
  381.         SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");  
  382.         String date = format.format(new Date());  
  383.         lastUpdatedTextView.setText("最近更新:" + date);  
  384.         changeHeaderViewByState();  
  385.     }  
  386.   
  387.     private void onRefresh() {  
  388.         if (refreshListener != null) {  
  389.             refreshListener.onRefresh();  
  390.         }  
  391.     }  
  392.   
  393.     // 下拉刷新的   
  394.     private void measureView(View child) {  
  395.         // v这组布局参数宽度和高度   
  396.         ViewGroup.LayoutParams p = child.getLayoutParams();  
  397.         if (p == null) {  
  398.             // 创建一个新组布局参数指定的宽度(填充)和高度(包裹)。   
  399.             p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,  
  400.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
  401.         }  
  402.   
  403.         // d得到childWidthSpec(高度或宽度)的子视图   
  404.         int childWidthSpec = ViewGroup.getChildMeasureSpec(00 + 0, p.width);  
  405.         int lpHeight = p.height;  
  406.         int childHeightSpec;  
  407.         if (lpHeight > 0) {  
  408.             // 创建一个测量规范基于所提供的大小和模式   
  409.             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,  
  410.                     MeasureSpec.EXACTLY);  
  411.         } else {  
  412.             childHeightSpec = MeasureSpec.makeMeasureSpec(0,  
  413.                     MeasureSpec.UNSPECIFIED);  
  414.         }  
  415.         // 找出一个视图应该多大。父供应约束信息在宽度和高度参数   
  416.         child.measure(childWidthSpec, childHeightSpec);  
  417.     }  
  418.   
  419.     public void setAdapter(BaseAdapter adapter) {  
  420.         // 设置最近刷新的时间   
  421.         SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日  HH:mm");  
  422.         String date = format.format(new Date());  
  423.         lastUpdatedTextView.setText("最近更新:" + date);  
  424.         super.setAdapter(adapter);  
  425.     }  
  426.   
  427. }  

12.接着是没有添加聊天功能的main3.java

  1. package com.wang;  
  2.   
  3. import android.app.Activity;  
  4. import android.os.Bundle;  
  5. import android.widget.ImageView;  
  6.   
  7. public class main3 extends Activity {  
  8.     protected void onCreate(Bundle savedInstanceState) {  
  9.         // TODO Auto-generated method stub   
  10.         super.onCreate(savedInstanceState);  
  11.         setContentView(R.layout.main3);  
  12.     }  
  13.   
  14. }  
13.亲,由于用到Activity,要注意注册哦!!
  1. <activity android:name=".pullrefreshtest"></activity>  
  2.       <activity android:name=".QQonline"></activity>  
  3.       <activity android:name=".main3"></activity>  

14.最后,还有一个重要的问题,本程序需要第三方jar包的支持,所以呢还需要导入第三方android-support-v4.jar包, 不会的参考 http://www.linuxidc.com/Linux/2012-08/67213.htm

下载地址

免费下载地址在 http://linux.linuxidc.com/

用户名与密码都是www.linuxidc.com

具体下载目录在 /2012年资料/8月/3日/Android模仿QQ的左右滑动切换界面和下拉更新的效果/android-support-v4.jar包

15,这样过后就可以看到运行效果咯: 第一张是下拉刷新时候的界面,第二张是松开即可刷新时候的图片,第三张是刷新后的内容,第四张的QQ联系人的界面,第五张是还没有完善聊天消息的界面,第六张是左右滑动切换界面的实现效果


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值