android固定头部和侧边表格实现

来源:互联网 发布:鹏博士数据客服电话 编辑:程序博客网 时间:2024/04/30 04:12

哈哈,感觉下CSDN的新版本编辑器,至少看起来还挺不错的,之前的编辑器插入代码很不方便,发布后会出现源代码,还估计是一个bug.

言归正传,这次要记录的是android怎么实现表格头、侧边固定滑动,并且实现纵向的合并,本来自我感觉良好,后来被群友告知这个有一个开源框架可以实现,想想自己的傻傻的去实现,累觉不爱,anywhere,已经写好了就只能安慰自己以后出现问题了方便修复吧,毕竟这是自己的东西。先看一个效果图:

这里写图片描述
要实现的效果就是左右滑动白色区域时,“时间”一列固定,头部跟着滑动,上下滑动白色区域时,头部固定,时间一列跟着滑动。显示的部分可以纵向合并。
思路也比较自然,首先需要滚动肯定要用ScrollView了。上下滚动就用平常的ScrollView就可以实现了,主要是左右滚动的时候要固定左边,这就需要处理好布局了,并且内容区要和头部同步,也就是任何一个在滚动的时候同步告诉另一个的位置。另一个就是合并,我现在的合并就是通过控制高度来实现,比如要合并两行,那么在开始合并的时候设置这个高度为2倍单元格高度,然后在下一次渲染下方的单元格时直接跳过,这样保证不会多出一个单元格来,具体的看代码,以下是核心代码:

总体的布局:main.xml

<LinearLayout            android:orientation="horizontal"            android:layout_width="match_parent"            android:layout_height="@dimen/dp_40">        <TextView                android:id="@+id/txt_time"                android:gravity="center"                android:textColor="@color/text_content_black"                android:text="@string/dpf_header_time"                android:background="@drawable/border_dfp_title"                android:layout_weight="1"                android:textSize="@dimen/text_font_normal"                android:layout_width="0dp"                android:layout_height="match_parent"/>        <com.wicky.fixtable.MyHorizontalScrollView                android:id="@+id/sc_title"                android:scrollbars="none"                android:background="@drawable/border_dfp_title"                android:layout_weight="3"                android:layout_width="0dp"                android:layout_height="match_parent">        </com.wicky.fixtable.MyHorizontalScrollView>    </LinearLayout>    <ScrollView            android:layout_weight="1"            android:layout_width="match_parent"            android:layout_height="0dp">        <RelativeLayout                android:layout_width="match_parent"                android:layout_height="match_parent">            <LinearLayout                    android:id="@+id/ll_left"                    android:orientation="vertical"                    android:layout_width="wrap_content"                    android:layout_height="match_parent">            </LinearLayout>            <com.wicky.fixtable.MyHorizontalScrollView                    android:id="@+id/sc_data"                    android:layout_toRightOf="@id/ll_left"                    android:layout_width="match_parent"                    android:layout_height="match_parent">                <LinearLayout                        android:id="@+id/ll_data"                        android:clickable="true"                        android:orientation="horizontal"                        android:layout_width="match_parent"                        android:layout_height="match_parent">                </LinearLayout>            </com.wicky.fixtable.MyHorizontalScrollView>        </RelativeLayout>    </ScrollView>

头部是一个线性布局,和下面的时间、内容分开,这是方便上下滑动,作为一个普通的ScrollView来处理。内容中又分为左右两块:左边是一个线性的时间,右边和头部一样用了自定义的ScrollView.这样实现左右滑动时的同步。

MyHorizontalScrollView.java

@Override    protected void onScrollChanged(int l, int t, int oldl, int oldt) {        super.onScrollChanged(l, t, oldl, oldt);        if(null != mView)            mView.scrollTo(l, t);    }    public void setScrollView(View mView) {        this.mView = mView;    }

主要实现onScrollChanged,来同步两个ScrollView的坐标。

主类MyActivity.java

private void initData() {        //要显示的内容区域        for (int i = 0; i < 10; i++) {            Map<String, String> map = new HashMap<String, String>();            map.put("text", "网球场"+i);            map.put("pid", String.valueOf(i));            dataList.add(map);        }        //时间片段        for (int i = 0; i < 12; i++) {            Map<String, String> map = new HashMap<String, String>();            map.put("text", "08:00-08:30");//偷个懒,写成一样的            map.put("tid", String.valueOf(i));            timeList.add(map);        }        //合并区域        Map<String, String> map1 = new HashMap<String, String>();        map1.put("pid", String.valueOf(1));        map1.put("start_tid", String.valueOf(4));        map1.put("end_tid", String.valueOf(5));        map1.put("status", String.valueOf(STATUS_ONE));        selectedList.add(map1);        //合并了3行        Map<String, String> map2 = new HashMap<String, String>();        map2.put("pid", String.valueOf(0));        map2.put("start_tid", String.valueOf(4));        map2.put("end_tid", String.valueOf(6));        map2.put("status", String.valueOf(STATUS_TWO));        selectedList.add(map2);    }

模拟一些数据,主要注意的是pid,这个用来决定在哪一列合并;tid这个用来决定从哪一行开始合并,这样就决定了合并的坐标了。

private void renderTable() {        //初始化时间        int timeCount = timeList.size();        for (int i = 0; i < timeCount; i++) {            ll_left.addView(getTimeRow(i));        }        //初始化表头        sc_title.addView(getTitleRow());        //初始化内容数据        for (int i = 0; i < dataList.size(); i++) {            ll_data.addView(getDataColumn(i));        }    }

在渲染的时候因为要纵向合并,所以得竖着添加数据,否则只能横向合并了。也就是getDataColumn(i)这个方法,这里主要是纵向处理合并的行数。

for (int i = 0; i < selectedList.size(); i++) {                Map<String, String> selectedMap = selectedList.get(i);                //如果存在已订场地相同的场地id,则需要显示                if((selectedMap.get("pid")).equals(pInfo.get("pid"))) {                    int startTid = Integer.parseInt(selectedMap.get("start_tid"));                    int endTid = Integer.parseInt(selectedMap.get("end_tid"));                    //得到当前遍历的时间集合,根据具体的业务计算合并几行                    Map<String, String> timeSpinnerMap = timeList.get(j);                    int tId = Integer.parseInt(timeSpinnerMap.get("tid"));                    //如果当前的这个时间id,等于合并数据的开始时间id,表示从这里开始合并                    if(tId == startTid) {                        mergeRow = endTid - startTid;                        dealState = Integer.parseInt(selectedMap.get("status"));                        Log.d(TAG, "合并的场id=" + pInfo.get("pid") + ",startTi=" + startTid + ",endTid=" + endTid + ",dealState=" + dealState);                    }                }            }

遍历要合并的数据,判断是否有pid和头部的pid相同,确定要合并的列。如果有相等的,则取其中start_tid.和时间的tid比较,来确定从哪一行开始,然后根据业务需求为处理要合并几行。具体的可以看源码,注释的很清楚了。

代码下载:http://download.csdn.net/detail/aj1031689/8895841

因为没有什么可以封装的布局,就直接写在主类里面了,可能看起来比较乱,但顺着思路走应该还是比较清晰的。

本文旨在分享,大神勿喷

2 0
原创粉丝点击