要求:可以上下左右移动的表格布局,仿同花顺自选列表,老虎证券财报列表

ScrollingTable

项目地址:MartinDong/ScrollingTable 

同花顺效果 老虎证券效果 最终实现效果如图

实现思路分析

视图分析

1、主视图分为: 头部控件(HeadView)+下面的ListView

2、头部控件(HeadView):左边为 TextView,右边为 HorizontalScrollView

3、ListView 条目视图:左边为 TextView,右边为 HorizontalScrollView

视图联动分析

1、头部 HorizontalScrollView 滑动事件广播通知 ListView 条目中的 HorizontalScrollView 从而实现联动效果

2、拦截 ListView 单个条目中的 HorizontalScrollView 滑动事件,防止 ListView 的触摸事件和 HorizontalScrollView 触摸事件冲突

3、统一处理 ListView 和 头部控件(HeadView)触摸事件,统一将触摸事件传递给 头部控件(HeadView)右边的 HorizontalScrollView ,从而实现(1)中的效果

 /*** Created by xiaoyulaoshi on 2018/1/31.** 自定义的 滚动控件* 重载了 [SyncHScrollView.onScrollChanged](滚动条变化),监听每次的变化通知给观察(此变化的)观察者* 可使用 [SyncHScrollView.AddOnScrollChangedListener] 来订阅本控件的 滚动条变化*/class SyncHScrollView : HorizontalScrollView {internal var mScrollViewObserver: ScrollViewObserver? = ScrollViewObserver()constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle) {}constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {}constructor(context: Context) : super(context) {}override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {/** 当滚动条移动后,引发 滚动事件。通知给观察者,观察者会传达给其他的条目中的滚动视图。*/if (mScrollViewObserver != null) {mScrollViewObserver!!.NotifyOnScrollChanged(l, t, oldl, oldt)}super.onScrollChanged(l, t, oldl, oldt)}/** 订阅 本控件 的 滚动条变化事件* */fun AddOnScrollChangedListener(listener: OnScrollChangedListener) {mScrollViewObserver!!.AddOnScrollChangedListener(listener)}/** 取消 订阅 本控件 的 滚动条变化事件* */fun RemoveOnScrollChangedListener(listener: OnScrollChangedListener) {mScrollViewObserver!!.RemoveOnScrollChangedListener(listener)}/** 当发生了滚动事件时*/interface OnScrollChangedListener {fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int)}/*** 观察者*/class ScrollViewObserver {internal var mList: MutableList<OnScrollChangedListener>? = nullinit {mList = ArrayList()}fun AddOnScrollChangedListener(listener: OnScrollChangedListener) {mList!!.add(listener)}fun RemoveOnScrollChangedListener(listener: OnScrollChangedListener) {mList!!.remove(listener)}fun NotifyOnScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {if (mList == null || mList!!.size == 0) {return}for (i in mList!!.indices) {if (mList!![i] != null) {mList!![i].onScrollChanged(l, t, oldl, oldt)}}}}}
/**
* ListView使用的数据适配器,实现数据填充以及列表右侧的 HorizontalScrollView 与 页面中的 头部控件(HeadView) 右侧 HorizontalScrollView 的绑定
*
* Created by xiaoyulaoshi on 2018/1/31.*/
class Type4Adapter(context: Context,/*** layout ID*/private val id_row_layout: Int,/*** List中的数据*/private val currentData: MutableList<Data>,/*** ListView头部*/private val mHead: RelativeLayout) : BaseAdapter() {private val mInflater: LayoutInflaterinit {Log.v(TAG + ".Type4Adapter", " 初始化")this.mInflater = LayoutInflater.from(context)}override fun getCount(): Int {return this.currentData.size}override fun getItem(position: Int): Any? {return null}override fun getItemId(position: Int): Long {return 0}/*** 向List中添加数据** @param items*/fun addItem(items: List<Data>) {for (item in items) {currentData.add(item)}}/*** 清空当List中的数据*/fun cleanAll() {this.currentData.clear()}@SuppressLint("SetTextI18n")override fun getView(position: Int, convertView: View?, parentView: ViewGroup): View {var convertView = convertViewvar holder: ViewHolder? = nullif (convertView == null) {convertView = mInflater.inflate(id_row_layout, null)holder = ViewHolder()//获取当前条目中的右侧滑动控件val scrollView1 = convertView!!.findViewById<SyncHScrollView>(R.id.horizontalScrollView1)//TODO 划重点:这里需要从传入的列表头拿到里面的右侧滑动控件val headScrollView = mHead.findViewById<SyncHScrollView>(R.id.horizontalScrollView1)//将当前条目的右侧滑动控件添加到头部滑动控件的滑动观察者集合中headScrollView.AddOnScrollChangedListener(OnScrollChangedListenerImp(scrollView1))//进行holder的初始化操作holder.scrollView = scrollView1holder.txt1 = convertView.findViewById(R.id.textView1)holder.txt2 = convertView.findViewById(R.id.textView2)holder.txt3 = convertView.findViewById(R.id.textView3)holder.txt4 = convertView.findViewById(R.id.textView4)holder.txt5 = convertView.findViewById(R.id.textView5)holder.txt6 = convertView.findViewById(R.id.textView6)holder.txt7 = convertView.findViewById(R.id.textView7)convertView.tag = holder} else {holder = convertView.tag as ViewHolder}holder.txt1!!.text = currentData[position].str1holder.txt2!!.text = currentData[position].str1!! + currentData[position].str2!!holder.txt3!!.text = currentData[position].str1!! + currentData[position].str3!!holder.txt4!!.text = currentData[position].str1!! + currentData[position].str4!!holder.txt5!!.text = currentData[position].str1!! + currentData[position].str5!!holder.txt6!!.text = currentData[position].str1!! + currentData[position].str6!!holder.txt7!!.text = currentData[position].str1!! + currentData[position].str7!!return convertView}internal inner class OnScrollChangedListenerImp(var mScrollViewArg: SyncHScrollView) :SyncHScrollView.OnScrollChangedListener {override fun onScrollChanged(l: Int, t: Int, oldl: Int, oldt: Int) {mScrollViewArg.smoothScrollTo(l, t)}}internal inner class ViewHolder {var txt1: TextView? = nullvar txt2: TextView? = nullvar txt3: TextView? = nullvar txt4: TextView? = nullvar txt5: TextView? = nullvar txt6: TextView? = nullvar txt7: TextView? = nullvar scrollView: HorizontalScrollView? = null}companion object {private val TAG = Type4Adapter::class.java.name}
}
/*** 最完美实现,使用 ListView + HorizontalScrollView 实现* Created by xiaoyulaoshi on 2018/1/31.*/
class Type4Activity : Activity() {internal lateinit var mListView1: ListViewinternal lateinit var mHead: RelativeLayoutinternal lateinit var type4Adapter: Type4Adapterpublic override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_type4)mHead = findViewById(R.id.head)mHead.isFocusable = truemHead.isClickable = true//TODO 划重点:这里需要从传入的列表头拿到里面的右侧滑动控件mHead.setOnTouchListener(ListViewAndHeadViewTouchListener())mListView1 = findViewById(R.id.lv_produce)mListView1.setOnTouchListener(ListViewAndHeadViewTouchListener())// 创建当前用于显示视图的数据val currentData = ArrayList<Data>()for (i in 0..49) {val data = Data()data.str1 = "股票>" + idata.str2 = "价格>1"data.str3 = "价格>2"data.str4 = "价格>3"data.str5 = "价格>4"data.str6 = "价格>5"data.str7 = "价格>6"data.str8 = "价格>7"currentData.add(data)}type4Adapter = Type4Adapter(this, R.layout.item_layout_type4, currentData, mHead)mListView1.adapter = type4Adapter// OnClick监听mListView1.onItemClickListener = OnItemClickListener { arg0, arg1, arg2, arg3 ->Log.i("Type4Activity ListView", "onItemClick Event")Toast.makeText(this@Type4Activity, "点了第" + arg2 + "个",Toast.LENGTH_SHORT).show()}}/*** TODO 划重点:用来将头部和列表上面的触摸事件都分发给头部的滑动控件*/internal inner class ListViewAndHeadViewTouchListener : View.OnTouchListener {override fun onTouch(arg0: View, arg1: MotionEvent): Boolean {// 当在列头 和 listView控件上touch时,将这个touch的事件分发给 ScrollViewval headScrollView = mHead.findViewById<HorizontalScrollView>(R.id.horizontalScrollView1)headScrollView.onTouchEvent(arg1)return false}}}

干货】最详细、最完美、可以上下左右移动的表格布局,仿同花顺自选列表,老虎证券财报列表,欢迎 Start、Fork相关推荐

  1. 完美解决在Latex的表格里的单元格内的文本紧贴着上边框线条的问题

    完美解决在Latex的表格里的单元格内的文本紧贴着上边框线条的问题 问题 一.通常出现表1的情况的代码如下 二.解决办法,也就是表2的代码 三.其它解决方案 四.引用 问题 通常做表格的时候可能会遇到 ...

  2. 小红书新品牌第一股,完美日记最新财报彰显了什么?

    互联网时代,全网营销成为品牌声浪冲击的一把利器,而选择在小红书投放的则是以女性用户为主的品牌,先通过小红书达人生产优质内容进行分享推荐.树立品牌形象后再由点到面进行全网营销. "国货之光&q ...

  3. web前端干货:详细了解JS前端开发框架都有哪些

    1. Foundation框架 Foundation框架总体来看要比Bootstrap略显高大上一点,但他们俩的设计理念都是非常清楚的,Bootstrap有引导的意思,尝试处理你项目中的一切所需.Fo ...

  4. Windows系统本地自建蚂蚁(leanote)笔记教程(步骤非常详细,完美运行)

    说明:本来在想找一个本地的笔记软件,偶尔需要记录一下资料,但是看了一下网上好多笔记软件,都是需要收费,我只需要一款本地笔记软件,在网上找了一下,发现蚂蚁笔记正好符合我的要求,就在网站找了很多教程,但是 ...

  5. 干货复试详细教程——从联系导师→自我介绍的复试教程

    文章目录 联系导师 联系之前的准备 联系导师注意 自我介绍 教育技术领域通用的复试准备 其他补充 联系导师 确定出分和自己能进复试以后联系. 分两类 科研技能型 低调,如实介绍,不吹不水.就算你很牛啥 ...

  6. 10100cpu支持Linux,i3-10100 cpu能装win7吗?i3-10100 装win7详细教程(完美支持)

    [文章导读]随着intel第十代cpu的发布,越来越多的人采用第十代cpu来组装机器,有很多使用网友问,intel 酷睿10代i3-10100 cpu处理器可以安装安装win7吗?答案是可以的,这里推 ...

  7. win 10 caffe python=3.5 小白安装全过程(最详细,完美解决各种版本不兼容等问题)

    由于caffe已经停止维护多年,现在安装过程中便会遇到很多版本不适应及各种报错问题,建议按照本文操作,亲测有效. 1.材料准备 ①visual studio 2015(已安装则忽略) ②caffe-w ...

  8. (Crypto必备干货)详细分析目前NFT的几大交易市场

    NFT 另一越来越受欢迎的用例是艺术(数字艺术).这种形式下,艺术家可以拥有自己艺术作品的版权,买家可以确保自己购买的艺术品真实权威,杜绝盗版造假.区块链可以解决所有权证明问题.艺术家不必再依赖第三方 ...

  9. CentOS 7 快速搭建JavaWeb开发环境并部署Spring boot项目(纯干货、详细)

    前言: 服务器:阿里云服务器ECS,装载CentOS 7系统 终端模拟工具&文件传输软件:xshell 7 \ xftp 7 IDE: IntelliJ IDEA 2022.1 部分内容参考阿 ...

  10. 996公司太累?那国企到底面试些什么干货,详细答案)

    谢安生(化名),末流985本科,非科班.18年10月零基础学的大数据,错过了秋招,但在春招拿了招商银行,光大银行,浪潮等国企大数据开发offer. 他是我学习群里的一个小伙伴,也是一个曾经在面试前一晚 ...

最新文章

  1. AI一分钟 | 美女机器人竟然想生孩子,太可怕了!比尔·盖茨当选中国工程院外籍院士
  2. 软件需求工程与UML建模——第九组第二周工作总结
  3. 用ACE的Reactor模式实现网络通讯的例子
  4. HDU1568 Fibonacci
  5. python 单元测试_Python系列之单元测试框架【unittest】
  6. springboot集成mybatis源码分析(一)
  7. warnings (imported as 'THREE') was not found in 'three'
  8. vscode之调试js
  9. 数据挖掘 姓名用字特点 目录 1. 姓名用字特点 1 2. 男性姓名专用字210个(三字词,双字词都适用) 1 2.1. 男性姓名专用字 双字词适用317个 1 3. 女人姓名用字 2 3.1.
  10. 兄弟FAX-2890更换硒鼓加粉清零方法
  11. Linux命令--vi(编辑或查看文件内容)
  12. 普元的ajax,普元EOS平台介绍
  13. 有什么方法可以将WMV格式转换成MP4格式
  14. 478-82(56、128、718、129)
  15. z-blog建立博客网站SEO优化细节教程
  16. favicon.ico制作
  17. bootstrap框架基础使用
  18. linux的内存占用分析,Linux 内存占用分析
  19. 艺赛旗(RPA) 【操作列表】
  20. linux c读文件读一行,Linux c 从文件当中读取任意一行的数据

热门文章

  1. 【苹果鼠标滑轮失灵】解决办法
  2. 命令行排序文件夹大小
  3. 等保2.0详解(附3级检查表)
  4. adb 通过WiFi连接小米8手机
  5. 国际市场营销知识框架图_留学热门丨伦敦里士满大学市场营销本科专业
  6. 谈如何归纳和分类美术风格比较合理
  7. python 网页设计实践报告_网页设计实习报告范文
  8. 快速原型工具,帮你从0开始画原型图
  9. 前端页面崩溃现象处理
  10. !! A股历史平均市盈率走势图