Android 帶阻尼回彈效果的ScorllView
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.FocusFinder;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.animation.AnimationUtils;
import android.view.animation.OvershootInterpolator;
import android.widget.FrameLayout;
import android. widget.Scroller;
import android.view.View.OnTouchListener;
import java.lang.reflect.Field;
import java.util.List;
/**
* Layout container for a view hierarchy that can be scrolled by the user,
* allowing it to be larger than the physical display. A ScrollView is a
* {@link FrameLayout}, meaning you should place one child in it containing the
* entire contents to scroll; this child may itself be a layout manager with a
* complex hierarchy of objects. A child that is often used is a
* {@link android.widget.LinearLayout} in a vertical orientation, presenting a vertical array
* of top-level items that the user can scroll through.
* <p>
* The {@link android.widget.TextView} class also takes care of its own scrolling, so does not
* require a ScrollView, but using the two together is possible to achieve the
* effect of a text view within a larger container.
* <p>
* ScrollView only supports vertical scrolling.
* <br/>仿Iphone的自動回彈動化的scrollView,直接做為容器像一般scrollView一樣使用即可
*/
public class OverScrollView extends FrameLayout implements OnTouchListener {
static final int ANIMATED_SCROLL_GAP = 250;
static final float MAX_SCROLL_FACTOR = 0.5f;
static final float OVERSHOOT_TENSION = 0.75f;
private long mLastScroll;
private final Rect mTempRect = new Rect();
private Scroller mScroller;
protected Context mContext;
Field mScrollYField;
Field mScrollXField;
boolean hasFailedObtainingScrollFields;
int prevScrollY;
boolean isInFlingMode = false;
DisplayMetrics metrics;
LayoutInflater inflater;
protected View child;
private Runnable overScrollerSpringbackTask;
/**
* Flag to indicate that we are moving focus ourselves. This is so the code
* that watches for focus changes initiated outside this ScrollView knows
* that it does not have to do anything.
*/
private boolean mScrollViewMovedFocus;
/**
* Position of the last motion event.
*/
private float mLastMotionY;
/**
* True when the layout has changed but the traversal has not come through
* yet. Ideally the view hierarchy would keep track of this for us.
*/
private boolean mIsLayoutDirty = true;
/**
* The child to give focus to in the event that a child has requested focus
* while the layout is dirty. This prevents the scroll from being wrong if
* the child has not been laid out before requesting focus.
*/
private View mChildToScrollTo = null;
/**
* True if the user is currently dragging this ScrollView around. This is
* not the same as 'is being flinged', which can be checked by
* mScroller.isFinished() (flinging begins when the user lifts his finger).
*/
private boolean mIsBeingDragged = false;
/**
* Determines speed during touch scrolling
*/
private VelocityTracker mVelocityTracker;
/**
* When set to true, the scroll view measure its child to make it fill the
* currently visible area.
*/
private boolean mFillViewport;
/**
* Whether arrow scrolling is animated.
*/
private boolean mSmoothScrollingEnabled = true;
private int mTouchSlop;
private int mMinimumVelocity;
private int mMaximumVelocity;
/**
* ID of the active pointer. This is used to retain consistency during
* drags/flings if multiple pointers are used.
*/
private int mActivePointerId = INVALID_POINTER;
/**
* Sentinel value for no current active pointer. Used by
* {@link #mActivePointerId}.
*/
private static final int INVALID_POINTER = -1;
private OnScrollChangedListener onScrollChangedListener;
public OverScrollView(Context context) {
this(context, null);
}
public OverScrollView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public OverScrollView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
initScrollView();
setFillViewport(true);
initBounce();
}
private void initBounce() {
metrics = this.mContext.getResources().getDisplayMetrics();
// init the bouncy scroller, and make sure the layout is being drawn
// after the top padding
mScroller = new Scroller(getContext(), new OvershootInterpolator(OVERSHOOT_TENSION));
overScrollerSpringbackTask = new Runnable() {
@Override
public void run() {
// scroll till after the padding
mScroller.computeScrollOffset();
scrollTo(0, mScroller.getCurrY());
if (!mScroller.isFinished()) {
post(this);
}
}
};
prevScrollY = getPaddingTop();
try {
mScrollXField = View.class.getDeclaredField("mScrollX");
mScrollYField = View.class.getDeclaredField("mScrollY");
} catch (Exception e) {
hasFailedObtainingScrollFields = true;
}
}
private void SetScrollY(int value) {
if (mScrollYField != null) {
try {
mScrollYField.setInt(this, value);
} catch (Exception e) {
}
}
}
private void SetScrollX(int value) {
if (mScrollXField != null) {
try {
mScrollXField.setInt(this, value);
} catch (Exception e) {
}
}
}
public void initChildPointer() {
child = getChildAt(0);
child.setPadding(0, 1500, 0, 1500);
}
@Override
protected float getTopFadingEdgeStrength() {
if (getChildCount() == 0) {
return 0.0f;
}
final int length = getVerticalFadingEdgeLength();
if (getScrollY() < length) {
return getScrollY() / (float) length;
}
return 1.0f;
}
@Override
protected float getBottomFadingEdgeStrength() {
if (getChildCount() == 0) {
return 0.0f;
}
final int length = getVerticalFadingEdgeLength();
final int bottomEdge = getHeight() - getPaddingBottom();
final int span = getChildAt(0).getBottom() - getScrollY() - bottomEdge;
if (span < length) {
return span / (float) length;
}
return 1.0f;
}
/**
* @return The maximum amount this scroll view will scroll in response to an
* arrow event.
*/
public int getMaxScrollAmount() {
return (int) (MAX_SCROLL_FACTOR * (getBottom() - getTop()));
}
private void initScrollView() {
mScroller = new Scroller(getContext());
setFocusable(true);
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
setWillNotDraw(false);
final ViewConfiguration configuration = ViewConfiguration.get(mContext);
mTouchSlop = configuration.getScaledTouchSlop();
mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
setOnTouchListener(this);
post(new Runnable() {
public void run() {
scrollTo(0, child.getPaddingTop());
}
});
}
@Override
public void addView(View child) {
if (getChildCount() > 0) {
throw new IllegalStateException("ScrollView can host only one direct child");
}
super.addView(child);
initChildPointer();
}
@Override
public void addView(View child, int index) {
if (getChildCount() > 0) {
throw new IllegalStateException("ScrollView can host only one direct child");
}
super.addView(child, index);
initChildPointer();
}
@Override
public void addView(View child, ViewGroup.LayoutParams params) {
if (getChildCount() > 0) {
throw new IllegalStateException("ScrollView can host only one direct child");
}
super.addView(child, params);
initChildPointer();
}
@Override
public void addView(View child, int index, ViewGroup.LayoutParams params) {
if (getChildCount() > 0) {
throw new IllegalStateException("ScrollView can host only one direct child");
}
super.addView(child, index, params);
}
/**
* @return Returns true this ScrollView can be scrolled
*/
private boolean canScroll() {
View child = getChildAt(0);
if (child != null) {
int childHeight = child.getHeight();
return getHeight() < childHeight + getPaddingTop() + getPaddingBottom();
}
return false;
}
/**
* Indicates whether this ScrollView's content is stretched to fill the
* viewport.
*
* @return True if the content fills the viewport, false otherwise.
*/
public boolean isFillViewport() {
return mFillViewport;
}
/**
* Indicates this ScrollView whether it should stretch its content height to
* fill the viewport or not.
*
* @param fillViewport True to stretch the content's height to the
* viewport's boundaries, false otherwise.
*/
public void setFillViewport(boolean fillViewport) {
if (fillViewport != mFillViewport) {
mFillViewport = fillViewport;
requestLayout();
}
}
/**
* @return Whether arrow scrolling will animate its transition.
*/
public boolean isSmoothScrollingEnabled() {
return mSmoothScrollingEnabled;
}
/**
* Set whether arrow scrolling will animate its transition.
*
* @param smoothScrollingEnabled whether arrow scrolling will animate its
* transition
*/
public void setSmoothScrollingEnabled(boolean smoothScrollingEnabled) {
mSmoothScrollingEnabled = smoothScrollingEnabled;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (!mFillViewport) {
return;
}
final int heightMode = MeasureSpec.getMode(heightMeasureSpec);
if (heightMode == MeasureSpec.UNSPECIFIED) {
return;
}
if (getChildCount() > 0) {
final View child = getChildAt(0);
int height = getMeasuredHeight();
if (child.getMeasuredHeight() < height) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, getPaddingLeft() + getPaddingRight(),
lp.width);
height -= getPaddingTop();
height -= getPaddingBottom();
int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
}
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
// Let the focused view and/or our descendants get the key first
return super.dispatchKeyEvent(event) || executeKeyEvent(event);
}
/**
* You can call this function yourself to have the scroll view perform
* scrolling from a key event, just as if the event had been dispatched to
* it by the view hierarchy.
*
* @param event The key event to execute.
* @return Return true if the event was handled, else false.
*/
public boolean executeKeyEvent(KeyEvent event) {
mTempRect.setEmpty();
if (!canScroll()) {
if (isFocused() && event.getKeyCode() != KeyEvent.KEYCODE_BACK) {
View currentFocused = findFocus();
if (currentFocused == this)
currentFocused = null;
View nextFocused = FocusFinder.getInstance().findNextFocus(this, currentFocused, View.FOCUS_DOWN);
return nextFocused != null && nextFocused != this && nextFocused.requestFocus(View.FOCUS_DOWN);
}
return false;
}
boolean handled = false;
if (event.getAction() == KeyEvent.ACTION_DOWN) {
switch (event.getKeyCode()) {
case KeyEvent.KEYCODE_DPAD_UP:
if (!event.isAltPressed()) {
handled = arrowScroll(View.FOCUS_UP);
} else {
handled = fullScroll(View.FOCUS_UP);
}
break;
case KeyEvent.KEYCODE_DPAD_DOWN:
if (!event.isAltPressed()) {
handled = arrowScroll(View.FOCUS_DOWN);
} else {
handled = fullScroll(View.FOCUS_DOWN);
}
break;
case KeyEvent.KEYCODE_SPACE:
pageScroll(event.isShiftPressed() ? View.FOCUS_UP : View.FOCUS_DOWN);
break;
}
}
return handled;
}
public boolean inChild(int x, int y) {
if (getChildCount() > 0) {
final int scrollY = getScrollY();
final View child = getChildAt(0);
return !(y < child.getTop() - scrollY || y >= child.getBottom() - scrollY || x < child.getLeft() || x >= child
.getRight());
}
return false;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
/*
* This method JUST determines whether we want to intercept the motion.
* If we return true, onMotionEvent will be called and we do the actual
* scrolling there.
*/
/*
* Shortcut the most recurring case: the user is in the dragging state
* and he is moving his finger. We want to intercept this motion.
*/
final int action = ev
相關推薦
Android 帶阻尼回彈效果的ScorllView
import android.content.Context;
import android.graphics.Color;
import android.graphics.Rect;
import android.util.AttributeSet;
impo
ScrollView實現阻尼回彈效果!
今天跟大夥簡紹個ScrollView的阻尼回彈!下拉到一定程度,可以回撥進行重新整理和進行操作等!
直接上程式碼了!
package com.***.fb**.widget;
import android.content.Context;
import
android ListView 仿IOS 回彈效果
最近看IOS的下拉效果感覺很不錯,當拉倒最上面和最下面的時候繼續拉動會有緩衝,想在android裡面也做一個,到網上到處找,沒有找到好的方法,據說android新的API對ListView有這樣的支援,感覺不是特別好用。
自己利用scroller實現了一下,廢話不多說了直接
Android HorizontalScrollView回彈效果
轉載記錄備份查閱
import android.annotation.SuppressLint;
import android.os.Build;
import android.util.Log;
import android.view.MotionEvent
Android滑動回彈效果
原理:
addHeaderView裡做的事:
1.測量出header的寬高,呼叫了measureView方法
2.設定LayoutParams,寬:MATCH_PARENT,高:10
3.設定topMargin的值為負的header的高度,即將header隱藏在螢幕最上方
Android中自定義仿IOS回彈效果的ListView
ios中有一個控制元件回彈的效果,比如listview ,拉動到第一條或者最後一條資料的時候,還可以繼續拉動,鬆手就回彈到原來位置,很贊,其實在android中實現起來也非常簡單,我們只需要重寫listview的下面兩個 方法即可
先上圖
@Override
pub
Android 自定義ScrollView 支援慣性滑動,慣性回彈效果。支援上拉載入更多
先講下原理:
ScrollView的子View 主要分為3部分:head頭部,滾動內容,fooder底部
我們實現慣性滑動,以及回彈,都是靠超過head或者fooder 就重新滾動到 ,內容的頂部或者底部。
之前看了Pulltorefresh 他是通過不斷改變 head或
android仿IOS頁面回彈效果
碼農同學們做過手機開發的相比一定對ios平臺頁面的上下回彈效果印象深刻,特別是android開發對此是各種嫉妒羨慕恨啊,在特效方面蘋果做的很好,做了很多,當然谷歌也不差,神馬特效咱們都能做出來,因為android開放更多,移植性也更好,so..我特麼手賤自己寫了一個上下拉動
Android ScrollView回彈效果(二)
上一篇文章說了那個效果不怎麼好,現在實現方法稍微變一下:
import android.content.Context;
import android.os.Handler;
import android.util.AttributeSet;
import android.
自定義帶滑動距離監控和仿iOS回彈效果的NestedScrollView
在最近的Support Library更新中(25.3.0),新增或者修復了許多東西,具體可以看revisions,其中有一個新增的動畫效果:SpringAnimation
即彈簧動畫,SpringAnimation是一個受SpringForce驅動的動畫。彈簧力限定
-webkit-overflow-scrolling 與滾動回彈效果.
插件 列表 卡住 快的 優雅 css 移動設備 分享 兼容性 參考來源:https://developer.mozilla.org/zh-CN/docs/Web/CSS/-webkit-overflow-scrolling
https://www.w3cways.
angual+mui 雙欄上拉加載,微信裏面禁用默認事件可用,可以防止瀏覽器回彈效果
apply length data mui this reat mobile ng- a10 //html 部分
p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 15.0px Consolas; color: #2eafa9
自定義ScrollView 實現上拉下拉的回彈效果--並且子控件中有Viewpager的情況
是否 AS abs pri tar utils lda animation ted
onInterceptTouchEvent就是對子控件中Viewpager的處理:左右滑動應該讓viewpager消費
1 public class MyScrollView ext
ios 下防止整個網頁滑動(阻尼回彈 . 瞞天過海,騙IOS,把阻尼回彈限制在滾動區div內
list ont 16px 一點 width sta 常見 沒有 手機app
下面是一個手機APP頁面,分成上中下三部分,最上面和最下面是固定的,中間可以滾動。這是常見的APP布局方式。
<style>
.box{
overflow: auto;
-
解決蘋果微信瀏覽器下拉回彈效果
.content是需要滑動的部分
var overscroll = function(el) {
el.addEventListener('touchstart', function()
移動端阻止瀏覽器中預設元素滑動回彈效果(橡皮筋效果)
在js檔案中加如下程式碼:
document.addEventListener('touchstart',function(e){
e.preventDefault(); //
JavaScript禁止微信瀏覽器下拉回彈效果
本文例項為大家分享了JavaScript禁止微信瀏覽器下拉回彈的效果
方法1:
<script
type="text/javascript">
var overscroll = function(el){
原來操控介面可以這麼簡單----安卓上下滑動縮放頂部圖片,左右滑動結束當前Activity,及View柔和回彈效果
先上效果圖:
上傳圖片不能超過2M,費了好大勁。每一張gif動的有點快,將就看。
首先說原理:
為activity的xml檔案根佈局新增setOnTouchListener。上下滑動和左右滑動的所有操作都是在OnTouchListener的onTouch方法中實現的,通過
Android ListView滑動回彈——overScrollBy
註解
/**
* Scroll the view with standard behavior for scrolling beyond the normal
* content boundaries. Views that call this met
實現ViewPager的回彈效果
為了能夠在ViewPager的第一頁和最後一頁左右滑動時候不顯得那麼生硬,通過重寫ViewPager類實現回彈效果。
程式碼很簡單,主要重寫onTouchEvent方法。
程式碼如下:
public class BounceBackViewPager