Android中实现 滑动时将指定View定位在顶部
参考一:
在项目开发中遇到这样的需求,需要实现scrollview顶部的悬停效果,实现原理非常简单,下面小编通过本文给大家分享实例代码,需要的朋友参考下
因项目中的需要实现ScrollView顶部的悬停,也不是太难便自己实现功能,话不多说,先上效果图
红色text一到顶上便会悬浮在上面,不会跟随scrollview的滑动而上滑。
原理:
原理其实很简单就是对view的gone和visible,写两个相同的要置顶的view,一个设置为gone,一个为visible,当可见的view超出屏幕范围的时候,将不可以的view设置为visible,不可见的view 与scrollview要同级,这样滑动的时候不会影响到view的位置。
直接上代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
<?xml version= "1.0" encoding= "utf-8" ?>
<RelativeLayout xmlns:android= "http://schemas.android.com/apk/res/android"
android:layout_width= "match_parent"
android:layout_height= "match_parent" >
<com.lanmai.ObservableScrollView
android:id= "@+id/scrollview"
android:layout_width= "match_parent"
android:layout_height= "match_parent"
>
<RelativeLayout
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical" >
<LinearLayout
android:layout_width= "match_parent"
android:layout_height= "match_parent"
android:orientation= "vertical" >
<!-- 中间就是填充的view就不写了-->
<!--指定要置顶的view-->
<TextView
android:id= "@+id/specific_text_view"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:background= "@android:color/holo_red_dark"
android:gravity= "center"
android:text= "text"
android:textSize= "40sp" />
<TextView
android:layout_width= "match_parent"
android:layout_height= "200dp"
android:background= "@android:color/darker_gray"
android:gravity= "center"
android:text= "text"
android:textSize= "40sp" />
</LinearLayout>
</RelativeLayout>
</com.lanmai.ObservableScrollView>
<!--指定要置顶的相同的view visibility设置为gone -->
<TextView
android:id= "@+id/specific_text_view_gone"
android:layout_width= "match_parent"
android:layout_height= "wrap_content"
android:background= "@android:color/holo_red_dark"
android:gravity= "center"
android:text= "text"
android:textSize= "40sp"
android:visibility= "gone" />
</RelativeLayout> |
接下来要重写scrollview,为什么要重写ScrollView,scrollview的滑动监听事件setOnScrollChangeListener 这个方法是在6.0以上才能用的。为了考虑低版本的的需求,要重写ScrollView把接口开放出来。
重写ScrollView
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
public
class ObservableScrollView extends ScrollView {
private ScrollViewListener scrollViewListener = null ;
public ObservableScrollView(Context context) {
super (context);
}
public ObservableScrollView(Context context, AttributeSet attrs,
int defStyle) {
super (context, attrs, defStyle);
}
public ObservableScrollView(Context context, AttributeSet attrs) {
super (context, attrs);
}
public void setScrollViewListener(ScrollViewListener scrollViewListener) {
this .scrollViewListener = scrollViewListener;
}
@Override
protected void onScrollChanged( int x, int
y, int oldx,
int oldy) {
super .onScrollChanged(x, y, oldx, oldy);
if (scrollViewListener != null ) {
scrollViewListener.onScrollChanged( this , x, y, oldx, oldy);
}
}
public interface ScrollViewListener {
void onScrollChanged(ScrollView scrollView, int x,
int y, int
oldx, int
oldy);
}
} |
我把重写的ScrollView命名为ObservableScrollView,重写三个构造方法,都是换汤不换药的作法,这里就不赘述。 最重要的是重写onScrollChanged这个方法,如何把滑动监听事件开放出去呢,其实也就是写一个监听回调,参数和onScrollChanged里面的的参数一样就可以了,当然主要不是用到这些参数,只是为了判断ScrollView的滑动事件,参数对于这个功并不是很重要。那这样,一个简单的自定义就写好了scrollview
如何去用?
用法也是挺简单的,直接上代码
1
2
3
4
5
6
7
8
9
10
|
@Override protected void onCreate(Bundle savedInstanceState) {
super .onCreate(savedInstanceState);
setContentView(R.layout.activity_scroll_view);
mTextView = ((TextView) findViewById(R.id.specific_text_view));
mScrollView = ((ObservableScrollView) findViewById(R.id.scrollview));
mVisibleTextView = ((TextView) findViewById(R.id.specific_text_view_gone));
mTextView.setOnClickListener( this );
mScrollView.setScrollViewListener( this );
}
|
这里onCreate方法里面的,也简单,拿到view 并且设置监听事件,当然,这里多实现了一个点击view置顶的功能,监听设置好以后,实现相应的接,接下来就是重头戏了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
@Override public void onScrollChanged(ScrollView scrollView, int x,
int y, int
oldx, int
oldy) {
int [] location = new int [ 2 ];
mTextView.getLocationOnScreen(location);
int xPosition = location[ 0 ];
int yPosition = location[ 1 ];
Log.d( "ScrollViewActivity" , "yPosition:" +
yPosition);
int statusBarHeight = getStatusBarHeight();
Log.d( "ScrollViewActivity" , "statusBarHeight:" +
statusBarHeight);
if (yPosition <= statusBarHeight) {
mVisibleTextView.setVisibility(View.VISIBLE);
} else {
mVisibleTextView.setVisibility(View.GONE);
}
}
|
onScrollChanged这个方法就是自己写的监听回调,里面的参数就是Scrollview滑动的时候回调出来的,里面的参数并不用去关心
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
int [] location = new int [ 2 ];
mTextView.getLocationOnScreen(location);
int xPosition = location[ 0 ];
int yPosition = location[ 1 ];
/* mTextView就是要悬浮的view,getLocationOnScreen(location)这个方法就是拿到view在屏幕中的位置 ,传入一个数组,最后得到的yPosition就是view在屏幕中的高度,这里面调用了native层的实现方式,所以数组能直接附上值*/
// 值得注意的是,拿到的这个高度还包括状态栏的高度。只要减掉就可以了,状态栏的高度获取获取附上代码:
public
int getStatusBarHeight() {
int result = 0 ;
int resourceId = getResources().getIdentifier( "status_bar_height" , "dimen" , "android" );
if (resourceId > 0 ) {
result = getResources().getDimensionPixelSize(resourceId);
}
return result;
} int statusBarHeight = getStatusBarHeight();
Log.d( "ScrollViewActivity" , "statusBarHeight:" +
statusBarHeight);
通过获取到的状态栏高度,如果小于状态栏的高度就表示已经滑出屏幕了,将要置顶的view设置为visibvle否则设置为gone
if (yPosition <= statusBarHeight) {
mVisibleTextView.setVisibility(View.VISIBLE);
} else {
mVisibleTextView.setVisibility(View.GONE);
}
|
这样scrollview的悬浮置顶的功能就实现了,这里我也给出点击view置顶的代码
1
2
3
4
5
6
7
8
|
@Override public void onClick(View v) {
int [] location = new int [ 2 ];
v.getLocationOnScreen(location);
int x = location[ 0 ];
int y = location[ 1 ];
mScrollView.scrollBy( 0 , location[ 1 ]
- getStatusBarHeight());
}
|
当然要缓慢的滑动过程用smoothScrollBy替代就可以了
结论:
实现这种效果,找对了思路就可以很容易的写出来了,这是一种比较简单的实现方式了,源码我就不贴出来了,基本已经都在了。
以上所述是小编给大家介绍的Android中使用ScrollView指定view的悬停效果,希望对大家有所帮助。。。
原文链接:http://blog.****.net/highwinzgs/article/details/69834309
参考二:
在刚刚完成的项目中,在一个页面中,用户体验师提出引用户操作的入住按钮要一直保留在页面当中,不管页面能滚动多长都得停留在页面的可视区域。最终实现效果如下图所示:
图片1 图片2
如图中的红色框中的view始终会停留在页面中,如果滑动至页面的顶部,会一直保留在顶部。
下面来说下具体的实现思路:
思路:其实整个页面当中一共有两个视觉效果一样的View,通过滑动的位置来进行View的隐藏和显示来达到这种效果。整个页面的在上下滑动的过程中可以总结为两个状态,状态A(如图1所示),view2在可视区域内时,view1不可见。状态B(如图2所示),view2滑过了可视区域,此种状态view1可见,view2不可见。
view显示和隐藏的时机:1、当页面向上滑动时,从状态A转变到状态B的瞬间,view1正好滑动至顶部与view2重合的瞬间,将view1显示;
2、当页面向下滑动,从状态B转变到状态A的瞬间,view2正好和view1重合的瞬间,将view1隐藏。
ViewAllShowLinearLayout类
- package org.sunday.uiext;
- import android.content.Context;
- import android.util.AttributeSet;
- import android.view.View;
- import android.widget.LinearLayout;
- import android.widget.ScrollView;
- /**
- * @author sunday
- * 2013-12-5
- * 邮箱:[email protected]
- * QQ:804935743
- */
- public class ViewAllShowLinearLayout extends LinearLayout {
- private View mView; // 顶部的View
- private ViewSwitchListener viewSwitchListener; // 对外钩子接口
- private ScrollView mScrollView;
- private boolean isFlag = true; //辅助判断变量
- public void initData(View view, ScrollView scrollview,
- ViewSwitchListener viewSwitchListener) {
- this.mView = view;
- this.mScrollView = scrollview;
- this.viewSwitchListener = viewSwitchListener;
- }
- public ViewAllShowLinearLayout(Context context) {
- super(context);
- init();
- }
- public ViewAllShowLinearLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- init();
- }
- private void init() {
- setOrientation(LinearLayout.VERTICAL);
- }
- @Override
- public void computeScroll() {
- if (mView != null && mScrollView != null && viewSwitchListener != null) {
- int y = mScrollView.getScrollY();
- if (isFlag) {
- int top = mView.getTop();
- if (y >= top) {
- viewSwitchListener.onViewShow();
- isFlag = false;
- }
- }
- if (!isFlag) {
- int bottom = mView.getBottom();
- if (y <= bottom - mView.getHeight()) {
- viewSwitchListener.onViewGone();
- isFlag = true;
- }
- }
- }
- }
- public interface ViewSwitchListener {
- public void onViewShow();
- public void onViewGone();
- }
- }
项目中的使用效果:
demo:http://download.****.net/detail/ff20081528/6664263
转载请说明出处:http://blog.****.net/ff20081528/article/details/17145113