经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 移动开发 » Android » 查看文章
利用HorizontalScrollView实现滑动页面时的缩放效果
来源:jb51  时间:2018/11/25 19:38:53  对本文有异议

在前面的文章中也有关于 HorizontalScrollView 的使用:Android使用HorizontalScrollView实现水平滚动

这里主要实现的是向右滑动时,左侧的视图有逐渐放大,也会越来越清晰;向左滑动时,左侧的视图逐渐减小,逐渐变的模糊,且不移出屏幕左边缘的效果。效果如下(可以在主页面上的右侧向右滑动都可以实现该效果):

这里需要用到自定义的 HorizontalScrollView ,让其作为布局文件的根标签。HorizontalScrollView 里面只能有一个子组件,所以要把左侧的视图布局文件包含在 HorizontalScrollView 的子组件里面。

activity_main.xml :

  1. <com.crazy.reduce.ReduceSideslip xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:id="@+id/reduce_lay"
  4. android:layout_width="wrap_content"
  5. android:layout_height="match_parent"
  6. android:background="@drawable/bg"
  7. android:scrollbars="none"
  8. tools:context="com.crazy.reduce.MainActivity" >
  9. <LinearLayout
  10. android:layout_width="wrap_content"
  11. android:layout_height="match_parent"
  12. android:orientation="horizontal" >
  13. <include layout="@layout/item" />
  14. <LinearLayout
  15. android:layout_width="match_parent"
  16. android:layout_height="match_parent"
  17. android:background="@drawable/bg_01" >
  18. <Button
  19. android:layout_width="wrap_content"
  20. android:layout_height="wrap_content"
  21. android:onClick="toggleMenu"
  22. android:text="点击" />
  23. </LinearLayout>
  24. </LinearLayout>
  25. </com.crazy.reduce.ReduceSideslip>

在 item.xml 布局文件的右边有个 button 按钮,这些都在 HorizontalScrollView 的子组件当中。而 item.xml 究竟是怎样的布局也都不会影响到整个的滑动。

item.xml :

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <LinearLayout
  6. android:layout_width="match_parent"
  7. android:layout_height="wrap_content"
  8. android:layout_centerHorizontal="true"
  9. android:orientation="vertical" >
  10. <Button
  11. android:id="@+id/bt_b"
  12. android:layout_width="wrap_content"
  13. android:layout_height="wrap_content"
  14. android:layout_marginTop="50dp"
  15. android:text="一个不同的按钮" />
  16. <ImageView
  17. android:id="@+id/img"
  18. android:layout_width="wrap_content"
  19. android:layout_height="match_parent"
  20. android:scaleType="centerCrop"
  21. android:src="@drawable/bg_03" />
  22. </LinearLayout>
  23. </RelativeLayout>

MainActivity.java :

  1. package com.crazy.reduce;
  2. import android.app.Activity;
  3. import android.os.Bundle;
  4. import android.view.View;
  5. public class MainActivity extends Activity {
  6. private ReduceSideslip rs;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. setContentView(R.layout.activity_main);
  11. rs = (ReduceSideslip)findViewById(R.id.reduce_lay);
  12. }
  13. public void toggleMenu(View v) {
  14. rs.reduce();
  15. }
  16. }

自定义的 ReduceSideslip.java :   需要 nineoldandroids-2.4.0.jar 包,其下载地址

  1. package com.crazy.reduce;
  2. import android.content.Context;
  3. import android.util.AttributeSet;
  4. import android.view.MotionEvent;
  5. import android.view.ViewGroup;
  6. import android.widget.FrameLayout;
  7. import android.widget.HorizontalScrollView;
  8. import android.widget.LinearLayout;
  9. import com.nineoldandroids.view.ViewHelper;
  10. public class ReduceSideslip extends HorizontalScrollView {
  11. private int mScreenWidth; // 屏幕宽度
  12. private int mMnuRightPadding = 300;
  13. private int mMenuWidth; // 视图宽度(左边的视图)
  14. private int mHalfMenuWidth;
  15. private boolean isOpen; // 标记菜单是否打开
  16. private boolean once; // 是否已经初始化回收菜单
  17. private ViewGroup mMenu; // 左边的视图
  18. private ViewGroup mContent; // 右边的视图
  19. public ReduceSideslip(Context context, AttributeSet attrs) {
  20. super(context, attrs);
  21. mScreenWidth = context.getResources().getDisplayMetrics().widthPixels;
  22. }
  23. @Override
  24. protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
  25. if (!once) {
  26. // 要与布局文件当中的一致
  27. LinearLayout temp = (LinearLayout)getChildAt(0);
  28. mMenu = (ViewGroup)temp.getChildAt(0);
  29. mContent = (ViewGroup)temp.getChildAt(1);
  30. mMenuWidth = mScreenWidth - mMnuRightPadding;
  31. mHalfMenuWidth = mMenuWidth/2;
  32. mMenu.getLayoutParams().width = mMenuWidth;
  33. mContent.getLayoutParams().width = mScreenWidth;
  34. }
  35. super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  36. }
  37. // 在视图计算完自身及子视图的宽高后,重新排版
  38. @Override
  39. protected void onLayout(boolean changed, int l, int t, int r, int b) {
  40. super.onLayout(changed, l, t, r, b);
  41. if (changed) {
  42. // 隐藏菜单
  43. this.scrollTo(mMenuWidth, 0);
  44. once = true;
  45. }
  46. }
  47. public void reduce(){
  48. if (isOpen) {
  49. closeMenu();
  50. } else {
  51. openMenu();
  52. }
  53. }
  54. private void openMenu() {
  55. if (isOpen) {
  56. return;
  57. }
  58. // 和 scrollTo() 相似,但是要缓和些,
  59. // 不像 scrollTo() 直接移动过去
  60. this.smoothScrollTo(0, 0);
  61. isOpen = true;
  62. }
  63. private void closeMenu() {
  64. if (isOpen) {
  65. this.smoothScrollTo(mMenuWidth, 0);
  66. isOpen = false;
  67. }
  68. }
  69. @Override
  70. public boolean onTouchEvent(MotionEvent ev) {
  71. switch (ev.getAction()){
  72. case MotionEvent.ACTION_UP: // 松开手
  73. int scrollX = getScrollX(); // 水平滑动的距离
  74. if (scrollX > mHalfMenuWidth) {
  75. this.smoothScrollTo(mMenuWidth, 0);
  76. isOpen = false;
  77. } else {
  78. this.smoothScrollTo(0, 0);
  79. isOpen = true;
  80. }
  81. return true;
  82. }
  83. return super.onTouchEvent(ev);
  84. }
  85. @Override
  86. protected void onScrollChanged(int l, int t, int oldl, int oldt) {
  87. super.onScrollChanged(l, t, oldl, oldt);
  88. // 左右视图切换时的渐变范围 (注意是 l 不是1(一))
  89. float scale = l*1.0f/mMenuWidth; // 范围值 (0, 1)
  90. float leftScale = 1- 0.3f*scale; // 范围值(0.7, 1)
  91. float rightScale = 0.8f + 0.2f*scale; // 范围值 (0.8, 1)
  92. ViewHelper.setScaleX(mMenu, leftScale);
  93. ViewHelper.setScaleY(mMenu, leftScale);
  94. // 往右滑动时,左边的视图逐渐变亮
  95. ViewHelper.setAlpha(mMenu, 0.6f + 0.4f * (1 - scale)); // (0.6, 1)
  96. // 往左滑动时,左边的视图不用移除屏幕左边界(可以不要)
  97. ViewHelper.setTranslationX(mMenu, mMenuWidth * scale * 0.7f);
  98. ViewHelper.setScaleX(mContent, rightScale);
  99. ViewHelper.setScaleY(mContent, rightScale);
  100. }
  101. }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号