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
     xmlns:android= "http://schemas.android.com/apk/res/android"
     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.csdn.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类

[java]  view plain  copy
  1. package org.sunday.uiext;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.view.View;  
  6. import android.widget.LinearLayout;  
  7. import android.widget.ScrollView;  
  8.   
  9. /** 
  10.  * @author sunday  
  11.  * 2013-12-5  
  12.  * 邮箱:zhengchao1937@163.com  
  13.  * QQ:804935743 
  14.  */  
  15. public class ViewAllShowLinearLayout extends LinearLayout {  
  16.   
  17.     private View mView; // 顶部的View  
  18.     private ViewSwitchListener viewSwitchListener; // 对外钩子接口  
  19.     private ScrollView mScrollView;  
  20.     private boolean isFlag = true;      //辅助判断变量  
  21.   
  22.     public void initData(View view, ScrollView scrollview,  
  23.             ViewSwitchListener viewSwitchListener) {  
  24.         this.mView = view;  
  25.         this.mScrollView = scrollview;  
  26.         this.viewSwitchListener = viewSwitchListener;  
  27.     }  
  28.   
  29.     public ViewAllShowLinearLayout(Context context) {  
  30.         super(context);  
  31.         init();  
  32.     }  
  33.   
  34.     public ViewAllShowLinearLayout(Context context, AttributeSet attrs) {  
  35.         super(context, attrs);  
  36.         init();  
  37.     }  
  38.   
  39.     private void init() {  
  40.         setOrientation(LinearLayout.VERTICAL);  
  41.     }  
  42.   
  43.     @Override  
  44.     public void computeScroll() {  
  45.         if (mView != null && mScrollView != null && viewSwitchListener != null) {  
  46.             int y = mScrollView.getScrollY();  
  47.             if (isFlag) {  
  48.                 int top = mView.getTop();  
  49.                 if (y >= top) {  
  50.                     viewSwitchListener.onViewShow();  
  51.                     isFlag = false;  
  52.                 }  
  53.             }  
  54.             if (!isFlag) {  
  55.                 int bottom = mView.getBottom();  
  56.                 if (y <= bottom - mView.getHeight()) {  
  57.                     viewSwitchListener.onViewGone();  
  58.                     isFlag = true;  
  59.                 }  
  60.             }  
  61.         }  
  62.     }  
  63.   
  64.     public interface ViewSwitchListener {  
  65.         public void onViewShow();  
  66.         public void onViewGone();  
  67.     }  
  68. }  

项目中的使用效果:

 

demo:http://download.csdn.net/detail/ff20081528/6664263
 

 

转载请说明出处:http://blog.csdn.net/ff20081528/article/details/17145113



  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android实现顶部滑动菜单可以使用ViewPager和TabLayout配合使用,具体步骤如下: 1.在XML布局文件添加ViewPager和TabLayout控件。 2.在Activity或Fragment初始化ViewPager和TabLayout控件,并设置ViewPager的适配器。 3.创建Fragment类作为ViewPager的子页面,将需要展示的内容添加到Fragment的布局文件。 4.在Activity或Fragment设置TabLayout与ViewPager的联动,即使用TabLayout的setupWithViewPager()方法将TabLayout与ViewPager绑定。 5.在TabLayout添加需要展示的菜单项,并设置TabLayout的样式。 6.在ViewPager的适配器返回对应位置的Fragment实例。 7.在Fragment设置需要展示的内容,例如ListView、RecyclerView等。 8.运行程序,查看效果。 示例代码: activity_main.xml ``` <androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" android:theme="?attr/actionBarTheme"/> <com.google.android.material.tabs.TabLayout android:id="@+id/tab_layout" android:layout_width="match_parent" android:layout_height="wrap_content"/> <androidx.viewpager.widget.ViewPager android:id="@+id/view_pager" android:layout_width="match_parent" android:layout_height="match_parent"/> ``` MainActivity.java ``` public class MainActivity extends AppCompatActivity { private Toolbar toolbar; private TabLayout tabLayout; private ViewPager viewPager; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); viewPager = findViewById(R.id.view_pager); setupViewPager(viewPager); tabLayout = findViewById(R.id.tab_layout); tabLayout.setupWithViewPager(viewPager); } private void setupViewPager(ViewPager viewPager) { ViewPagerAdapter adapter = new ViewPagerAdapter(getSupportFragmentManager()); adapter.addFragment(new Fragment1(), "菜单1"); adapter.addFragment(new Fragment2(), "菜单2"); adapter.addFragment(new Fragment3(), "菜单3"); viewPager.setAdapter(adapter); } private static class ViewPagerAdapter extends FragmentPagerAdapter { private final List<Fragment> fragmentList = new ArrayList<>(); private final List<String> fragmentTitleList = new ArrayList<>(); ViewPagerAdapter(FragmentManager fragmentManager) { super(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); } @NonNull @Override public Fragment getItem(int position) { return fragmentList.get(position); } @Override public int getCount() { return fragmentList.size(); } void addFragment(Fragment fragment, String title) { fragmentList.add(fragment); fragmentTitleList.add(title); } @Nullable @Override public CharSequence getPageTitle(int position) { return fragmentTitleList.get(position); } } } ``` Fragment1.java ``` public class Fragment1 extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment1, container, false); // 设置需要展示的内容,例如ListView、RecyclerView等 return view; } } ``` 注意:以上代码的布局文件和Fragment类仅作为示例,具体实现应根据需求进行调整。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值