• 指令汇B新闻客户端开发(三) 下拉刷新


    现在我们继续这个新闻客户端的开发,今天分享的是下拉刷新的实现,我们都知道下拉刷新是一个应用很常见也很实用的功能。我这个应用是通过拉ListView来实现刷新的,先看一张刷新的原理图

    从图中可知,手指移动的距离就是dy。

    刷新分为三种状态:下拉刷新、正在刷新、松开刷新;

    定义这三种状态为:

    private static final int STATE_PULL_REFRESH = 0;// 下拉刷新
    private static final int STATE_RELEASE_REFRESH = 1;// 松开刷新
    private static final int STATE_REFRESHING = 2;// 正在刷新

    接下来开始写我们的代码了

    初始化头布局:

    private void initHeaderView() {
    		mHeaderView = View.inflate(getContext(), R.layout.refresh_header, null);
    		this.addHeaderView(mHeaderView);
    
    		tvTitle = (TextView) mHeaderView.findViewById(R.id.tv_title);
    		tvTime = (TextView) mHeaderView.findViewById(R.id.tv_time);
    		ivArrow = (ImageView) mHeaderView.findViewById(R.id.iv_arr);
    		pbProgress = (ProgressBar) mHeaderView.findViewById(R.id.pb_progress);
    
    		mHeaderView.measure(0, 0);
    		mHeaderViewHeight = mHeaderView.getMeasuredHeight();
    
    		mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏头布局
    
    		initArrowAnim();
    
    		tvTime.setText("最后刷新时间:" + getCurrentTime());
    	}
    初始化脚布局

     * 初始化脚布局
    	 */
    	private void initFooterView() {
    		mFooterView = View.inflate(getContext(),
    				R.layout.refresh_listview_footer, null);
    		this.addFooterView(mFooterView);
    
    		mFooterView.measure(0, 0);
    		mFooterViewHeight = mFooterView.getMeasuredHeight();
    
    		mFooterView.setPadding(0, -mFooterViewHeight, 0, 0);// 隐藏
    
    		this.setOnScrollListener(this);
    	}

    初始化箭头的动画:

    /**
    	 * 初始化箭头动画
    	 */
    	private void initArrowAnim() {
    		// 箭头向上动画
    		animUp = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f,
    				Animation.RELATIVE_TO_SELF, 0.5f);
    		animUp.setDuration(200); 
    		animUp.setFillAfter(true);
    
    		// 箭头向下动画
    		animDown = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,
    				0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    		animDown.setDuration(200);
    		animDown.setFillAfter(true);
    
    	}
    


    接下来是实现触摸的方法及偏移量的计算:

    @Override
    	public boolean onTouchEvent(MotionEvent ev) {
    		switch (ev.getAction()) {
    		case MotionEvent.ACTION_DOWN:
    			startY = (int) ev.getRawY();
    			break;
    		case MotionEvent.ACTION_MOVE:
    			if (startY == -1) {// 确保startY有效
    				startY = (int) ev.getRawY();
    			}
    
    			if (mCurrrentState == STATE_REFRESHING) {// 正在刷新时不做处理
    				break;
    			}
    
    			int endY = (int) ev.getRawY();
    			int dy = endY - startY;// 移动偏移量
    
    			if (dy > 0 && getFirstVisiblePosition() == 0) {// 只有下拉并且当前是第一个item,才允许下拉
    				int padding = dy - mHeaderViewHeight;// 计算padding
    				mHeaderView.setPadding(0, padding, 0, 0);// 设置当前padding
    
    				if (padding > 0 && mCurrrentState != STATE_RELEASE_REFRESH) {// 状态改为松开刷新
    					mCurrrentState = STATE_RELEASE_REFRESH;
    					refreshState();
    				} else if (padding < 0 && mCurrrentState != STATE_PULL_REFRESH) {// 改为下拉刷新状态
    					mCurrrentState = STATE_PULL_REFRESH;
    					refreshState();
    				}
    
    				return true;
    			}
    
    			break;
    		case MotionEvent.ACTION_UP:
    			startY = -1;// 重置
    
    			if (mCurrrentState == STATE_RELEASE_REFRESH) {
    				mCurrrentState = STATE_REFRESHING;// 正在刷新
    				mHeaderView.setPadding(0, 0, 0, 0);// 显示
    				refreshState();
    			} else if (mCurrrentState == STATE_PULL_REFRESH) {
    				mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏
    			}
    
    			break;
    
    		default:
    			break;
    		}
    		return super.onTouchEvent(ev);
    	}
    

    刷新下拉控件的布局:

    private void refreshState() {
    		switch (mCurrrentState) {
    		case STATE_PULL_REFRESH:
    			tvTitle.setText("下拉刷新");
    			ivArrow.setVisibility(View.VISIBLE);
    			pbProgress.setVisibility(View.INVISIBLE);
    			ivArrow.startAnimation(animDown);
    			break;
    		case STATE_RELEASE_REFRESH:
    			tvTitle.setText("松开刷新");
    			ivArrow.setVisibility(View.VISIBLE);
    			pbProgress.setVisibility(View.INVISIBLE);
    			ivArrow.startAnimation(animUp);
    			break;
    		case STATE_REFRESHING:
    			tvTitle.setText("正在刷新...");
    			ivArrow.clearAnimation();// 必须先清除动画,才能隐藏
    			ivArrow.setVisibility(View.INVISIBLE);
    			pbProgress.setVisibility(View.VISIBLE);
    
    			if (mListener != null) {
    				mListener.onRefresh();
    			}
    			break;
    
    		default:
    			break;
    		}
    	}

    刷新完成之后我们需要收起这个下拉刷新的按钮,额,好吧,总的来说比较复杂了:

    /*
    	 * 收起下拉刷新的控件
    	 */
    	public void onRefreshComplete(boolean success) {
    		if (isLoadingMore) {// 正在加载更多...
    			mFooterView.setPadding(0, -mFooterViewHeight, 0, 0);// 隐藏脚布局
    			isLoadingMore = false;
    		} else {
    			mCurrrentState = STATE_PULL_REFRESH;
    			tvTitle.setText("下拉刷新");
    			ivArrow.setVisibility(View.VISIBLE);
    			pbProgress.setVisibility(View.INVISIBLE);
    
    			mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);// 隐藏
    
    			if (success) {
    				tvTime.setText("最后刷新时间:" + getCurrentTime());
    			}
    		}
    	}
    

    我们还可以看到上面有一个实时的时间,获取当前系统时间:

    /**
    	 * 获取当前时间
    	 */
    	public String getCurrentTime() {
    		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    		return format.format(new Date());
    	}
    
    	private boolean isLoadingMore;
    
    	@Override
    	public void onScrollStateChanged(AbsListView view, int scrollState) {
    		if (scrollState == SCROLL_STATE_IDLE
    				|| scrollState == SCROLL_STATE_FLING) {
    
    			if (getLastVisiblePosition() == getCount() - 1 && !isLoadingMore) {// 滑动到最后
    			//	System.out.println("到底了.....");
    				mFooterView.setPadding(0, 0, 0, 0);// 显示
    				setSelection(getCount() - 1);// 改变listview显示位置
    
    				isLoadingMore = true;
    
    				if (mListener != null) {
    					mListener.onLoadMore();
    				}
    			}
    		}
    	}

    在新闻详情页里面要设置一下下拉刷新监听:

    // 设置下拉刷新监听
    		lvList.setOnRefreshListener(new OnRefreshListener() {
    
    			@Override
    			public void onRefresh() {
    				getDataFromServer();
    			}
    
    			@Override
    			public void onLoadMore() {
    				if (mMoreUrl != null) {
    					getMoreDataFromServer();
    				} else {
    					Toast.makeText(mActivity, "最后一页了", Toast.LENGTH_SHORT)
    							.show();
    					lvList.onRefreshComplete(false);// 收起加载更多的布局
    				}
    			}
    		});

    这里刷新功能基本上实现了,这里只写出了关键代码。




  • 相关阅读:
    异常以及异常处理框架探析
    ArcGis Server10 for java初试
    C#制作鹰眼全过程(带注释)
    flex remoteobject 因默认设置而调用失败
    ExecutorService.submit(Callable).get()不并发执行
    学习《The Flex, Spring, and BlazeDS full stack》-1
    java.lang.NoSuchMethodError: org.hibernate.mapping.SimpleValue.<init>(Lorg/hibernate/mapping/Table;)V
    用内置jetty运行项目struts2提示找不到Action
    二分查找
    排序
  • 原文地址:https://www.cnblogs.com/sdksdk0/p/5585123.html
Copyright © 2020-2023  润新知