自定义总结2017.8.28
来源:互联网 发布:阿里云飞天有几个部门 编辑:程序博客网 时间:2024/06/05 03:20
1.自定义录播图:
1.MainActivity ViewPager的使用
public class MainActivity extends Activity implements OnPageChangeListener{ private ViewPager viewPager; private int[] imageResIds; private ArrayList<ImageView> imageViewList; private LinearLayout ll_point_container; private String[] contentDescs; private TextView tv_desc; private int previousSelectedPosition = 0; boolean isRunning = false; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // 初始化布局 View视图 initViews(); // Model数据 initData(); // Controller 控制器 initAdapter(); // 开启轮询 new Thread(){ public void run() { isRunning = true; while(isRunning){ try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } // 往下跳一位 runOnUiThread(new Runnable() { @Override public void run() { System.out.println("设置当前位置: " + viewPager.getCurrentItem()); viewPager.setCurrentItem(viewPager.getCurrentItem()+1); } }); } }; }.start(); } @Override protected void onDestroy() { super.onDestroy(); isRunning = false; } private void initViews() { viewPager = (ViewPager) findViewById(R.id.viewpager); viewPager.setOnPageChangeListener(this);// 设置页面更新监听// viewPager.setOffscreenPageLimit(1);// 左右各保留几个对象 ll_point_container = (LinearLayout) findViewById(R.id.ll_point_container); tv_desc = (TextView) findViewById(R.id.tv_desc); } private void initData() { // 初始化要显示的数据 // 图片资源id数组 imageResIds = new int[]{R.drawable.a, R.drawable.b, R.drawable.c, R.drawable.d, R.drawable.e}; // 文本描述 contentDescs = new String[]{ "巩俐不低俗,我就不能低俗", "扑树又回来啦!再唱经典老歌引万人大合唱", "揭秘北京电影如何升级", "乐视网TV版大派送", "热血屌丝的反杀" }; // 初始化要展示的5个ImageView imageViewList = new ArrayList<ImageView>(); ImageView imageView; View pointView; LayoutParams layoutParams; for (int i = 0; i < imageResIds.length; i++) { // 初始化要显示的图片对象 imageView = new ImageView(this); imageView.setBackgroundResource(imageResIds[i]); imageViewList.add(imageView); // 加小白点, 指示器 pointView = new View(this); pointView.setBackgroundResource(R.drawable.selector_bg_point); layoutParams = new LinearLayout.LayoutParams(5, 5); if(i != 0) layoutParams.leftMargin = 10; // 设置默认所有都不可用 pointView.setEnabled(false); ll_point_container.addView(pointView, layoutParams); } } private void initAdapter() { ll_point_container.getChildAt(0).setEnabled(true); tv_desc.setText(contentDescs[0]); previousSelectedPosition = 0; // 设置适配器 viewPager.setAdapter(new MyAdapter()); // 默认设置到中间的某个位置 int pos = Integer.MAX_VALUE / 2 - (Integer.MAX_VALUE / 2 % imageViewList.size()); // 2147483647 / 2 = 1073741823 - (1073741823 % 5) viewPager.setCurrentItem(5000000); // 设置到某个位置 } class MyAdapter extends PagerAdapter{ @Override public int getCount() { return Integer.MAX_VALUE; } // 3. 指定复用的判断逻辑, 固定写法 @Override public boolean isViewFromObject(View view, Object object) { // 当划到新的条目, 又返回来, view是否可以被复用. // 返回判断规则 return view == object; } // 1. 返回要显示的条目内容, 创建条目 @Override public Object instantiateItem(ViewGroup container, int position) { System.out.println("instantiateItem初始化: " + position); // container: 容器: ViewPager // position: 当前要显示条目的位置 0 -> 4// newPosition = position % 5 int newPosition = position % imageViewList.size(); ImageView imageView = imageViewList.get(newPosition); // a. 把View对象添加到container中 container.addView(imageView); // b. 把View对象返回给框架, 适配器 return imageView; // 必须重写, 否则报异常 } // 2. 销毁条目 @Override public void destroyItem(ViewGroup container, int position, Object object) { // object 要销毁的对象 System.out.println("destroyItem销毁: " + position); container.removeView((View)object); } } @Override public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { // 滚动时调用 } @Override public void onPageSelected(int position) { // 新的条目被选中时调用 System.out.println("onPageSelected: " + position); int newPosition = position % imageViewList.size(); //设置文本 tv_desc.setText(contentDescs[newPosition]);// for (int i = 0; i < ll_point_container.getChildCount(); i++) {// View childAt = ll_point_container.getChildAt(position);// childAt.setEnabled(position == i);// } // 把之前的禁用, 把最新的启用, 更新指示器 ll_point_container.getChildAt(previousSelectedPosition).setEnabled(false); ll_point_container.getChildAt(newPosition).setEnabled(true); // 记录之前的位置 previousSelectedPosition = newPosition; } @Override public void onPageScrollStateChanged(int state) { // 滚动状态变化时调用 }}
selector_bg_point.xml
<item android:state_enabled="true" android:drawable="@drawable/shape_bg_point_enable"/><item android:state_enabled="false" android:drawable="@drawable/shape_bg_point_disable"/>
shape_bg_point_disable.xml
shape_bg_point_enable.xml
RelativeLayout
<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" tools:context=".MainActivity" > <RelativeLayout android:layout_width="match_parent" android:layout_height="160dp" > <android.support.v4.view.ViewPager android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent" /> <LinearLayout android:layout_width="match_parent" android:layout_height="40dp" android:padding="5dp" android:orientation="vertical" android:layout_alignParentBottom="true" android:gravity="center_horizontal" android:background="#66000000" > <TextView android:id="@+id/tv_desc" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="@android:color/white" android:singleLine="true" android:text="天王盖地虎, 天王盖地虎, 天王盖地虎, " /> <LinearLayout android:id="@+id/ll_point_container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:orientation="horizontal" ></LinearLayout> </LinearLayout> </RelativeLayout>
2.自定义开关
ToggleView
/**
* 自定义开关
* @author poplar
*
* Android 的界面绘制流程
* 测量 摆放 绘制
* measure -> layout -> draw
* | | |
* onMeasure -> onLayout -> onDraw 重写这些方法, 实现自定义控件
*
* onResume()之后执行
*
* View
* onMeasure() (在这个方法里指定自己的宽高) -> onDraw() (绘制自己的内容)
*
* ViewGroup
* onMeasure() (指定自己的宽高, 所有子View的宽高)-> onLayout() (摆放所有子View) -> onDraw() (绘制内容)
*/
public class ToggleView extends View {
private Bitmap switchBackgroupBitmap; // 背景图片private Bitmap slideButtonBitmap; // 滑块图片private Paint paint; // 画笔private boolean mSwitchState = false; // 开关状态, 默认false private float currentX;/** * 用于代码创建控件 * @param context */public ToggleView(Context context) { super(context); init();}/** * 用于在xml里使用, 可指定自定义属性 * @param context * @param attrs */public ToggleView(Context context, AttributeSet attrs) { super(context, attrs); init(); // 获取配置的自定义属性 String namespace = "http://schemas.android.com/apk/res/com.itheima74.toggleview"; int switchBackgroundResource = attrs.getAttributeResourceValue(namespace , "switch_background", -1); int slideButtonResource = attrs.getAttributeResourceValue(namespace , "slide_button", -1); mSwitchState = attrs.getAttributeBooleanValue(namespace, "switch_state", false); setSwitchBackgroundResource(switchBackgroundResource); setSlideButtonResource(slideButtonResource);}/** * 用于在xml里使用, 可指定自定义属性, 如果指定了样式, 则走此构造函数 * @param context * @param attrs * @param defStyle */public ToggleView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init();}private void init() { paint = new Paint();}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { setMeasuredDimension(switchBackgroupBitmap.getWidth(), switchBackgroupBitmap.getHeight());}// Canvas 画布, 画板. 在上边绘制的内容都会显示到界面上.@Overrideprotected void onDraw(Canvas canvas) { // 1. 绘制背景 canvas.drawBitmap(switchBackgroupBitmap, 0, 0, paint); // 2. 绘制滑块 if(isTouchMode){ // 根据当前用户触摸到的位置画滑块 // 让滑块向左移动自身一半大小的位置 float newLeft = currentX - slideButtonBitmap.getWidth() / 2.0f; int maxLeft = switchBackgroupBitmap.getWidth() - slideButtonBitmap.getWidth(); // 限定滑块范围 if(newLeft < 0){ newLeft = 0; // 左边范围 }else if (newLeft > maxLeft) { newLeft = maxLeft; // 右边范围 } canvas.drawBitmap(slideButtonBitmap, newLeft, 0, paint); }else { // 根据开关状态boolean, 直接设置图片位置 if(mSwitchState){// 开 int newLeft = switchBackgroupBitmap.getWidth() - slideButtonBitmap.getWidth(); canvas.drawBitmap(slideButtonBitmap, newLeft, 0, paint); }else {// 关 canvas.drawBitmap(slideButtonBitmap, 0, 0, paint); } }}boolean isTouchMode = false;private OnSwitchStateUpdateListener onSwitchStateUpdateListener;// 重写触摸事件, 响应用户的触摸.@Overridepublic boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: isTouchMode = true; System.out.println("event: ACTION_DOWN: " + event.getX()); currentX = event.getX(); break; case MotionEvent.ACTION_MOVE: System.out.println("event: ACTION_MOVE: " + event.getX()); currentX = event.getX(); break; case MotionEvent.ACTION_UP: isTouchMode = false; System.out.println("event: ACTION_UP: " + event.getX()); currentX = event.getX(); float center = switchBackgroupBitmap.getWidth() / 2.0f; // 根据当前按下的位置, 和控件中心的位置进行比较. boolean state = currentX > center; // 如果开关状态变化了, 通知界面. 里边开关状态更新了. if(state != mSwitchState && onSwitchStateUpdateListener != null){ // 把最新的boolean, 状态传出去了 onSwitchStateUpdateListener.onStateUpdate(state); } mSwitchState = state; break; default: break; } // 重绘界面 invalidate(); // 会引发onDraw()被调用, 里边的变量会重新生效.界面会更新 return true; // 消费了用户的触摸事件, 才可以收到其他的事件.}/** * 设置背景图 * @param switchBackground */public void setSwitchBackgroundResource(int switchBackground) { switchBackgroupBitmap = BitmapFactory.decodeResource(getResources(), switchBackground);}/** * 设置滑块图片资源 * @param slideButton */public void setSlideButtonResource(int slideButton) { slideButtonBitmap = BitmapFactory.decodeResource(getResources(), slideButton);}/** * 设置开关状态 * @param b */public void setSwitchState(boolean mSwitchState) { this.mSwitchState = mSwitchState;}public interface OnSwitchStateUpdateListener{ // 状态回调, 把当前状态传出去 void onStateUpdate(boolean state);}public void setOnSwitchStateUpdateListener( OnSwitchStateUpdateListener onSwitchStateUpdateListener) { this.onSwitchStateUpdateListener = onSwitchStateUpdateListener;}
}
MainActivity
public class MainActivity extends Activity { private ToggleView toggleView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toggleView = (ToggleView) findViewById(R.id.toggleView);// toggleView.setSwitchBackgroundResource(R.drawable.switch_background);// toggleView.setSlideButtonResource(R.drawable.slide_button);// toggleView.setSwitchState(true);// // 设置开关更新监听 toggleView.setOnSwitchStateUpdateListener(new OnSwitchStateUpdateListener(){ @Override public void onStateUpdate(boolean state) { Toast.makeText(getApplicationContext(), "state: " + state, 0).show(); } }); }
activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:itheima="http://schemas.android.com/apk/res/com.itheima74.toggleview" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" > <com.itheima74.toggleview.ui.ToggleView android:id="@+id/toggleView" android:layout_centerInParent="true" itheima:switch_background="@drawable/switch_background" itheima:slide_button="@drawable/slide_button" itheima:switch_state="false" android:layout_width="wrap_content" android:layout_height="wrap_content" /></RelativeLayout>
侧滑面板的案列:
SlideMenu.class
package com.example.administrator.yan55text_20170824.ui;import android.content.Context;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import android.widget.Scroller;public class SlideMenu extends ViewGroup { private float downX; // 按下的x坐标 private float downY; // 按下的y坐标 private float moveX; public static final int MAIN_STATE = 0; public static final int MENU_STATE = 1; private int currentState = MAIN_STATE; // 当前模式 private Scroller scroller; public SlideMenu(Context context) { super(context); init(); } public SlideMenu(Context context, AttributeSet attrs) { super(context, attrs); init(); } public SlideMenu(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } private void init() { // 初始化滚动器, 数值模拟器 scroller = new Scroller(getContext()); } /** * 测量并设置 所有子View的宽高 * widthMeasureSpec: 当前控件的宽度测量规则 * heightMeasureSpec: 当前控件的高度测量规则 */ @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { // 指定左面板的宽高 View leftMenu = getChildAt(0); leftMenu.measure(leftMenu.getLayoutParams().width, heightMeasureSpec); // 指定主面板的宽高 View mainContent = getChildAt(1); mainContent.measure(widthMeasureSpec, heightMeasureSpec); super.onMeasure(widthMeasureSpec, heightMeasureSpec); } /** * changed: 当前控件的尺寸大小, 位置 是否发生了变化 * left:当前控件 左边距 * top:当前控件 顶边距 * right:当前控件 右边界 * bottom:当前控件 下边界 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // 摆放内容, 左面板 View leftMenu = getChildAt(0); leftMenu.layout(-leftMenu.getMeasuredWidth(), 0, 0, b); // 主面板 getChildAt(1).layout(l, t, r, b); } /** * 处理触摸事件 */ @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: downX = event.getX(); break; case MotionEvent.ACTION_MOVE: moveX = event.getX(); // 将要发生的偏移量/变化量 int scrollX = (int) (downX - moveX); // 计算将要滚动到的位置, 判断是否会超出去, 超出去了.不执行scrollBy // getScrollX() 当前滚动到的位置 int newScrollPosition = getScrollX() + scrollX; if (newScrollPosition < -getChildAt(0).getMeasuredWidth()) { // 限定左边界 // < -240 scrollTo(-getChildAt(0).getMeasuredWidth(), 0); } else if (newScrollPosition > 0) { // 限定右边界 // > 0 scrollTo(0, 0); } else { // 让变化量生效 scrollBy(scrollX, 0); } downX = moveX; break; case MotionEvent.ACTION_UP: // 根据当前滚动到的位置, 和左面板的一半进行比较 int leftCenter = (int) (-getChildAt(0).getMeasuredWidth() / 2.0f); if (getScrollX() < leftCenter) { // 打开, 切换成菜单面板 currentState = MENU_STATE; updateCurrentContent(); } else { // 关闭, 切换成主面板 currentState = MAIN_STATE; updateCurrentContent(); } break; default: break; } return true; // 消费事件 } /** * 根据当前的状态, 执行 关闭/开启 的动画 */ private void updateCurrentContent() { int startX = getScrollX(); int dx = 0; if (currentState == MENU_STATE) { dx = -getChildAt(0).getMeasuredWidth() - startX; } else { dx = 0 - startX; } int duration = Math.abs(dx * 2); scroller.startScroll(startX, 0, dx, 0, duration); invalidate();// 重绘界面 -> drawChild() -> computeScroll(); } //2. 维持动画的继续 @Override public void computeScroll() { super.computeScroll(); if (scroller.computeScrollOffset()) { // 直到duration事件以后, 结束 // true, 动画还没有结束 // 获取当前模拟的数据, 也就是要滚动到的位置 int currX = scroller.getCurrX(); System.out.println("currX: " + currX); scrollTo(currX, 0); // 滚过去 invalidate(); // 重绘界面-> drawChild() -> computeScroll();循环 } } public void open() { currentState = MENU_STATE; updateCurrentContent(); } public void close() { currentState = MAIN_STATE; updateCurrentContent(); } public void switchState() { if (currentState == MAIN_STATE) { open(); } else { close(); } } public int getCurrentState() { return currentState; } /** * 拦截判断 */ @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downX = ev.getX(); downY = ev.getY(); break; case MotionEvent.ACTION_MOVE: float xOffset = Math.abs(ev.getX() - downX); float yOffset = Math.abs(ev.getY() - downY); if (xOffset > yOffset && xOffset > 5) { // 水平方向超出一定距离时,才拦截 return true; // 拦截此次触摸事件, 界面的滚动 } break; case MotionEvent.ACTION_UP: break; default: break; } return super.onInterceptTouchEvent(ev); }}
MainActivity.class
public class MainActivity extends Activity implements OnClickListener{ private SlideMenu sm; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_main); sm = (SlideMenu) findViewById(R.id.sm); findViewById(R.id.ib_back).setOnClickListener(this); } public void onTabClick(View view){ } @Override public void onClick(View v) { sm.switchState(); }}
activity_main.xmllayout_left_menu.xmllayout_main_content.xml
下拉刷新提示
public class RefreshListView extends ListView implements OnScrollListener{ private View mHeaderView; // 头布局 private float downY; // 按下的y坐标 private float moveY; // 移动后的y坐标 private int mHeaderViewHeight; // 头布局高度 public static final int PULL_TO_REFRESH = 0;// 下拉刷新 public static final int RELEASE_REFRESH = 1;// 释放刷新 public static final int REFRESHING = 2; // 刷新中 private int currentState = PULL_TO_REFRESH; // 当前刷新模式 private RotateAnimation rotateUpAnim; // 箭头向上动画 private RotateAnimation rotateDownAnim; // 箭头向下动画 private View mArrowView; // 箭头布局 private TextView mTitleText; // 头布局标题 private ProgressBar pb; // 进度指示器 private TextView mLastRefreshTime; // 最后刷新时间 private OnRefreshListener mListener; // 刷新监听 private View mFooterView; // 脚布局 private int mFooterViewHeight; // 脚布局高度 private boolean isLoadingMore; // 是否正在加载更多 public RefreshListView(Context context) { super(context); init(); } public RefreshListView(Context context, AttributeSet attrs) { super(context, attrs); init(); } public RefreshListView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); init(); } /** * 初始化头布局, 脚布局 * 滚动监听 */ private void init() { initHeaderView(); initAnimation(); initFooterView(); setOnScrollListener(this); } /** * 初始化脚布局 */ private void initFooterView() { mFooterView = View.inflate(getContext(), R.layout.layout_footer_list, null); mFooterView.measure(0, 0); mFooterViewHeight = mFooterView.getMeasuredHeight(); // 隐藏脚布局 mFooterView.setPadding(0, -mFooterViewHeight, 0, 0); addFooterView(mFooterView); } /** * 初始化头布局的动画 */ private void initAnimation() { // 向上转, 围绕着自己的中心, 逆时针旋转0 -> -180. rotateUpAnim = new RotateAnimation(0f, -180f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateUpAnim.setDuration(300); rotateUpAnim.setFillAfter(true); // 动画停留在结束位置 // 向下转, 围绕着自己的中心, 逆时针旋转 -180 -> -360 rotateDownAnim = new RotateAnimation(-180f, -360, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f); rotateDownAnim.setDuration(300); rotateDownAnim.setFillAfter(true); // 动画停留在结束位置 } /** * 初始化头布局 */ private void initHeaderView() { mHeaderView = View.inflate(getContext(), R.layout.layout_header_list, null); mArrowView = mHeaderView.findViewById(R.id.iv_arrow); pb = (ProgressBar) mHeaderView.findViewById(R.id.pb); mTitleText = (TextView) mHeaderView.findViewById(R.id.tv_title); mLastRefreshTime = (TextView) mHeaderView.findViewById(R.id.tv_desc_last_refresh); // 提前手动测量宽高 mHeaderView.measure(0, 0);// 按照设置的规则测量 mHeaderViewHeight = mHeaderView.getMeasuredHeight(); System.out.println(" measuredHeight: " + mHeaderViewHeight); // 设置内边距, 可以隐藏当前控件 , -自身高度 mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0); // 在设置数据适配器之前执行添加 头布局/脚布局 的方法. addHeaderView(mHeaderView); } @Override public boolean onTouchEvent(MotionEvent ev) { // 判断滑动距离, 给Header设置paddingTop switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: downY = ev.getY(); System.out.println("downY: " + downY); break; case MotionEvent.ACTION_MOVE: moveY = ev.getY(); System.out.println("moveY: " + moveY); // 如果是正在刷新中, 就执行父类的处理 if(currentState == REFRESHING){ return super.onTouchEvent(ev); } float offset = moveY - downY; // 移动的偏移量 // 只有 偏移量>0, 并且当前第一个可见条目索引是0, 才放大头部 if(offset > 0 && getFirstVisiblePosition() == 0){// int paddingTop = -自身高度 + 偏移量 int paddingTop = (int) (- mHeaderViewHeight + offset); mHeaderView.setPadding(0, paddingTop, 0, 0); if(paddingTop >= 0 && currentState != RELEASE_REFRESH){// 头布局完全显示 System.out.println("切换成释放刷新模式: " + paddingTop); // 切换成释放刷新模式 currentState = RELEASE_REFRESH; updateHeader(); // 根据最新的状态值更新头布局内容 }else if(paddingTop < 0 && currentState != PULL_TO_REFRESH){ // 头布局不完全显示 System.out.println("切换成下拉刷新模式: " + paddingTop); // 切换成下拉刷新模式 currentState = PULL_TO_REFRESH; updateHeader(); // 根据最新的状态值更新头布局内容 } return true; // 当前事件被我们处理并消费 } break; case MotionEvent.ACTION_UP: // 根据刚刚设置状态 if(currentState == PULL_TO_REFRESH){// - paddingTop < 0 不完全显示, 恢复 mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0); }else if(currentState == RELEASE_REFRESH){// - paddingTop >= 0 完全显示, 执行正在刷新... mHeaderView.setPadding(0, 0, 0, 0); currentState = REFRESHING; updateHeader(); } break; default: break; } return super.onTouchEvent(ev); } /** * 根据状态更新头布局内容 */ private void updateHeader() { switch (currentState) { case PULL_TO_REFRESH: // 切换回下拉刷新 // 做动画, 改标题 mArrowView.startAnimation(rotateDownAnim); mTitleText.setText("下拉刷新"); break; case RELEASE_REFRESH: // 切换成释放刷新 // 做动画, 改标题 mArrowView.startAnimation(rotateUpAnim); mTitleText.setText("释放刷新"); break; case REFRESHING: // 刷新中... mArrowView.clearAnimation(); mArrowView.setVisibility(View.INVISIBLE); pb.setVisibility(View.VISIBLE); mTitleText.setText("正在刷新中..."); if(mListener != null){ mListener.onRefresh(); // 通知调用者, 让其到网络加载更多数据. } break; default: break; } } /** * 刷新结束, 恢复界面效果 */ public void onRefreshComplete() { if(isLoadingMore){ // 加载更多 mFooterView.setPadding(0, -mFooterViewHeight, 0, 0); isLoadingMore = false; }else { // 下拉刷新 currentState = PULL_TO_REFRESH; mTitleText.setText("下拉刷新"); // 切换文本 mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏头布局 pb.setVisibility(View.INVISIBLE); mArrowView.setVisibility(View.VISIBLE); String time = getTime(); mLastRefreshTime.setText("最后刷新时间: " + time); } } private String getTime() { long currentTimeMillis = System.currentTimeMillis(); SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return format.format(currentTimeMillis); } public interface OnRefreshListener{ void onRefresh(); // 下拉刷新 void onLoadMore();// 加载更多 } public void setRefreshListener(OnRefreshListener mListener) { this.mListener = mListener; }// public static int SCROLL_STATE_IDLE = 0; // 空闲// public static int SCROLL_STATE_TOUCH_SCROLL = 1; // 触摸滑动// public static int SCROLL_STATE_FLING = 2; // 滑翔 @Override public void onScrollStateChanged(AbsListView view, int scrollState) { // 状态更新的时候 System.out.println("scrollState: " + scrollState); if(isLoadingMore){ return; // 已经在加载更多.返回 } // 最新状态是空闲状态, 并且当前界面显示了所有数据的最后一条. 加载更多 if(scrollState == SCROLL_STATE_IDLE && getLastVisiblePosition() >= (getCount() - 1)){ isLoadingMore = true; System.out.println("scrollState: 开始加载更多"); mFooterView.setPadding(0, 0, 0, 0); setSelection(getCount()); // 跳转到最后一条, 使其显示出加载更多. if(mListener != null){ mListener.onLoadMore(); } } } @Override public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { // 滑动过程 }}
MainActivity.class
public class MainActivity extends Activity { private RefreshListView listview; private ArrayList<String> listDatas; private MyAdapter adapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题 setContentView(R.layout.activity_main); listview = (RefreshListView) findViewById(R.id.listview); listview.setRefreshListener(new OnRefreshListener() { @Override public void onRefresh() { new Thread(){ public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } listDatas.add(0,"我是下拉刷新出来的数据!"); runOnUiThread(new Runnable() { @Override public void run() { adapter.notifyDataSetChanged(); listview.onRefreshComplete(); } }); }; }.start(); } @Override public void onLoadMore() { new Thread(){ public void run() { try { Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } listDatas.add("我是加载更多出来的数据!1"); listDatas.add("我是加载更多出来的数据!2"); listDatas.add("我是加载更多出来的数据!3"); runOnUiThread(new Runnable() { @Override public void run() { adapter.notifyDataSetChanged(); listview.onRefreshComplete(); } }); }; }.start(); } }); listDatas = new ArrayList<String>(); for (int i = 0; i < 30; i++) { listDatas.add("这是一条ListView数据: " + i); } // 设置数据适配器 adapter = new MyAdapter(); listview.setAdapter(adapter); } class MyAdapter extends BaseAdapter { @Override public int getCount() { return listDatas.size(); } @Override public View getView(int position, View convertView, ViewGroup parent) { TextView textView = new TextView(parent.getContext()); textView.setTextSize(18f); textView.setText(listDatas.get(position)); return textView; } @Override public Object getItem(int position) { return listDatas.get(position); } @Override public long getItemId(int position) { return position; } }}
activity_main.xml
layout_footer_list.xml
layout_header_list.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="horizontal"> <FrameLayout android:layout_margin="5dp" android:layout_width="50dp" android:layout_height="50dp" > <ImageView android:id="@+id/iv_arrow" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/common_listview_headview_red_arrow" /> <ProgressBar android:id="@+id/pb" android:layout_width="match_parent" android:layout_height="match_parent" android:indeterminateDrawable="@drawable/shape_progress" android:visibility="invisible" /> </FrameLayout> <LinearLayout android:layout_margin="5dp" android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_horizontal" android:orientation="vertical" > <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:text="下拉刷新" android:textColor="#F00" android:textSize="18sp" /> <TextView android:id="@+id/tv_desc_last_refresh" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="5dp" android:singleLine="true" android:text="最后刷新时间: 2015-10-11 09:20:35" android:textColor="#666" android:textSize="14sp" /> </LinearLayout></LinearLayout>----------
阅读全文
0 0
- 自定义总结2017.8.28
- 总结:发送自定义消息
- 总结:发送自定义消息
- 总结:发送自定义消息
- 总结:发送自定义消息
- 自定义泛型总结
- 自定义标签开发总结
- 自定义generator 总结
- 自定义事件、组件总结
- 自定义标签总结
- 自定义事件总结
- smarty自定义函数总结
- SMARTY自定义函数总结
- FLEX:自定义事件 总结
- FLEX:自定义事件总结
- 自定义view总结一
- 自定义对话框的总结
- 自定义viewgroup总结
- springboot集成mongodb使用mongoTemplate和MongoRepository
- 极乐叔支招:程序员七夕表白招式
- scrapy爬虫实战教程
- java丶对数组值按首字母进行排序
- webgl+three.js,学习笔记,画一个立方体+解析
- 自定义总结2017.8.28
- ios 证书不同的期限
- iOS NSData转float
- Java IO全解
- 6.软件测试工作流程
- Java获取文件后缀名
- 判断两个链表是否相交并找出第一个相交节点
- AJax技术简单的验证注册的用户名
- Path