原理描述:
想写来着,但是似乎描述不太清楚。效果图来着,没找到好的视频录制软件,直接上代码吧。
代码:
1、xml布局文件
自定义控件的包名删除了部分,需要重新导入自定义控件!!!
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#ffffff"android:orientation="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="50dp"android:orientation="horizontal"><TextViewandroid:layout_width="0dp"android:layout_height="50dp"android:layout_weight="1"android:gravity="center"android:orientation="vertical"android:text="标题" /><Viewandroid:layout_width="1px"android:layout_height="50dp"android:background="#cccccc" /><LinearLayoutandroid:id="@+id/lin_header_content"android:layout_width="0dp"android:layout_height="50dp"android:layout_weight="3"android:orientation="vertical"><views.excel.SyncHorizontalScrollViewandroid:id="@+id/header_horizontal"android:layout_width="wrap_content"android:layout_height="50dp"android:overScrollMode="never"android:scrollbars="none"><LinearLayoutandroid:id="@+id/ll_excel_title_container"android:layout_width="wrap_content"android:layout_height="50dp"android:orientation="horizontal" /></views.excel.SyncHorizontalScrollView></LinearLayout></LinearLayout><Viewandroid:layout_width="match_parent"android:layout_height="1px"android:background="#cccccc" /><ScrollViewandroid:id="@+id/scroll_content"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:scrollbars="vertical"><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentTop="true"android:orientation="horizontal"><views.excel.NoscrollListViewandroid:id="@+id/lv_left"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="1"android:overScrollMode="never"android:scrollbars="none" /><Viewandroid:layout_width="1px"android:layout_height="match_parent"android:background="#cccccc" /><LinearLayoutandroid:id="@+id/lin_data_content"android:layout_width="0dp"android:layout_height="match_parent"android:layout_weight="3"android:orientation="vertical"><views.excel.SyncHorizontalScrollViewandroid:id="@+id/data_horizontal"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:scrollbars="none"><views.excel.NoscrollListViewandroid:id="@+id/lv_data"android:layout_width="match_parent"android:layout_height="match_parent"android:overScrollMode="never"android:scrollbars="none" /></views.excel.SyncHorizontalScrollView></LinearLayout></LinearLayout></ScrollView></LinearLayout>
2、activity界面
public class ExcelActivity extends AppCompatActivity {/*** Excel上方的表格*/private LinearLayout llTitleContainer;private NoscrollListView mLeft;private LeftAdapter mLeftAdapter;private NoscrollListView mData;private DataAdapter mDataAdapter;private SyncHorizontalScrollView mHeaderHorizontal;private SyncHorizontalScrollView mDataHorizontal;/*** excel的列表的数据*/private List<String> mLeftListData;/*** 最上面的标题的集合*/private List<String> titles;/*** 标题下方的内容的集合*/private List<String> contents;private List<View> contentViews;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.selfview_excel);initView();}private void initView() {mLeft = (NoscrollListView) findViewById(R.id.lv_left);mData = (NoscrollListView) findViewById(R.id.lv_data);mDataHorizontal = (SyncHorizontalScrollView) findViewById(R.id.data_horizontal);mHeaderHorizontal = (SyncHorizontalScrollView) findViewById(R.id.header_horizontal);mDataHorizontal.setScrollView(mHeaderHorizontal);mHeaderHorizontal.setScrollView(mDataHorizontal);llTitleContainer = findViewById(R.id.ll_excel_title_container);ThreadPoolProxyFactory.getNormalThreadPoolProxy().submit(new Runnable() {@Overridepublic void run() {//设置标题,与下方的contents的长度要一致titles = new ArrayList<>();for (int i = 0; i < 6; i++) {titles.add("标题" + i);}contents = new ArrayList<>();for (int i = 0; i < 6; i++) {contents.add("内容 " + i);}mLeftListData = new ArrayList<>();contentViews = new ArrayList<>();LinearLayout linearLayout = null;//竖直方向的行数for (int i = 0; i <30; i++) {mLeftListData.add("" + i);View view = null;linearLayout = new LinearLayout(ExcelActivity.this);for (String content : contents) {view = View.inflate(ExcelActivity.this, R.layout.item_excel_title, null);TextView tvTitle = view.findViewById(R.id.tv_item_excel_title);tvTitle.setText(content);linearLayout.addView(view);}contentViews.add(linearLayout);}//设置上方水平栏MyApplication.getMainThreadHandler().post(new Runnable() {@Overridepublic void run() {View view = null;for (String title : titles) {view = View.inflate(ExcelActivity.this, R.layout.item_excel_title, null);TextView tvTitle = view.findViewById(R.id.tv_item_excel_title);tvTitle.setText(title);llTitleContainer.addView(view);}//设置左边栏mLeftAdapter = new LeftAdapter();mLeft.setAdapter(mLeftAdapter);//设置内容mDataAdapter = new DataAdapter();mData.setAdapter(mDataAdapter);}});}});}class LeftAdapter extends BaseAdapter {@Overridepublic int getCount() {return mLeftListData.size();}@Overridepublic Object getItem(int position) {return mLeftListData.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {ViewHolder holder = null;if (convertView == null) {holder = new ViewHolder();convertView = LayoutInflater.from(ExcelActivity.this).inflate(R.layout.item_left, null);holder.tvLeft = (TextView) convertView.findViewById(R.id.tv_left);convertView.setTag(holder);} else {holder = (ViewHolder) convertView.getTag();}holder.tvLeft.setText("第" + position + "行");return convertView;}class ViewHolder {TextView tvLeft;}}/*** 内容的适配器adapter*/class DataAdapter extends BaseAdapter {@Overridepublic int getCount() {return mLeftListData.size();}@Overridepublic Object getItem(int position) {return mLeftListData.get(position);}@Overridepublic long getItemId(int position) {return position;}@Overridepublic View getView(int position, View convertView, ViewGroup parent) {// convertView = LayoutInflater.from(ExcelActivity.this).inflate(R.layout.item_data, null);
// LinearLayout llContent = (LinearLayout) convertView.findViewById(R.id.ll_excel_content);
//
// View view = null;
// for (String content : contents) {
// view = View.inflate(ExcelActivity.this, R.layout.item_excel_title, null);
// TextView tvTitle = view.findViewById(R.id.tv_item_excel_title);
// tvTitle.setText(content);
// llContent.addView(view);
// }convertView = contentViews.get(position);return convertView;}}
}
3、自定义控件
public class SyncHorizontalScrollView extends HorizontalScrollView {private View mView;public SyncHorizontalScrollView(Context context) {super(context);}public SyncHorizontalScrollView(Context context, AttributeSet attrs) {super(context, attrs);}public SyncHorizontalScrollView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);//这是上方的水平标题与下方的水平内容进行绑定if (mView != null) {mView.scrollTo(l, t);}}public void setScrollView(View view) {mView = view;}}
public class NoscrollListView extends ListView {public NoscrollListView(Context context) {super(context);}public NoscrollListView(Context context, AttributeSet attrs) {super(context, attrs);}public NoscrollListView(Context context, AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int expandSpec = MeasureSpec.makeMeasureSpec(Integer.MAX_VALUE >> 2, MeasureSpec.AT_MOST);super.onMeasure(widthMeasureSpec, expandSpec);}}
似乎就这就大功告成。
个人感觉精化点:
1、实现红、绿部分水平滑动时候的联动。主要通过俩个自定义控件SyncHorizontalScrollView的互相的绑定。在该自定义控件的onScrollChanged(...)方法中的 mView.scrollTo(l, t); ,如下:
@Overrideprotected void onScrollChanged(int l, int t, int oldl, int oldt) {super.onScrollChanged(l, t, oldl, oldt);//这是上方的水平标题与下方的水平内容进行绑定if (mView != null) {mView.scrollTo(l, t);}}
2、mView是通过自定义控件中的如下方法传入,在activity中调用:
public void setScrollView(View view) {mView = view;}
3、这个点不难,但是在下当初没想到。参考了别人的项目实现、想明白。虽然逻辑简单,但是自己想不到,真尴尬!!!
结束语
忘了哪位的博客了,挺多的,可根据自己需要查看!!!
一、Android实现Excel表格,且表格能左右、上下滑动
http://www.cnblogs.com/begin1949/p/5910785.html
二、Android复杂表格的实现:https://www.jianshu.com/p/6d133f572ed2
源代码地址:https://github.com/Kelin-Hong/ScrollablePanel
三、Android实现了复杂表格,表格内容区域可以与上下滑动、左右滚动,并且标题会跟着滚动
http://blog.csdn.net/jingleye/article/details/55510135
源代码地址:https://github.com/leafseelight/ComplexTable-Master
四、Android实现类似Excel的大表格,可横向纵向滑动,带表头
http://blog.csdn.net/z3896823/article/details/72858678
源代码地址: https://github.com/z3896823/PanelList
一三四用的实现方式是类似的。都是用的ScrollView里面嵌套listview,还有就是表头都是写死的布局。
五、 Android-自定义类似excel表格,双向滑动的ListView
http://blog.csdn.net/u011511921/article/details/77865908
这篇文章的留言中看到另外一个例子:
源代码地址:https://github.com/huangyanbin/smartTable
smartTable这个Demo功能很强大,但是想要完全读取作者的代码并且能灵活运用起来有一些难度。
六、仿房产销冠APP销控表界面-多RecyclerView同步滚动
https://www.jianshu.com/p/ed7fce51e5b5
源代码地址:https://github.com/GitLqr/TopsalesSellControlTableDemo
体验不是很好。
七、Android用RecyclerView实现的二维Excel效果组件
http://www.codesocang.com/kj-recyclerviews/34949.html
没有了,欢迎指教,一起进步!!!