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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章