/** * 根据当前ListView的滚动状态来设定 {@link #ableToPull} * 的值,每次都需要在onTouch中第一个执行,这样可以判断出当前应该是滚动ListView,还是应该进行下拉。 * * @param event */ private void setIsAbleToPull(View view, MotionEvent event) { boolean oldVal = this.ableToPull; this.ableToPull = this.pullableView.isPullable(view, event); if (this.ableToPull) { if (oldVal == false) { yDown = event.getRawY(); } } else if (headerLayoutParams.topMargin != hideHeaderHeight) { headerLayoutParams.topMargin = hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } if (pullableView.getView() instanceof ListView) { View firstChild = ((ListView) pullableView.getView()).getChildAt(0); if (firstChild != null) { int firstVisiblePos = ((ListView) pullableView.getView()).getFirstVisiblePosition(); if (firstVisiblePos == 0 && firstChild.getTop() == 0) { if (!ableToPull) { yDown = event.getRawY(); } // 如果首个元素的上边缘,距离父布局值为0,就说明ListView滚动到了最顶部,此时应该允许下拉刷新 ableToPull = true; } else { if (headerLayoutParams.topMargin != hideHeaderHeight) { headerLayoutParams.topMargin = hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } ableToPull = false; } } else { // 如果ListView中没有元素,也应该允许下拉刷新 ableToPull = true; } } }
protected void updateMargins() { //noinspection ConstantConditions final int margin = getResources().getDimensionPixelSize(R.dimen.space_normal); final boolean titleVisible = title_TV.getVisibility() == VISIBLE; final boolean secondaryTitleVisible = secondaryTitle_TV.getVisibility() == VISIBLE; final boolean subTitleVisible = subTitle_TV.getVisibility() == VISIBLE; final boolean contentVisible = content_FL.getVisibility() == VISIBLE; final boolean iconVisible = icon_IV.getVisibility() == VISIBLE; MarginLayoutParams lp = (MarginLayoutParams) subTitle_TV.getLayoutParams(); //noinspection ConstantConditions lp.topMargin = titleVisible || secondaryTitleVisible ? margin : 0; lp = (MarginLayoutParams) content_FL.getLayoutParams(); //noinspection ConstantConditions lp.topMargin = titleVisible || secondaryTitleVisible || subTitleVisible ? margin : 0; lp = (MarginLayoutParams) icon_IV.getLayoutParams(); //noinspection ConstantConditions lp.topMargin = titleVisible || secondaryTitleVisible || subTitleVisible ? margin : 0; lp = (MarginLayoutParams) listContainer_LL.getLayoutParams(); //noinspection ConstantConditions lp.topMargin = titleVisible || secondaryTitleVisible || subTitleVisible || contentVisible || iconVisible ? margin : 0; }
@Override protected void onLayout(boolean changed, int l, int t, int r, int b) { if (log.isDebugEnabled()) { log.debug("onLayout ..."); } super.onLayout(changed, l, t, r, b); if (changed && (headerLayoutParams == null)) { hideHeaderHeight = -header.getHeight(); if (log.isDebugEnabled()) { log.debug("init Layout params, hideHeaderHeight :" + hideHeaderHeight); } headerLayoutParams = (MarginLayoutParams) header.getLayoutParams(); headerLayoutParams.topMargin = hideHeaderHeight; if (!this.pendingTasks.isEmpty()) { for (AsyncTask<Void, Integer, Integer> task : this.pendingTasks) { task.execute(); } this.pendingTasks.clear(); } } else { if (log.isDebugEnabled()) { log.debug("onLayout, hideHeaderHeight :" + headerLayoutParams.topMargin); } // header.setLayoutParams(headerLayoutParams); } }
/** 当ListView被触摸时调用,其中处理了各种下拉刷新的具体逻辑。 */ @Override public boolean onTouch(View v, MotionEvent event) { setIsAbleToPull(event); if (ableToPull) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: yDown = event.getRawY(); break; case MotionEvent.ACTION_MOVE: float yMove = event.getRawY(); int distance = (int) (yMove - yDown); // 如果手指是下滑状态,并且下拉头是完全隐藏的,就屏蔽下拉事件 if (distance <= 0 && headerLayoutParams.topMargin <= hideHeaderHeight) { return false; } if (distance < touchSlop) { return false; } if (currentStatus != STATUS_REFRESHING) { if (headerLayoutParams.topMargin > 0) { currentStatus = STATUS_RELEASE_TO_REFRESH; } else { currentStatus = STATUS_PULL_TO_REFRESH; } // 通过偏移下拉头的topMargin值,来实现下拉效果 headerLayoutParams.topMargin = (distance / 2) + hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } break; case MotionEvent.ACTION_UP: default: if (currentStatus == STATUS_RELEASE_TO_REFRESH) { // 松手时如果是释放立即刷新状态,就去调用正在刷新的任务 new RefreshingTask().execute(); } else if (currentStatus == STATUS_PULL_TO_REFRESH) { // 松手时如果是下拉状态,就去调用隐藏下拉头的任务 new HideHeaderTask().execute(); } break; } // 时刻记得更新下拉头中的信息 if (currentStatus == STATUS_PULL_TO_REFRESH || currentStatus == STATUS_RELEASE_TO_REFRESH) { updateHeaderView(); // 当前正处于下拉或释放状态,要让ListView失去焦点,否则被点击的那一项会一直处于选中状态 listView.setPressed(false); listView.setFocusable(false); listView.setFocusableInTouchMode(false); lastStatus = currentStatus; // 当前正处于下拉或释放状态,通过返回true屏蔽掉ListView的滚动事件 return true; } } return false; }
/** 进行一些关键性的初始化操作,比如:将下拉头向上偏移进行隐藏,给ListView注册touch事件。 */ @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { super.onLayout(changed, l, t, r, b); if (changed && !loadOnce) { hideHeaderHeight = -header.getHeight(); headerLayoutParams = (MarginLayoutParams) header.getLayoutParams(); headerLayoutParams.topMargin = hideHeaderHeight; listView = (ListView) getChildAt(1); listView.setOnTouchListener(this); loadOnce = true; } }
// Wrapper around setting the header offset in different ways depending on // the API version @SuppressLint("NewApi") private void setHeaderOffet(int offset) { if (mHeaderOffset == null || mHeaderOffset != offset) { mHeaderOffset = offset; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { mHeader.setTranslationY(mHeaderOffset); } else { MarginLayoutParams params = (MarginLayoutParams) mHeader.getLayoutParams(); params.topMargin = mHeaderOffset; mHeader.setLayoutParams(params); } } }
/** 设置未读消息偏移,原点为文字的右上角.当控件高度固定,消息提示位置易控制,显示效果佳 */ public void setMsgMargin(int position, float leftPadding, float bottomPadding) { if (position >= mTabCount) { position = mTabCount - 1; } View tabView = mTabsContainer.getChildAt(position); MsgView tipView = (MsgView) tabView.findViewById(R.id.rtv_msg_tip); if (tipView != null) { TextView tv_tab_title = (TextView) tabView.findViewById(R.id.tv_tab_title); mTextPaint.setTextSize(mTextsize); float textWidth = mTextPaint.measureText(tv_tab_title.getText().toString()); float textHeight = mTextPaint.descent() - mTextPaint.ascent(); MarginLayoutParams lp = (MarginLayoutParams) tipView.getLayoutParams(); lp.leftMargin = mTabWidth >= 0 ? (int) (mTabWidth / 2 + textWidth / 2 + dp2px(leftPadding)) : (int) (mTabPadding + textWidth + dp2px(leftPadding)); lp.topMargin = mHeight > 0 ? (int) (mHeight - textHeight) / 2 - dp2px(bottomPadding) : 0; tipView.setLayoutParams(lp); } }
/** * 根据当前ListView的滚动状态来设定 {@link #ableToPull} * 的值,每次都需要在onTouch中第一个执行,这样可以判断出当前应该是滚动ListView,还是应该进行下拉。 * * @param event */ private void setIsAbleToPull(MotionEvent event) { View firstChild = listView.getChildAt(0); if (firstChild != null) { int firstVisiblePos = listView.getFirstVisiblePosition(); if (firstVisiblePos == 0 && firstChild.getTop() == 0) { if (!ableToPull) { yDown = event.getRawY(); } // 如果首个元素的上边缘,距离父布局值为0,就说明ListView滚动到了最顶部,此时应该允许下拉刷新 ableToPull = true; } else { if (headerLayoutParams.topMargin != hideHeaderHeight) { headerLayoutParams.topMargin = hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } ableToPull = false; } } else { // 如果ListView中没有元素,也应该允许下拉刷新 ableToPull = true; } }
private void applyMarginInsets( MarginLayoutParams lp, Object insets, int drawerGravity, boolean topOnly) { WindowInsets wi = (WindowInsets) insets; if (drawerGravity == Gravity.LEFT) { wi = wi.replaceSystemWindowInsets( wi.getSystemWindowInsetLeft(), wi.getSystemWindowInsetTop(), 0, wi.getSystemWindowInsetBottom()); } else if (drawerGravity == Gravity.RIGHT) { wi = wi.replaceSystemWindowInsets( 0, wi.getSystemWindowInsetTop(), wi.getSystemWindowInsetRight(), wi.getSystemWindowInsetBottom()); } lp.leftMargin = wi.getSystemWindowInsetLeft(); lp.topMargin = topOnly ? 0 : wi.getSystemWindowInsetTop(); lp.rightMargin = wi.getSystemWindowInsetRight(); lp.bottomMargin = wi.getSystemWindowInsetBottom(); }
/** 当ListView被触摸时调用,其中处理了各种下拉刷新的具体逻辑。 */ @Override public boolean onTouch(View v, MotionEvent event) { setIsAbleToPull(v, event); boolean retVal = false; if (ableToPull) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: yDown = event.getRawY(); // if(log.isDebugEnabled()){ // log.debug("Touch down, y position :"+yDown); // } break; case MotionEvent.ACTION_MOVE: float yMove = event.getRawY(); int distance = (int) (yMove - yDown); // if(log.isDebugEnabled()){ // log.debug("Touch down and move, y position :"+yMove+", move distance :"+distance); // } // 如果手指是下滑状态,并且下拉头是完全隐藏的,就屏蔽下拉事件 if (distance <= 0 && headerLayoutParams.topMargin <= hideHeaderHeight) { return false; } if (distance < touchSlop) { return false; } if (!pullStarted) { // if(log.isDebugEnabled()){ // log.debug("Pull started, touchSlop = "+touchSlop); // } pullableView.pullStarted(v); pullStarted = true; } retVal = true; if (currentStatus != STATUS_REFRESHING) { if (headerLayoutParams.topMargin > 0) { currentStatus = STATUS_RELEASE_TO_REFRESH; } else { currentStatus = STATUS_PULL_TO_REFRESH; } // 通过偏移下拉头的topMargin值,来实现下拉效果 headerLayoutParams.topMargin = (distance / 2) + hideHeaderHeight; header.setLayoutParams(headerLayoutParams); } break; case MotionEvent.ACTION_UP: default: if (pullStarted) { pullableView.pullEnded(v); pullStarted = false; retVal = true; } if (currentStatus == STATUS_RELEASE_TO_REFRESH) { // 松手时如果是释放立即刷新状态,就去调用正在刷新的任务 setOnRefreshing(true); } else if (currentStatus == STATUS_PULL_TO_REFRESH) { // 松手时如果是下拉状态,就去调用隐藏下拉头的任务 hideHeader(); } break; } // 时刻记得更新下拉头中的信息 if (currentStatus == STATUS_PULL_TO_REFRESH || currentStatus == STATUS_RELEASE_TO_REFRESH) { updateHeaderView(); // 当前正处于下拉或释放状态,要让ListView失去焦点,否则被点击的那一项会一直处于选中状态 pullableView.getView().setPressed(false); pullableView.getView().setFocusable(false); pullableView.getView().setFocusableInTouchMode(false); lastStatus = currentStatus; // 当前正处于下拉或释放状态,通过返回true屏蔽掉ListView的滚动事件 } } return retVal; }
private void setMargin(int top) { headerMargins.topMargin = top; LayoutParams params = new LayoutParams(headerMargins); header.setLayoutParams(params); }
package com.chang.news.util;