如上图所示效果,整体视图构成已标记,联动效果通过两个CustomHorizontalScrollView的setOnScrollChangeListener方法绑定实现。

表格里面数据通过动态添加textview和分割线view绘制而成。

具体看以下代码:

package com.rmondjone.locktableview;import android.content.Context;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.Log;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.HorizontalScrollView;
import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;import java.util.ArrayList;
import java.util.List;
import java.util.Random;/*** 说明 可锁定首行和首列的表格视图* 作者 康汉斌* 创建时间 2017/3/29.*/public class LockTableView implements View.OnClickListener {/*** 上下文*/private Context mContext;/*** 表格父视图*/private ViewGroup mContentView;/*** 表格数据,每一行为一条数据,从表头计算*/private ArrayList<ArrayList<String>> mTableDatas = new ArrayList<ArrayList<String>>();/*** 表格视图*/private View mTableView;/*** 是否锁定首行*/private boolean isLockFristRow = true;/*** 是否锁定首列*/private boolean isLockFristColumn = true;/*** 最大列宽(dp)*/private int maxColumnWidth;/*** 最小列宽(dp)*/private int minColumnWidth;/*** 最大行高(dp)*/private int maxRowHeight;/*** 最小行高dp)*/private int minRowHeight;/*** 第一行背景颜色*/private int mFristRowBackGroudColor;/*** 数据为空时的缺省值*/private String mNullableString;/*** 单元格字体大小*/private int mTextViewSize;/*** 表格头部字体颜色*/private int mTableHeadTextColor;/*** 表格内容字体颜色*/private int mTableContentTextColor;/*** 表格监听事件*/private OnTableViewListener mTableViewListener;//表格数据/*** 表格第一行数据,不包括第一个元素*/private ArrayList<String> mTableFristData = new ArrayList<>();/*** 表格第一列数据,不包括第一个元素*/private ArrayList<String> mTableColumnDatas = new ArrayList<>();/*** 表格左上角数据*/private String mColumnTitle;/*** 表格每一行数据,不包括第一行和第一列*/private ArrayList<ArrayList<String>> mTableRowDatas = new ArrayList<ArrayList<String>>();/*** 记录每列最大宽度*/private ArrayList<Integer> mColumnMaxWidths = new ArrayList<Integer>();/*** 记录每行最大高度*/private ArrayList<Integer> mRowMaxHeights = new ArrayList<Integer>();/*** 把所有的滚动视图放图列表,后面实现联动效果*/private ArrayList<HorizontalScrollView> mScrollViews = new ArrayList<HorizontalScrollView>();//表格视图/*** 表格左上角视图*/private TextView mColumnTitleView;/*** 第一行布局(锁状态)*/private LinearLayout mLockHeadView;/*** 第一行布局(未锁状态)*/private LinearLayout mUnLockHeadView;/*** 第一行滚动视图(锁状态)*/private CustomHorizontalScrollView mLockScrollView;/*** 第一行滚动视图(未锁状态)*/private CustomHorizontalScrollView mUnLockScrollView;/*** 表格主视图*/private ScrollView mTableScrollView;private View lockTableViewContent;private CustomHorizontalScrollView lockScrollViewParent;/*** 构造方法** @param mContext 上下文* @param mContentView 表格父视图* @param mTableDatas 表格数据*/public LockTableView(Context mContext, ViewGroup mContentView, ArrayList<ArrayList<String>> mTableDatas) {this.mContext = mContext;this.mContentView = mContentView;this.mTableDatas = mTableDatas;initAttrs();}/*** 初始化属性*/private void initAttrs() {mTableView = LayoutInflater.from(mContext).inflate(R.layout.locktableview, null);maxColumnWidth = 100;minColumnWidth = 70;minRowHeight=20;maxRowHeight=60;mNullableString = "N/A";mTableHeadTextColor = R.color.beijin;mTableContentTextColor = R.color.border_color;mFristRowBackGroudColor = R.color.table_head;mTextViewSize = 16;}/*** 展现视图*/public void show() {initData();initView();mContentView.addView(mTableView);}/*** 初始化表格数据*/private void initData() {if (mTableDatas != null && mTableDatas.size() > 0) {//检查数据,如果有一行数据长度不一致,以最长为标准填"N/A"字符串,如果有null也替换int maxLength = 0;for (int i = 0; i < mTableDatas.size(); i++) {if (mTableDatas.get(i).size() >= maxLength) {maxLength = mTableDatas.get(i).size();}ArrayList<String> rowDatas = mTableDatas.get(i);for (int j = 0; j < rowDatas.size(); j++) {if (rowDatas.get(j) == null || rowDatas.get(j).equals("")) {rowDatas.set(j, mNullableString);}}mTableDatas.set(i, rowDatas);}
//            Log.e("每行最多个数",maxLength+"");for (int i = 0; i < mTableDatas.size(); i++) {ArrayList<String> rowDatas = mTableDatas.get(i);if (rowDatas.size() < maxLength) {int size=maxLength - rowDatas.size();for (int j = 0; j <size; j++) {rowDatas.add(mNullableString);}mTableDatas.set(i, rowDatas);}}//            //测试
//            for (int i=0;i<mTableDatas.size();i++){
//                ArrayList<String> rowDatas=mTableDatas.get(i);
//                StringBuffer b=new StringBuffer();
//                for (String str:rowDatas){
//                    b.append("["+str+"]");
//                }
//                Log.e("第"+i+"行数据",b.toString()+"/"+rowDatas.size()+"个");
//            }//初始化每列最大宽度for (int i = 0; i < mTableDatas.size(); i++) {ArrayList<String> rowDatas = mTableDatas.get(i);StringBuffer buffer = new StringBuffer();for (int j = 0; j < rowDatas.size(); j++) {TextView textView = new TextView(mContext);textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextViewSize);textView.setText(rowDatas.get(j));textView.setGravity(Gravity.CENTER);//设置布局LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);textViewParams.setMargins(45, 45, 45, 45);//android:layout_margin="15dp"textView.setLayoutParams(textViewParams);if (i == 0) {mColumnMaxWidths.add(measureTextWidth(textView, rowDatas.get(j)));buffer.append("[" + measureTextWidth(textView, rowDatas.get(j)) + "]");} else {int length = mColumnMaxWidths.get(j);int current = measureTextWidth(textView, rowDatas.get(j));if (current > length) {mColumnMaxWidths.set(j, current);}buffer.append("[" + measureTextWidth(textView, rowDatas.get(j)) + "]");}}
//                Log.e("第"+i+"行列最大宽度",buffer.toString());}
//            Log.e("每列最大宽度dp:",mColumnMaxWidths.toString());//初始化每行最大高度for (int i = 0; i < mTableDatas.size(); i++) {ArrayList<String> rowDatas = mTableDatas.get(i);StringBuffer buffer = new StringBuffer();TextView textView = new TextView(mContext);textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextViewSize);textView.setGravity(Gravity.CENTER);//设置布局LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);textViewParams.setMargins(45, 45, 45, 45);//android:layout_margin="15dp"textView.setLayoutParams(textViewParams);int maxHeight=measureTextHeight(textView,rowDatas.get(0));mRowMaxHeights.add(maxHeight);for (int j = 0; j < rowDatas.size(); j++) {int currentHeight=measureTextHeight(textView,rowDatas.get(j));buffer.append("["+currentHeight+"]");if (currentHeight>maxHeight){mRowMaxHeights.set(i,currentHeight);}}
//                Log.e("第"+i+"行高度",buffer.toString());}
//            Log.e("每行最大高度dp:",mRowMaxHeights.toString());if (isLockFristRow) {ArrayList<String> fristRowDatas = mTableDatas.get(0);if (isLockFristColumn) {//锁定第一列mColumnTitle = fristRowDatas.get(0);fristRowDatas.remove(0);mTableFristData.addAll(fristRowDatas);//构造第一列数据,并且构造表格每行数据for (int i = 1; i < mTableDatas.size(); i++) {ArrayList<String> rowDatas = mTableDatas.get(i);mTableColumnDatas.add(rowDatas.get(0));rowDatas.remove(0);mTableRowDatas.add(rowDatas);}} else {mTableFristData.addAll(fristRowDatas);for (int i = 1; i < mTableDatas.size(); i++) {mTableRowDatas.add(mTableDatas.get(i));}}} else {if (isLockFristColumn) {//锁定第一列//构造第一列数据,并且构造表格每行数据for (int i = 0; i < mTableDatas.size(); i++) {ArrayList<String> rowDatas = mTableDatas.get(i);mTableColumnDatas.add(rowDatas.get(0));rowDatas.remove(0);mTableRowDatas.add(rowDatas);}} else {for (int i = 0; i < mTableDatas.size(); i++) {mTableRowDatas.add(mTableDatas.get(i));}}}//            Log.e("第一行数据",mTableFristData.toString());
//            Log.e("第一列数据",mTableColumnDatas.toString());
//            Log.e("每行数据",mTableRowDatas.toString());} else {Toast.makeText(mContext, "表格数据为空!", Toast.LENGTH_SHORT).show();}}/*** 初始化表格视图*/private void initView() {mColumnTitleView = (TextView) mTableView.findViewById(R.id.lockHeadView_Text);mLockHeadView = (LinearLayout) mTableView.findViewById(R.id.lockHeadView);mUnLockHeadView = (LinearLayout) mTableView.findViewById(R.id.unLockHeadView);mLockScrollView = (CustomHorizontalScrollView) mTableView.findViewById(R.id.lockHeadView_ScrollView);mUnLockScrollView = (CustomHorizontalScrollView) mTableView.findViewById(R.id.unlockHeadView_ScrollView);mTableScrollView = (ScrollView) mTableView.findViewById(R.id.table_scrollView);mLockHeadView.setBackgroundColor(ContextCompat.getColor(mContext, mFristRowBackGroudColor));mUnLockHeadView.setBackgroundColor(ContextCompat.getColor(mContext, mFristRowBackGroudColor));if (isLockFristRow) {if (isLockFristColumn) {mLockHeadView.setVisibility(View.VISIBLE);mUnLockHeadView.setVisibility(View.GONE);} else {mLockHeadView.setVisibility(View.GONE);mUnLockHeadView.setVisibility(View.VISIBLE);}creatHeadView();} else {mLockHeadView.setVisibility(View.GONE);mUnLockHeadView.setVisibility(View.GONE);}createTableView();}/*** 创建头部视图*/private void creatHeadView() {if (isLockFristColumn) {mColumnTitleView.setTextColor(ContextCompat.getColor(mContext, mTableHeadTextColor));mColumnTitleView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextViewSize);mColumnTitleView.setText(mColumnTitle);LinearLayout.LayoutParams layoutParams =(LinearLayout.LayoutParams) mColumnTitleView.getLayoutParams();layoutParams.width = DisplayUtil.dip2px(mContext, mColumnMaxWidths.get(0));layoutParams.height=DisplayUtil.dip2px(mContext,mRowMaxHeights.get(0));layoutParams.setMargins(45, 45, 45, 45);mColumnTitleView.setLayoutParams(layoutParams);//构造滚动视图createScollview(mLockScrollView, mTableFristData, true);mScrollViews.add(mLockScrollView);mLockScrollView.setOnScrollChangeListener(new CustomHorizontalScrollView.onScrollChangeListener() {@Overridepublic void onScrollChanged(HorizontalScrollView scrollView, int x, int y) {changeAllScrollView(x, y);}});} else {createScollview(mUnLockScrollView, mTableFristData, true);mScrollViews.add(mUnLockScrollView);mUnLockScrollView.setOnScrollChangeListener(new CustomHorizontalScrollView.onScrollChangeListener() {@Overridepublic void onScrollChanged(HorizontalScrollView scrollView, int x, int y) {changeAllScrollView(x, y);}});}}/*** 构造表格主视图*/private void createTableView() {if (isLockFristColumn) {createLockColumnView();} else {createUnLockColumnView();}}/*** 创建锁定列视图*/private void createLockColumnView() {lockTableViewContent=LayoutInflater.from(mContext).inflate(R.layout.locktablecontentview,null);LinearLayout lockViewParent=(LinearLayout) lockTableViewContent.findViewById(R.id.lockView_parent);lockScrollViewParent=(CustomHorizontalScrollView)lockTableViewContent.findViewById(R.id.lockScrollView_parent);//构造锁定视图for (int i=0;i<mTableColumnDatas.size();i++){//构造TextView容器,如果要设置背景色设置这一个而不是设置TextView,TextView有外边距设置不全LinearLayout textViewContainer=new LinearLayout(mContext);LinearLayout.LayoutParams textLinearParams=new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);textViewContainer.setOrientation(LinearLayout.HORIZONTAL);textViewContainer.setLayoutParams(textLinearParams);//构造TextViewTextView textView=new TextView(mContext);//设置布局LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);textViewParams.setMargins(45, 45, 45, 45);textView.setLayoutParams(textViewParams);textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextViewSize);textView.setText(mTableColumnDatas.get(i));textView.setGravity(Gravity.CENTER);ViewGroup.LayoutParams layoutParams = textView.getLayoutParams();layoutParams.width = DisplayUtil.dip2px(mContext, mColumnMaxWidths.get(0));if (isLockFristRow){layoutParams.height=DisplayUtil.dip2px(mContext,mRowMaxHeights.get(i+1));}else{layoutParams.height=DisplayUtil.dip2px(mContext,mRowMaxHeights.get(i));}textView.setLayoutParams(layoutParams);if (!isLockFristRow){if (i==0){textViewContainer.setBackgroundColor(ContextCompat.getColor(mContext,mFristRowBackGroudColor));textView.setTextColor(ContextCompat.getColor(mContext, mTableHeadTextColor));}else{textView.setTextColor(ContextCompat.getColor(mContext, mTableContentTextColor));}}else{textView.setTextColor(ContextCompat.getColor(mContext, mTableContentTextColor));}textViewContainer.addView(textView);//表格线View splite=new View(mContext);ViewGroup.LayoutParams spliteLayoutParam= new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,DisplayUtil.dip2px(mContext,1));splite.setLayoutParams(spliteLayoutParam);splite.setBackgroundColor(ContextCompat.getColor(mContext,R.color.light_gray));lockViewParent.addView(textViewContainer);lockViewParent.addView(splite);}//构造滚动视图LinearLayout scollViewItemContentView=new LinearLayout(mContext);LinearLayout.LayoutParams scollViewItemContentViewParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);scollViewItemContentView.setLayoutParams(scollViewItemContentViewParams);scollViewItemContentView.setOrientation(LinearLayout.VERTICAL);for (int i=0;i<mTableRowDatas.size();i++){final ArrayList<String> datas=mTableRowDatas.get(i);//设置LinearLayoutLinearLayout linearLayout = new LinearLayout(mContext);LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);linearLayout.setLayoutParams(layoutParams);linearLayout.setGravity(Gravity.CENTER);linearLayout.setOrientation(LinearLayout.HORIZONTAL);if (!isLockFristRow){if (i==0){linearLayout.setBackgroundColor(ContextCompat.getColor(mContext,mFristRowBackGroudColor));}}for (int j = 0; j < datas.size(); j++) {//构造单元格TextView textView = new TextView(mContext);if (!isLockFristRow){if (i==0) {textView.setTextColor(ContextCompat.getColor(mContext, mTableHeadTextColor));} else {textView.setTextColor(ContextCompat.getColor(mContext, mTableContentTextColor));}}else{textView.setTextColor(ContextCompat.getColor(mContext, mTableContentTextColor));}textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextViewSize);textView.setGravity(Gravity.CENTER);textView.setText(datas.get(j));//设置布局LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);textViewParams.setMargins(45, 45, 45, 45);if (isLockFristRow){textViewParams.height=DisplayUtil.dip2px(mContext,mRowMaxHeights.get(i+1));}else{textViewParams.height=DisplayUtil.dip2px(mContext,mRowMaxHeights.get(i));}textView.setLayoutParams(textViewParams);ViewGroup.LayoutParams textViewParamsCopy = textView.getLayoutParams();textViewParamsCopy.width = DisplayUtil.dip2px(mContext, mColumnMaxWidths.get(j+1));linearLayout.addView(textView);//右侧分隔线if (j != datas.size() - 1) {View splitView = new View(mContext);ViewGroup.LayoutParams splitViewParmas = new ViewGroup.LayoutParams(DisplayUtil .dip2px(mContext, 1),ViewGroup.LayoutParams.MATCH_PARENT);splitView.setLayoutParams(splitViewParmas);if (!isLockFristRow){if (i==0) {splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.white));} else {splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.light_gray));}}else{splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.light_gray));}linearLayout.addView(splitView);}//加入点击事件// 加入点击事件final int finalJ = j;textView.setClickable(true);final int finalI = i;textView.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.e("断案事件", datas.get(finalJ));String msg = "";if (finalJ == 0) {msg = mTableColumnDatas.get(finalI)+"下一个数据为" + datas.get(finalJ + 1);} else if (finalJ == datas.size() - 1) {msg = "上个数据为" + datas.get(finalJ - 1);} else {msg = "上个数据为" + datas.get(finalJ - 1) + "\n" + "下一个数据为" + datas.get(finalJ + 1);}new AlertDialog.Builder(mContext).setTitle("短按提示").setMessage(msg).setCancelable(true).show();}});// 加入长按事件textView.setOnLongClickListener(new View.OnLongClickListener() {@Overridepublic boolean onLongClick(View v) {Log.e("长按事件", datas.get(finalJ));String msg = "";if (finalJ == 0) {msg = "下一个数据为" + datas.get(finalJ + 1);} else if (finalJ == datas.size() - 1) {msg = "上个数据为" + datas.get(finalJ - 1);} else {msg = "上个数据为" + datas.get(finalJ - 1) + "\n" + "下一个数据为" + datas.get(finalJ + 1);}new AlertDialog.Builder(mContext).setTitle("短按提示").setMessage(msg).setCancelable(true).show();return true;}});}scollViewItemContentView.addView(linearLayout);//底部分隔线View splite=new View(mContext);ViewGroup.LayoutParams spliteLayoutParam= new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,DisplayUtil.dip2px(mContext,1));splite.setLayoutParams(spliteLayoutParam);splite.setBackgroundColor(ContextCompat.getColor(mContext,R.color.light_gray));scollViewItemContentView.addView(splite);}lockScrollViewParent.addView(scollViewItemContentView);mScrollViews.add(lockScrollViewParent);lockScrollViewParent.setOnScrollChangeListener(new CustomHorizontalScrollView.onScrollChangeListener() {@Overridepublic void onScrollChanged(HorizontalScrollView scrollView, int x, int y) {changeAllScrollView(x,y);}});mTableScrollView.addView(lockTableViewContent);}/*** 创建不锁定列视图*/private void createUnLockColumnView() {lockTableViewContent=LayoutInflater.from(mContext).inflate(R.layout.unlocktablecontentview,null);lockScrollViewParent=(CustomHorizontalScrollView) lockTableViewContent.findViewById(R.id.unlockScrollView_parent);//构造滚动视图LinearLayout scollViewItemContentView=new LinearLayout(mContext);LinearLayout.LayoutParams scollViewItemContentViewParams=new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);scollViewItemContentView.setLayoutParams(scollViewItemContentViewParams);scollViewItemContentView.setOrientation(LinearLayout.VERTICAL);for (int i=0;i<mTableRowDatas.size();i++){ArrayList<String> datas=mTableRowDatas.get(i);//设置LinearLayoutLinearLayout linearLayout = new LinearLayout(mContext);LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);linearLayout.setLayoutParams(layoutParams);linearLayout.setGravity(Gravity.CENTER);linearLayout.setOrientation(LinearLayout.HORIZONTAL);if (!isLockFristRow){if (i==0){linearLayout.setBackgroundColor(ContextCompat.getColor(mContext,mFristRowBackGroudColor));}}for (int j = 0; j < datas.size(); j++) {//构造单元格TextView textView = new TextView(mContext);if (!isLockFristRow){if (i==0) {textView.setTextColor(ContextCompat.getColor(mContext, mTableHeadTextColor));} else {textView.setTextColor(ContextCompat.getColor(mContext, mTableContentTextColor));}}else{textView.setTextColor(ContextCompat.getColor(mContext, mTableContentTextColor));}textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextViewSize);textView.setGravity(Gravity.CENTER);textView.setText(datas.get(j));//设置布局LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);textViewParams.setMargins(45, 45, 45, 45);if (isLockFristRow){textViewParams.height=DisplayUtil.dip2px(mContext,mRowMaxHeights.get(i+1));}else{textViewParams.height=DisplayUtil.dip2px(mContext,mRowMaxHeights.get(i));}textView.setLayoutParams(textViewParams);ViewGroup.LayoutParams textViewParamsCopy = textView.getLayoutParams();textViewParamsCopy.width = DisplayUtil.dip2px(mContext, mColumnMaxWidths.get(j));linearLayout.addView(textView);//右侧分隔线if (j != datas.size() - 1) {View splitView = new View(mContext);ViewGroup.LayoutParams splitViewParmas = new ViewGroup.LayoutParams(DisplayUtil.dip2px(mContext, 1),ViewGroup.LayoutParams.MATCH_PARENT);splitView.setLayoutParams(splitViewParmas);if (!isLockFristRow){if (i==0) {splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.white));} else {splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.light_gray));}}else{splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.light_gray));}linearLayout.addView(splitView);}}scollViewItemContentView.addView(linearLayout);//底部分隔线View splite=new View(mContext);ViewGroup.LayoutParams spliteLayoutParam= new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,DisplayUtil.dip2px(mContext,1));splite.setLayoutParams(spliteLayoutParam);splite.setBackgroundColor(ContextCompat.getColor(mContext,R.color.light_gray));scollViewItemContentView.addView(splite);}lockScrollViewParent.addView(scollViewItemContentView);mScrollViews.add(lockScrollViewParent);lockScrollViewParent.setOnScrollChangeListener(new CustomHorizontalScrollView.onScrollChangeListener() {@Overridepublic void onScrollChanged(HorizontalScrollView scrollView, int x, int y) {changeAllScrollView(x,y);}});mTableScrollView.addView(lockTableViewContent);}/*** 改变所有滚动视图位置** @param x* @param y*/private void changeAllScrollView(int x, int y) {if (mScrollViews.size() > 0) {if (mTableViewListener!=null){mTableViewListener.onTableViewScrollChange(x,y);}for (int i = 0; i < mScrollViews.size(); i++) {HorizontalScrollView scrollView = mScrollViews.get(i);scrollView.scrollTo(x, y);}}}/*** 根据最大最小值,计算TextView的宽度** @param textView* @param text* @return*/private int measureTextWidth(TextView textView, String text) {if (textView != null) {LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();int width = DisplayUtil.px2dip(mContext, layoutParams.leftMargin) +DisplayUtil.px2dip(mContext, layoutParams.rightMargin) +getTextViewWidth(textView, text);if (width <= minColumnWidth) {return minColumnWidth;} else if (width > minColumnWidth && width <= maxColumnWidth) {return width;} else {return maxColumnWidth;}}return 0;}/*** 计算TextView高度* @param textView* @param text* @return*/private int measureTextHeight(TextView textView,String text){if (textView != null) {LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams) textView.getLayoutParams();int height = getTextViewHeight(textView, text);if (height<minRowHeight){return minRowHeight;}else if(height>minRowHeight&&height<maxRowHeight){return height;}else{return maxRowHeight;}}return 0;}/*** 根据文字计算textview的高度** @param textView* @param text* @return*/private int getTextViewHeight(TextView textView, String text) {if (textView != null) {int width=measureTextWidth(textView,text);TextPaint textPaint  = textView.getPaint();StaticLayout staticLayout = new StaticLayout(text, textPaint, DisplayUtil.dip2px(mContext,width), Layout.Alignment.ALIGN_NORMAL, 1, 0, false);int height=DisplayUtil.px2dip(mContext,staticLayout.getHeight());return height;}return 0;}/*** 根据文字计算textview的高度** @param view* @param text* @return*/private int getTextViewWidth(TextView view, String text) {if (view != null) {TextPaint paint = view.getPaint();return DisplayUtil.px2dip(mContext, (int) paint.measureText(text));}return 0;}/*** 构造滚动视图** @param scrollView* @param datas* @param isFristRow 是否是第一行*/private void createScollview(HorizontalScrollView scrollView, List<String> datas, boolean isFristRow) {//设置LinearLayoutLinearLayout linearLayout = new LinearLayout(mContext);LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.MATCH_PARENT);linearLayout.setLayoutParams(layoutParams);linearLayout.setGravity(Gravity.CENTER);linearLayout.setOrientation(LinearLayout.HORIZONTAL);for (int i = 0; i < datas.size(); i++) {//构造单元格TextView textView = new TextView(mContext);if (isFristRow) {textView.setTextColor(ContextCompat.getColor(mContext, mTableHeadTextColor));} else {textView.setTextColor(ContextCompat.getColor(mContext, mTableContentTextColor));}textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextViewSize);textView.setGravity(Gravity.CENTER);textView.setText(datas.get(i));//设置布局LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,LinearLayout.LayoutParams.WRAP_CONTENT);textViewParams.setMargins(45, 45, 45, 45);textView.setLayoutParams(textViewParams);ViewGroup.LayoutParams textViewParamsCopy = textView.getLayoutParams();if (isLockFristColumn) {textViewParamsCopy.width = DisplayUtil.dip2px(mContext, mColumnMaxWidths.get(i + 1));} else {textViewParamsCopy.width = DisplayUtil.dip2px(mContext, mColumnMaxWidths.get(i));}linearLayout.addView(textView);//画分隔线if (i != datas.size() - 1) {View splitView = new View(mContext);ViewGroup.LayoutParams splitViewParmas = new ViewGroup.LayoutParams(DisplayUtil.dip2px(mContext, 1),ViewGroup.LayoutParams.MATCH_PARENT);splitView.setLayoutParams(splitViewParmas);if (isFristRow) {splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.white));} else {splitView.setBackgroundColor(ContextCompat.getColor(mContext, R.color.light_gray));}linearLayout.addView(splitView);}}scrollView.addView(linearLayout);}//属性设置public LockTableView setLockFristRow(boolean lockFristRow) {isLockFristRow = lockFristRow;return this;}public LockTableView setLockFristColumn(boolean lockFristColumn) {isLockFristColumn = lockFristColumn;return this;}public LockTableView setMaxColumnWidth(int maxColumnWidth) {this.maxColumnWidth = maxColumnWidth;return this;}public LockTableView setMinColumnWidth(int minColumnWidth) {this.minColumnWidth = minColumnWidth;return this;}public LockTableView setFristRowBackGroudColor(int mFristRowBackGroudColor) {this.mFristRowBackGroudColor = mFristRowBackGroudColor;return this;}public LockTableView setNullableString(String mNullableString) {this.mNullableString = mNullableString;return this;}public LockTableView setTextViewSize(int mTextViewSize) {this.mTextViewSize = mTextViewSize;return this;}public LockTableView setTableHeadTextColor(int mTableHeadTextColor) {this.mTableHeadTextColor = mTableHeadTextColor;return this;}public LockTableView setTableContentTextColor(int mTableContentTextColor) {this.mTableContentTextColor = mTableContentTextColor;return this;}public LockTableView setMaxRowHeight(int maxRowHeight) {this.maxRowHeight = maxRowHeight;return this;}public LockTableView setMinRowHeight(int minRowHeight) {this.minRowHeight = minRowHeight;return this;}public LockTableView setTableViewListener(OnTableViewListener mTableViewListener) {this.mTableViewListener = mTableViewListener;return this;}/*** 设置数据源* @param tableDatas* @return*/public LockTableView setTableViewDatas(ArrayList<ArrayList<String>> tableDatas) {this.mTableDatas = tableDatas;return this;}public LockTableView setScrollToBottom() {Handler mHandler = new Handler();mHandler.post(new Runnable() {@Overridepublic void run() {mTableScrollView.fullScroll(ScrollView.FOCUS_DOWN);}});return this;}public LockTableView setScrollToRight() {Handler mHandler = new Handler();mHandler.post(new Runnable() {@Overridepublic void run() {lockScrollViewParent.fullScroll(ScrollView.FOCUS_RIGHT);}});return this;}/*** 添加数据钱重置* @return*/public LockTableView clear() {mTableFristData.clear();mTableColumnDatas.clear();mTableRowDatas.clear();mContentView.removeAllViews();mLockScrollView.removeAllViews();mTableScrollView.removeAllViews();return this;}//值获取public ArrayList<Integer> getColumnMaxWidths() {return mColumnMaxWidths;}public ArrayList<Integer> getRowMaxHeights() {return mRowMaxHeights;}public LinearLayout getLockHeadView() {return mLockHeadView;}public LinearLayout getUnLockHeadView() {return mUnLockHeadView;}public ArrayList<HorizontalScrollView> getScrollViews() {return mScrollViews;}@Overridepublic void onClick(View v) {}//回调监听public interface OnTableViewListener{/*** 滚动监听* @param x* @param y*/void onTableViewScrollChange(int x,int y);}
}

安卓视线可锁定首行和首列的表格视图相关推荐

  1. uniapp 固定首行和固定列的表格

    准备 在uniapp应用中新建一个页面: css部分用到了sass,开发工具是HbuilderX的话安装sass插件即可. 效果 第一个一个表格是默认样式用作对照,第二个表格是固定了末尾两列和首行的自 ...

  2. 使用jQuery来锁定HTML表格中的首行和首列

    初到公司实习,师傅给了个任务,要求写一个能锁定表格首行和首列的JS文件,类似于Excel那种的.琢磨了一下,记录一下自己学习的过程,有什么需要改进的地方,也希望看的朋友能够指点指点 function ...

  3. 纯css position:sticky 实现表格首行和首列固定

    目录 1.认识position:sticky 2.position:sticky小栗子-实现表格首行和首列固定 2.1 效果图 2.2 代码 1.认识position:sticky 我们先来了解一个c ...

  4. 固定Excel首行和首列作为标题以及某些行和列

    固定Excel首行和首列作为标题以及某些行和列 Excel功能十分强大,可以通过表格形式直观的看很多内容,而且灵活的表格样式设计也让用户有更多的呈现能力,首行和首列一般都作为标题存在,很多时候我们都希 ...

  5. EXCEL中,怎们同时冻结首行和首列

    Excel完美冻结第一行第一列的技巧 Excel冻结窗口是一项非常实用的功能.最近在使用"冻结窗格"功能时发现,同样的表格,在不同的机器上操作,却出现了不同的冻结效果.在有些电脑上 ...

  6. html中固定table的首行和首列

    见代码: <!doctype html> <html lang="en"> <head><meta charset="UTF-8 ...

  7. 如何在Microsoft Excel中迅速冻结首行和末行

    如果你正在处理一个大型电子表格,那么冻结某些行或列会很有用,这样当你滚动浏览工作表的其余部分时,它们会留在屏幕上. 当你在 Excel 中滚动浏览大的工作表时,你可能希望保留一些行或列,例如页眉.Ex ...

  8. 微信小程序 table表格 固定表头和首列 右侧表格可以左右滚动(多种表格演练)

    最近在做公司的项目需要到表格展示数据,但是微信小程序是没有原生table标签的,于是就百度各种搜...发现结构有类似的就粘过来修改,要善于学习和借鉴别人的经验使其变成为自己的东西,学无止境~ 在这里做 ...

  9. 【Linux脚本-sed命令在文本首行和尾行插入空行】

    @[TOC]Linux脚本-sed命令在文本首行和尾行插入空行 Linux脚本-sed命令在文本首行和尾行插入空行 演示如下: 首先创建需要操作的文本文件 //create a file contai ...

最新文章

  1. 直接铸造与“ as”运算符?
  2. 性能监控和分析工具--nmon
  3. centos 编译 mysql_centos 编译安装mysql
  4. 深度学习caffe的代码怎么读?
  5. linux以16进制查看文件
  6. Java集合篇:Hashtable原理详解(JDK1.8)
  7. neo4j数据浏览器_Neo4j:在Neo4j浏览器的帮助下探索新数据集
  8. CentOS录屏快捷键
  9. 吴恩达机器学习笔记 1单变量线性回归
  10. 责任分配矩阵和raci的区别_有限责任公司实现盈利,当年就一定可以分红吗?...
  11. [渝粤教育] 中国地质大学 现代控制理论 复习题 (2)
  12. 阿里云前端周刊 - 第 9 期
  13. 图像算法之3D人脸识别技术原理概述
  14. ArcFace 论文阅读及 pytorch 实现
  15. CSS 零基础到实战(05)布局、盒子模型、弹性盒子【前端就业课 第二阶段】
  16. java 前后端分离教程,Java web前后端分离
  17. Microsoft软件保护平台服务一直占用大量CPU资源
  18. 第二章 查询结果排序(SQL server经典实例)
  19. 如何友好提示vue3.0不再支持IE11及以下的浏览器版本
  20. keil5 c语言函数库,C语言中KeilC51库函数大全.doc

热门文章

  1. 牛客网数据库SQL实战25—— 获取员工其当前的薪水比其manager当前薪水还高的相关信息
  2. ant jeecg vue 前端通过dom节点 导出xlsx表格
  3. ios html5 audio mp3,H5 audio 微信端 在IOS上不能播放音乐
  4. 春天正是补气的好时刻,喝枸杞+黄芪就对了
  5. 亚信安全中标北方网“津云”项目 护航“云+网”全媒体平台
  6. OCAD应用:反射棱镜的初始结构设计
  7. pytest文档56-插件打包上传到 pypi 库
  8. 水果店圈子:水果店怎么入门,水果店工作注意什么
  9. nginx限流防刷方案
  10. 引流复盘:从知乎引流20万粉,我只用了1个月