1.背景介绍

  最近项目用到两个ScrollView的同步显示,即拖动左边的ScrollView滚动的同时,实现右边的ScrollView同步滚动。此种情形常用在复杂界面布局中,比如左边的ScrollView显示主要项目,只需上下滚动即可;右边项目是次要项目,可以实现上下或者左右滚动,当上下滚动时,需要左右两边的同步显示。

  如图所示,左侧是主项目(日期和股票代码),右侧是次要项目(开盘价、最高价、成交量....等等信息)。因为信息比较多,左侧的主项目需要上下拖动显示,而右侧则需要上下左右都可以拖动才能显示完全(ScrollView嵌套一个HorizontalScrollView)。我们希望左侧或右侧上下拖动时,能够实现同步。这就需要实现两个ScrollView的同步显示。因为Android控件中没有此种功能,因此需要重写ScrollView。

2.思路介绍

  我们首先想到使用ScrollView的类似与setOnScrollChangedListener的方法来实现,当一个ScrollView滚动时,触发该方法进而使另外一个ScrollView滚动。不过很遗憾,谷歌没有提供该方法。通过查询相应的源代码,我们发现该方法的原型

protected void onScrollChanged(int x, int y, int oldx, int oldy)

该方法是protected类型,不能直接调用,于是需要重新实现ScrollView。

3.具体实现

  首先,定一个一个接口(ScrollViewListener.java):

public interface ScrollViewListener {void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy);}

我们需要重写ScrollView才能实现该借口,因此有下面的代码(ObservableScrollView.java):

package com.devin;import android.content.Context;
import android.util.AttributeSet;
import android.widget.ScrollView;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;}@Overrideprotected 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);}}}

接下来是界面的XML,这里是一个简单的Demo,如下(main.xml):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:background="#ffffff"android:orientation="horizontal" ><com.devin.ObservableScrollViewandroid:id="@+id/scrollview1"android:layout_width="400dp"android:layout_height="wrap_content" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" ><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="monday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="tuesday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="wednesday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="thursday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="friday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="saturday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="sunday"android:textColor="#000000" /></LinearLayout></com.devin.ObservableScrollView><com.devin.ObservableScrollViewandroid:id="@+id/scrollview2"android:layout_width="400dp"android:layout_height="wrap_content" ><LinearLayoutandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical" ><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="monday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="tuesday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="wednesday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="thursday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="friday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="saturday"android:textColor="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="200dp"android:layout_weight="1"android:text="sunday"android:textColor="#000000" /></LinearLayout></com.devin.ObservableScrollView></LinearLayout>

最后是我们的主程调用(PadTestActivity.java):

package com.devin;import android.app.Activity;
import android.os.Bundle;public class PadTestActivity extends Activity implements ScrollViewListener {private ObservableScrollView scrollView1 = null;private ObservableScrollView scrollView2 = null;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);scrollView1 = (ObservableScrollView) findViewById(R.id.scrollview1);scrollView1.setScrollViewListener(this);scrollView2 = (ObservableScrollView) findViewById(R.id.scrollview2);scrollView2.setScrollViewListener(this);}public void onScrollChanged(ObservableScrollView scrollView, int x, int y, int oldx, int oldy) {if(scrollView == scrollView1) {scrollView2.scrollTo(x, y);} else if(scrollView == scrollView2) {scrollView1.scrollTo(x, y);}}}

代码一目了然,具体就不讲解了,关键是思路,即如何才能想到是怎么实现的。如有疑问,欢迎留言。谢谢。

转载于:https://www.cnblogs.com/chengzhengfu/p/4578872.html

重写ScrollView实现两个ScrollView的同步滚动显示相关推荐

  1. vue中两个iframe滚动条同步滚动问题总结

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.问题分析 二.记录爬坑过程 1.获取dom 错误操作:在mounted里面this.$nextTick,如果场景里面有t ...

  2. vue实现两个区域滚动条同步滚动

    项目开发中,遇到一个比较两个form差异的需求,但当item过多就需要滚动条,这里就用到了滚动条同步的地方,其实原理和git的差异比较差不多,这里来做一下分析.这是效果图 要点分析: 其实主要是通过r ...

  3. 同步滚动两个DataGrid

         拿到这个首先想到的就是重写Scroll方法,可是想想工作量有些大,所以想在Form级别上做做手脚,看看DataGrid的成员列表可以看到这样两个保护性的方法: GridHScrolled   ...

  4. 城轨的两类时钟系统均同步于_基于两台SDS3000示波器同步产生“8通道”示波器...

    在很多应用场合需要4通道以上的示波器,但是市面上极大部分示波器最多只有四通道,而且没有外部输入的同步时钟接口. 有什么快捷的方法获得更多通道功能的示波器? 最简便的方法是:将两台示波器的辅助输入信号作 ...

  5. SQL DATACOMPARE 实现两个数据库的同步处理.

    1. SQL DATACOMPARE 实现 两个数据库的同步 安装破解. 然后进行对比 然后进行 deploy 生成sql 等. 貌似很好用 但是前提是数据库是可用的... 这里面能够看到 生成的脚本 ...

  6. 关于git中,两个branch自动同步的问题和解决

    关于git中,两个branch自动同步的问题和解决 1问题描述 2问题原因 3解决方法 1问题描述 在git中,如果在一个branch中对代码进行了修改,切不做任何操作直接checkout另一个bra ...

  7. 文件共享两台电脑不同步

    最近在网络上看到网友问:文件共享两台电脑不同步怎么解决?文件共享的两天电脑之间文件做了修改,不能同步,好蛋疼!小编想说,在工作学习中,我们经常会用到两台电脑互相传输文件件,如何高效简洁的完成文件共享, ...

  8. SwiftUI ScrollView 高级技巧之 01 单击按钮手动滚动到某个位置

    实战需求 SwiftUI ScrollView 高级技巧之 01 单击按钮手动滚动到某个位置 开发过程中,有时开发人员希望以编程方式滚动到特定位置,或者希望从下到上滚动,例如聊天视图.交易视图等,我们 ...

  9. git 局域网 两台电脑之间同步 (不用安装Java和Gitblit和OpenSSH)

    git 两台电脑之间同步,两台电脑同属一个局域网,可以是windows和windows,也可以是windows和ubuntu. (不用安装Java和Gitblit和OpenSSH),可以不用连接外网. ...

最新文章

  1. php中常见的错误类型有,JavaScript中常见的错误类型有哪些?(详细介绍)
  2. MPB:微生物所王军组-​人类肠道病毒粒子富集及纳米孔测序
  3. BAT面试必知:DubboZookeeper面试集锦
  4. OpenGL键盘消息实例
  5. java客户姓名添加和查找_java类与对象 演练 客户姓名添加与查看
  6. 计算机学院创新实验室,ACM创新实验室概况
  7. 搜索——下沙小面的2(hdu1572)
  8. PCL中点云可视化:坐标字段、随机、单一颜色、法向量
  9. 【Spring学习】01
  10. 麦肯锡指出布局金融生态圈对中国国内银行意义重大
  11. 微博回应用户被“劫持”;途牛否认破产清算;微软宣布开源 MsQuic | 极客头条...
  12. 迪杰斯特拉算法(dijkstra)
  13. 专硕考数二英二的计算机专业,专硕难度升级!英二改考英一,数二改考数一
  14. 使用Travis CI实现C++ CMake工程多平台编译
  15. 小象学院—小象学院—Python学习联盟09—空气质量指数计算
  16. 三星android7要更新8,三星Bixby Voice将停止支持安卓7.0/8.0,用户可以升级系统使用...
  17. android 第三方视频库,android视频播放库
  18. 算法之算法的时间复杂度
  19. 为什么要做数仓分层,不做行吗?
  20. linux设备驱动归纳总结(十三):1.触摸屏与ADC时钟

热门文章

  1. python核心编程6-14习题的解题思路
  2. 关于微信公众平台表情代码的记录
  3. POJ 3687 Labeling Balls
  4. !--#include virtual='head.html'--代码复用
  5. C语言博客作业--结构体
  6. 【Python之路Day12】网络篇之Python操作RabbitMQ
  7. 商业模式(一):北京秒针公司,以互联网广告监测服务为主的生财之道
  8. Mac OS X中配置Apache
  9. (一)数据结构与算法简介
  10. git基于tag创建分支