android之浮动title

Activity定义使用的相关的属性:

/** 活动精选距离屏幕的座标 */
	private int[] locationActive = new int[2];
	/** title标题距离屏幕的座标 */
	private int locationTitleY;
	/** 是否手指向上滑动(startY>MoveY) */
	private boolean isMoveUp;
	/** 是否执行title显示或隐藏动画 */
	private boolean isRunAnim;
	/** 是否显示 */
	private boolean isTitleShow;
	/** title的高度 */
	int titleHeight;

初始化相关位置信息,:注必须是在加载完页面之后调用此代码,否则获取的location都为0

int[] locationTitle = new int[2];
		rlActTitleParent.getLocationOnScreen(locationTitle);
		titleHeight = getResources().getDimensionPixelSize(R.dimen.home_title_height);
		locationTitleY = locationTitle[1] + titleHeight;

location详解:http://blog.csdn.net/lvxiangan/article/details/19971509


lvWelfare.setOnMoveListener(new OnMoveListener() {

			@Override
			public void onMoveList(Boolean isShow) {// 滑动显示隐藏title
				isMoveUp = isShow;
				showTitle();
			}
		});
		lvWelfare.setOnScrollListenerExtra(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {// 这个方法只有松开手才会执行
				if (scrollState == SCROLL_STATE_IDLE) {// setOnMoveListener OnScrollListener结合滑动显示隐藏title
					showTitle();
				}
			}

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

			}
		});

/***
	 * 
	 * @description 显示title
	 * @author zhongwr
	 * @params
	 * @update 2016年1月28日 下午5:56:35
	 */
	private void showTitle() {
		if (isRunAnim) {
			return;
		}
		rlActiveTitleParent.getLocationOnScreen(locationActive);
		if (isMoveUp) {// 手指向下滑动(starty<MoveY)
			if (locationActive[1] > locationTitleY) {
				if (!isTitleShow) {
					isTitleShow = true;
					rlActTitleParent.setVisibility(View.VISIBLE);
					setShowTitleAnimator(true);
				}
			}
		} else {// 手指向上滑动:starty>MoveY
			if (locationActive[1] <= locationTitleY) {
				if (isTitleShow) {
					isTitleShow = false;
					// rlActTitleParent.setVisibility(View.GONE);
					setShowTitleAnimator(false);
				}
			}
		}
	}

/**
	 * 
	 * @description 设置动画
	 * @author zhongwr
	 * @params
	 * @update 2016年1月28日 下午6:00:45
	 */
	private void setShowTitleAnimator(final boolean isShow) {
		ValueAnimator animator;
		if (isShow) {// 显示
			animator = ValueAnimator.ofFloat(-titleHeight, 0).setDuration(200);
		} else {// 隐藏
			animator = ValueAnimator.ofFloat(0, -titleHeight).setDuration(200);
		}
		animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
			@Override
			public void onAnimationUpdate(ValueAnimator animation) {
				float translationY = (Float) animation.getAnimatedValue();
				// 设置控件rlActTitleParent沿Y移动动画,移动位置是translationY
				ViewHelper.setTranslationY(rlActTitleParent, translationY);
			}
		});

		animator.addListener(new AnimatorListener() {

			@Override
			public void onAnimationStart(Animator arg0) {
				isRunAnim = true;
			}

			@Override
			public void onAnimationRepeat(Animator arg0) {
			}

			@Override
			public void onAnimationEnd(Animator arg0) {
				isRunAnim = false;
				if (!isShow) {
					rlActTitleParent.setVisibility(View.GONE);
				}
			}

			@Override
			public void onAnimationCancel(Animator arg0) {
				isRunAnim = false;
			}
		});
		animator.start();
	}

lvWelfare:Listview(集合上拉加载更多,下拉刷新功能;以上定义的回调接口以及onTouchEvent()都在这个类中


public class PullToRefreshListView extends ListView implements OnScrollListener {
	private static final String TAG = "ElasticScrollView";
	private final static int RELEASE_To_REFRESH = 0;
	private final static int PULL_To_REFRESH = 1;
	private final static int REFRESHING = 2;
	private final static int DONE = 3;
	private final static int LOADING = 4;
	// 实际的padding的距离与界面上偏移距离的比例
	private final static int RATIO = 3;

	private int headContentWidth;
	private int headContentHeight;

	private LinearLayout innerLayout;
	private LinearLayout headView;
	private ProgressBar arrowImageView;
	private ProgressBar progressBar;
	private TextView tipsTextview;
	private TextView lastUpdatedTextView;
	private OnRefreshListener refreshListener;
	private OnMoveListener mOnMoveListener;
	private OnScrollStateChangedListener mScrollStateChangedListener;
	private boolean isRefreshable;
	private int state;

	private boolean isBack;

	// private RotateAnimation animation;
	// private RotateAnimation reverseAnimation;

	private boolean canReturn;
	private boolean isRecored;
	private int startY;
	private String down_str = "下拉刷新";
	private String release_str = "松开刷新";
	private OnPullUpListener pullUpListener;

	private Context mContext;

	public PullToRefreshListView(Context context) {
		super(context);
		init(context);
	}

	public PullToRefreshListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	private void init(Context context) {
		mContext = context;
		LayoutInflater inflater = LayoutInflater.from(context);
		View view = getFirstHeadView();
		if(view != null)
		{
			addHeaderView(view);
		}
		headView = (LinearLayout) inflater.inflate(R.layout.mylistview_head, null);
		arrowImageView = (ProgressBar) headView.findViewById(R.id.head_arrowImageView);
		progressBar = (ProgressBar) headView.findViewById(R.id.head_progressBar);
		tipsTextview = (TextView) headView.findViewById(R.id.head_tipsTextView);
		lastUpdatedTextView = (TextView) headView.findViewById(R.id.head_lastUpdatedTextView);
		measureView(headView);

		headContentHeight = headView.getMeasuredHeight();
		headContentWidth = headView.getMeasuredWidth();
		headView.setPadding(0, -1 * headContentHeight, 0, 0);
		headView.invalidate();

		Log.i("size", "width:" + headContentWidth + " height:" + headContentHeight);

		addHeaderView(headView);

		// animation = new RotateAnimation(0, -180,
		// Animation.RELATIVE_TO_SELF, 0.5f,
		// Animation.RELATIVE_TO_SELF, 0.5f);
		// animation.setInterpolator(new LinearInterpolator());
		// animation.setDuration(250);
		// animation.setFillAfter(true);
		//
		// reverseAnimation = new RotateAnimation(-180, 0,
		// Animation.RELATIVE_TO_SELF, 0.5f,
		// Animation.RELATIVE_TO_SELF, 0.5f);
		// reverseAnimation.setInterpolator(new LinearInterpolator());
		// reverseAnimation.setDuration(200);
		// reverseAnimation.setFillAfter(true);

		state = DONE;
		isRefreshable = false;
		canReturn = false;
	}
	
	public View getFirstHeadView()
	{
		return null;
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		try {
			if (isRefreshable) {
				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					if (getScrollY() == 0 && !isRecored) {
						isRecored = true;
						startY = (int) event.getY();
						Log.i(TAG, "在down时候记录当前位置‘");
					}
					break;
				case MotionEvent.ACTION_UP:
					if (state != REFRESHING && state != LOADING) {
						if (state == DONE) {
							// 什么都不做
						}
						if (state == PULL_To_REFRESH) {
							state = DONE;
							changeHeaderViewByState();
							onPullUp();
							Log.i(TAG, "由下拉刷新状态,到done状态");
						}
						if (state == RELEASE_To_REFRESH) {
							state = REFRESHING;
							changeHeaderViewByState();
							onRefresh();
							onPullUp();
							Log.i(TAG, "由松开刷新状态,到done状态");
						}
					}
					isRecored = false;
					isBack = false;

					break;
				case MotionEvent.ACTION_MOVE:
					int tempY = (int) event.getY();
					if (!isRecored && getScrollY() == 0) {
						Log.i(TAG, "在move时候记录下位置");
						isRecored = true;
						startY = tempY;
					} else {
						if (startY < tempY) {
							if (mOnMoveListener != null) {
								mOnMoveListener.onMoveList(true);
							}
						} else {
							if (mOnMoveListener != null) {
								mOnMoveListener.onMoveList(false);
							}
						}
					}
					if (state != REFRESHING && isRecored && state != LOADING
							&& PullToRefreshListView.this.getFirstVisiblePosition() == 0) {
						// 可以松手去刷新了
						if (state == RELEASE_To_REFRESH) {
							canReturn = true;

							if (((tempY - startY) / RATIO < headContentHeight) && (tempY - startY) > 0) {
								state = PULL_To_REFRESH;
								changeHeaderViewByState();
								Log.i(TAG, "由松开刷新状态转变到下拉刷新状态");
							}
							// 一下子推到顶了
							else if (tempY - startY <= 0) {
								state = DONE;
								changeHeaderViewByState();
								Log.i(TAG, "由松开刷新状态转变到done状态");
							} else {
								// 不用进行特别的操作,只用更新paddingTop的值就行了
							}
						}
						// 还没有到达显示松开刷新的时候,DONE或者是PULL_To_REFRESH状态
						if (state == PULL_To_REFRESH) {
							canReturn = true;

							// 下拉到可以进入RELEASE_TO_REFRESH的状态
							if ((tempY - startY) / RATIO >= headContentHeight) {
								state = RELEASE_To_REFRESH;
								isBack = true;
								changeHeaderViewByState();
								Log.i(TAG, "由done或者下拉刷新状态转变到松开刷新");
							}
							// 上推到顶了
							else if (tempY - startY <= 0) {
								state = DONE;
								changeHeaderViewByState();
								Log.i(TAG, "由DOne或者下拉刷新状态转变到done状态");
							}
						}

						// done状态下
						if (state == DONE) {
							if (tempY - startY > 0) {
								state = PULL_To_REFRESH;
								changeHeaderViewByState();
							}
						}

						// 更新headView的size
						if (state == PULL_To_REFRESH) {
							headView.setPadding(0, -1 * headContentHeight + (tempY - startY) / RATIO, 0, 0);

						}

						// 更新headView的paddingTop
						if (state == RELEASE_To_REFRESH) {
							headView.setPadding(0, (tempY - startY) / RATIO - headContentHeight, 0, 0);
						}
						if (canReturn) {
							canReturn = false;
							return true;
						}
					}
					break;
				}
			}
			return super.onTouchEvent(event);
		} catch (Exception ex) {
			ex.printStackTrace();
			return false;
		}
	}
	
	/**
	 * 显示“正在刷新”view
	 */
	public void showRefreshingView() {
		state = REFRESHING;
		changeHeaderViewByState();
	}

	// 当状态改变时候,调用该方法,以更新界面
	private void changeHeaderViewByState() {
		switch (state) {
		case RELEASE_To_REFRESH:
			arrowImageView.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);
			tipsTextview.setVisibility(View.VISIBLE);
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			// arrowImageView.clearAnimation();
			// arrowImageView.startAnimation(animation);

			tipsTextview.setText(release_str);

			Log.i(TAG, "当前状态,松开刷新");
			break;
		case PULL_To_REFRESH:
			progressBar.setVisibility(View.GONE);
			tipsTextview.setVisibility(View.VISIBLE);
			lastUpdatedTextView.setVisibility(View.VISIBLE);
			arrowImageView.clearAnimation();
			arrowImageView.setVisibility(View.VISIBLE);
			// 是由RELEASE_To_REFRESH状态转变来的
			if (isBack) {
				isBack = false;
				// arrowImageView.clearAnimation();
				// arrowImageView.startAnimation(reverseAnimation);

				tipsTextview.setText(down_str);
			} else {
				tipsTextview.setText(down_str);
			}
			Log.i(TAG, "当前状态,下拉刷新");
			break;

		case REFRESHING:

			headView.setPadding(0, 0, 0, 0);
			progressBar.setVisibility(View.VISIBLE);
			arrowImageView.clearAnimation();
			arrowImageView.setVisibility(View.GONE);
			tipsTextview.setText("正在刷新...");
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			Log.i(TAG, "当前状态,正在刷新...");
			break;
		case DONE:
			headView.setPadding(0, -1 * headContentHeight, 0, 0);
			progressBar.setVisibility(View.GONE);
			arrowImageView.clearAnimation();
			arrowImageView.destroyDrawingCache();
			progressBar.destroyDrawingCache();
			// arrowImageView.setImageResource(R.drawable.head_arrow);
			tipsTextview.setText(down_str);
			lastUpdatedTextView.setVisibility(View.VISIBLE);

			Log.i(TAG, "当前状态,done");
			break;
		}
	}

	private void measureView(View child) {
		ViewGroup.LayoutParams p = child.getLayoutParams();
		if (p == null) {
			p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
		}
		int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);
		int lpHeight = p.height;
		int childHeightSpec;
		if (lpHeight > 0) {
			childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
		} else {
			childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
		}
		child.measure(childWidthSpec, childHeightSpec);
	}

	public void setOnMoveListener(OnMoveListener moveListener) {
		this.mOnMoveListener = moveListener;
	}

	public interface OnMoveListener {
		public void onMoveList(Boolean isShow);
	}

	public void setonRefreshListener(OnRefreshListener refreshListener) {
		this.refreshListener = refreshListener;
		isRefreshable = true;
	}

	public interface OnRefreshListener {
		public void onRefresh();
	}

	@SuppressWarnings("deprecation")
	public void onRefreshComplete() {
		state = DONE;
		lastUpdatedTextView.setText("最近更新:" + new Date().toLocaleString());
		changeHeaderViewByState();
		invalidate();
		scrollTo(0, 0);
	}

	public void setDownStr(String s) {
		down_str = s;
	}

	public void setReleaseStr(String s) {
		release_str = s;
	}

	private void onRefresh() {
		if (refreshListener != null) {
			if (null != mLoadingMoreListener) {
				setFootVisiable(View.GONE, View.GONE, llFootLoadingParent.getVisibility());
			}
			refreshListener.onRefresh();
		}
	}

	public void addChild(View child) {
		innerLayout.addView(child);
	}

	public void addChild(View child, int position) {
		innerLayout.addView(child, position);
	}

	public int getState() {
		return state;
	}

	public void setState(int state) {
		this.state = state;
	}

	private void onPullUp() {
		if (pullUpListener != null) {
			pullUpListener.onPullUp();
		}
	}

	public void setOnPullUpListener(OnPullUpListener pullUpListener) {
		this.pullUpListener = pullUpListener;
	}

	public interface OnPullUpListener {
		public void onPullUp();
	}

	/**
	 * xml加载完之后会调用这个方法
	 * */
	@Override
	protected void onFinishInflate() {
		super.onFinishInflate();

	}

	/** 加载更多的底部 */
	private View mFootView;
	private RelativeLayout rlFootNoMoreParent;
	private LinearLayout llFootLoadingParent;
	/** 加载更多的监听器 */
	private OnLoadingMoreListener mLoadingMoreListener;
	/** 加载出错时,点击加载更多 */
	private Button btnReload;
	/**没有更多*/
	private TextView tvNoMoreText;

	/** 设置上拉加载更多可用 */
	public void setLoadingMoreEnable(OnLoadingMoreListener loadingMoreListener) {
		this.mLoadingMoreListener = loadingMoreListener;
		// 添加底部
		mFootView = LayoutInflater.from(mContext).inflate(R.layout.get_more, null);
		rlFootNoMoreParent = (RelativeLayout) this.mFootView.findViewById(R.id.rl_no_more_parent);
		llFootLoadingParent = (LinearLayout) this.mFootView.findViewById(R.id.ll_loading_parent);
		tvNoMoreText = (TextView) this.mFootView.findViewById(R.id.foot_layout_no_more_text);
		btnReload = (Button) this.mFootView.findViewById(R.id.bt_load);
		btnReload.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				if ("加载失败,点击重试".equals(btnReload.getText().toString()) && null != mLoadingMoreListener) {
					mLoadingMoreListener.onLoadingMore(PullToRefreshListView.this, OnScrollListener.SCROLL_STATE_IDLE);
				}
			}
		});
		// 首次加载应该是隐藏的
		// setFootVisiable(View.VISIBLE, View.GONE, View.GONE);
		addFooterView(this.mFootView);

		// 添加底部之后就可以上拉加载更多 :这个监听器,可以消除上滑的时候不加载图片
		setOnScrollListener(new PauseOnScrollListener(ImageLoader.getInstance(), true, true, this));

	}

	/**
	 * 
	 * @description 设置没有更多文本颜色值
	 * @author zhongwr
	 * @update 2015-12-14 下午8:26:07
	 */
	public void setNoMoreTextColor(int colorResId) {
		if (null != tvNoMoreText) {
			tvNoMoreText.setTextColor(colorResId);
		}
	}
	public View getFootView() {
		return mFootView;
	}

	public boolean removeFootView() {
		return removeFooterView(this.mFootView);
	}

	/**
	 * 
	 * @description 加载完成
	 * @param isNoMore
	 *            是否没有更多了
	 * @author zhongwr
	 * @update 2015-11-6 上午1:08:15
	 */
	public void setOnLoadingMoreCompelete(boolean isNoMore) {
		setOnLoadingMoreCompelete(isNoMore, false);
	}
	
	public void setOnLoadingMoreCompelete() {
		setFootVisiable(View.GONE, View.GONE, View.GONE);
		this.isLoadingMore = false;
	}

	/**
	 * 
	 * @description 加载完成
	 * @param isNoMore
	 *            是否没有更多了
	 * @param isLoadingMoreFailed
	 *            加载更多时出错
	 * @author zhongwr
	 * @update 2015-11-6 上午1:08:15
	 */
	public void setOnLoadingMoreCompelete(boolean isNoMore, boolean isLoadingMoreFailed) {
		if (!isLoadingMoreFailed) {
			if (!"加载更多...".equals(btnReload.getText().toString())) {
				btnReload.setText("加载更多...");
			}
			if (isNoMore) {
				setFootVisiable(View.VISIBLE, View.VISIBLE, View.GONE);
			} else {
				setFootVisiable(View.VISIBLE, View.GONE, View.VISIBLE);
			}
		} else {// 加载失败,提示点击重试
			btnReload.setText("加载失败,点击重试");
			setFootVisiable(View.VISIBLE, View.GONE, View.VISIBLE);
		}
		this.isLoadingMore = false;
	}

	/***
	 * 
	 * @description 用于下拉刷新时,隐藏底部
	 * @author zhongwr
	 * @update 2015-11-25 下午5:24:51
	 */
	public void hiddenFootView() {
		if (null != mFootView) {
			isLoadingMore = false;
			mFootView.setVisibility(View.GONE);
		}
	}

	/**
	 * 
	 * @description 显示底部
	 * @author zhongwr
	 * @params
	 * @update 2016年1月4日 下午4:16:06
	 */
	public void showFootView() {
		if (null != mFootView) {
			mFootView.setVisibility(View.VISIBLE);
		}
	}
	/***
	 * 
	 * @description 设置底部可见:加载更多或没有更多
	 * @author zhongwr
	 * @param footView
	 *            这个底部是否可见
	 * @param footNoMoreParent
	 *            没有更多是否可见
	 * @param footLoadingParent
	 *            加载更多是否可见
	 * @update 2015年9月24日 上午11:26:32
	 */
	private void setFootVisiable(int footView, int footNoMoreParent, int footLoadingParent) {
		if (null != mFootView) {
			if (footView != mFootView.getVisibility()) {
				mFootView.setVisibility(footView);
			}
			// 整个底部可见,设置子布局是否可见
			if (footNoMoreParent != rlFootNoMoreParent.getVisibility()) {
				this.rlFootNoMoreParent.setVisibility(footNoMoreParent);
			}
			if (footLoadingParent != llFootLoadingParent.getVisibility()) {
				llFootLoadingParent.setVisibility(footLoadingParent);
			}
		}
	}

	/** 是否加载更多 */
	private boolean isLoadingMore;

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
		if(mOnScrollListenerExtra != null)
		{
			mOnScrollListenerExtra.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
		}
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		// 不是首页&历史数据没有加载完&最后一天item&上一次已经加载完成
		Logcat.dLog("isLoadingMore = " + (view.getLastVisiblePosition() == view.getCount() - 1) + " idle = "
				+ (scrollState == SCROLL_STATE_IDLE) + " done = " + (state == DONE) + " isLoadingMore = "
				+ isLoadingMore);
		Logcat.dLog("rlFootNoMoreParent = "+(rlFootNoMoreParent.getVisibility() == View.GONE));
		if (rlFootNoMoreParent.getVisibility() == View.GONE && view.getLastVisiblePosition() == view.getCount() - 1 && scrollState == SCROLL_STATE_IDLE && state == DONE
				&& !isLoadingMore) {
			isLoadingMore = true;
			setFootVisiable(View.VISIBLE, View.GONE, View.VISIBLE);
			if (null != mLoadingMoreListener) {
				mLoadingMoreListener.onLoadingMore(view, scrollState);
			}
		}
		// 实现滑动状态改变事件
		if (mScrollStateChangedListener != null) {
			mScrollStateChangedListener.onScrollStateChanged(view, scrollState);
		}
		
		if(mOnScrollListenerExtra != null)
		{
			mOnScrollListenerExtra.onScrollStateChanged(view, scrollState);
		}
	}
	
	/**
	 * @Description 增加ListView滑动状态改变监听 接口
	 * @author chenxinghong
	 * @date 2015-12-17
	 */
	public interface OnScrollStateChangedListener {
		public void onScrollStateChanged(AbsListView view, int scrollState);
	}
	
	public void setOnScrollStateChangedListener(OnScrollStateChangedListener listener) {
		this.mScrollStateChangedListener = listener;
	}
	
	private OnScrollListener mOnScrollListenerExtra;
	
	public void setOnScrollListenerExtra(OnScrollListener listener) {
		this.mOnScrollListenerExtra = listener;
	}
	
	/***
	 * 加载更多的接口
	 * 
	 * @author zhongwr
	 * @update 2015年9月28日 下午6:03:35
	 */
	public interface OnLoadingMoreListener {
		public void onLoadingMore(AbsListView view, int scrollState);
	}
}




发布了68 篇原创文章 · 获赞 38 · 访问量 25万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章