近期公司要做报表功能,在网上搜索下表格的样式后便自己写了一个自定义的表格控件,该表格控件能根据设置的数据中数据的最大值自动设置左侧信息栏显示的值,使得条形图能尽量的充满控件,条形图部
近期公司要做报表功能,在网上搜索下表格的样式后便自己写了一个自定义的表格控件,该表格控件能根据设置的数据中数据的最大值自动设置左侧信息栏显示的值,使得条形图能尽量的充满控件,条形图部分支持左右滑动,数据的长度可能超过控件本身所能容纳的长度,所以在绘制的时候做了判断,当需要绘制的部分不再控件范围内则不进行绘制,具体请阅读代码,目前只支持一个名称对应一条数据,如有不足之处,大家提出帮忙修改
使用方法如下:
在xml文件中定义控件属性
<RelativeLayout
xmlns:Android="Http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#333333"
tools:context=".MainActivity">
<com.example.administrator.widget.MyChatView
android:id="@+id/chatView"
android:layout_width="match_parent"
android:layout_height="250dp"
android:layout_marginTop="100dp"
android:background="#FFFFFF"
/>
</RelativeLayout>
在Activity中设置控件要显示的数据、设置显示的样式
public class MainActivity extends AppCompatActivity {
private MyChatView mMyChatView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mMyChatView = (MyChatView) this.findViewById(R.id.chatView);
mMyChatView.setData(getData1())
.setDataCompany("美元")
.setDataTitle("测试")
.setLeftTextColor(Color.RED)
.setBottomTextColor(Color.BLUE)
.setmDataTopTextColor(Color.RED) .setDataBackgroundColor(Color.parseColor("#ABCDEF"))
.setDataColor(Color.RED)
.setTitleColor(Color.BLUE)
.setLeftTextSize(12)
.setBottomTextSize(15)
.setDataTopTextSize(10)
.setTitleTextSize(20)
.setSpanBottomText(15);
}
private List<Map<String, String>> getData1(){
List<Map<String, String>> data = new ArrayList<>();
HashMap<String, String> map;
int temp;
for (int i=0; i<100; i++) {
map = new HashMap<>();
map.put(MyChatView.NAME, "name:"+i);
temp = (int) (Math.random()*100);
map.put(MyChatView.VALUE, temp +"."+i*i);
data.add(map);
}
return data;
}
}
自定义控件代码:
public class MyChatView extends View {
public static final String NAME = "name";
public static final String VALUE = "value";
private Context mContext;
private int mHeight;
private int mWidget;
private List<Map<String, String>> mData;
private String mDataCompany = "单位: ";
private String mDataTitle = null;
private int mBottomTextSize;
private int mLeftTextSize;
private int mDataTopTextSize;
private int mTitleTextSize;
private int mSpanLeftText;
int mSpanDataTopText;
int mSpanBottomText;
int mSpanBottom;
private int mDataBackgroundColor = Color.WHITE;
private int mBottomTextColor = Color.BLACK;
private int mDataColor = Color.BLACK;
private int mLeftTextColor = Color.BLACK;
private int mDataTopTextColor = Color.BLACK;
private int mTitleColor = Color.BLACK;
private int mChartMovedSize = 0;
private int mDownX = 0;
private int mUpX = 0;
private int mChartMaxMovedLengthX;
public MyChatView(Context context) {
this(context, null);
}
public MyChatView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public MyChatView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
this.mContext = context;
this.mBottomTextSize = dpToPx(context, 15);
this.mLeftTextSize = dpToPx(context, 10);
this.mDataTopTextSize = dpToPx(context, 10);
this.mSpanLeftText = dpToPx(context, 2);
this.mSpanDataTopText = dpToPx(context, 3);
this.mSpanBottomText = dpToPx(context, 10);
this.mSpanBottom = dpToPx(context, 8);
this.mTitleTextSize = dpToPx(context, 20);
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.mHeight = h;
this.mWidget = w;
}
@Override
public boolean onTouchEvent(@NonNull MotionEvent event) {
int action = event.getAction();
switch (action) {
case MotionEvent.ACTION_DOWN:
mDownX = (int) event.getX();
break;
case MotionEvent.ACTION_MOVE:
mUpX = (int) event.getX();
shouldMoveChart();
break;
case MotionEvent.ACTION_UP:
mUpX = (int) event.getX();
shouldMoveChart();
break;
}
return true;
}
private void shouldMoveChart (){
if (mChartMaxMovedLengthX<mWidget) {
this.mChartMaxMovedLengthX = (getXTotalLength() - mWidget*2/3);
}
int size = dpToPx(mContext, 2);
if ((mUpX-mDownX)>=size || (mDownX-mUpX)>=size ) {
mChartMovedSize += (mUpX - mDownX);
mDownX = mUpX;
if (mChartMovedSize>=0) {
mChartMovedSize = 0;
}
if (mChartMovedSize<-mChartMaxMovedLengthX) {
mChartMovedSize = -mChartMaxMovedLengthX;
}
this.invalidate();
}
}
private InnerDraw innerDraw;
@Override
protected void onDraw(canvas canvas) {
super.onDraw(canvas);
if (innerDraw==null) {
innerDraw = new InnerDraw(canvas);
} else {
innerDraw.initData(canvas);
}
innerDraw.drawLeftMenue();
innerDraw.drawDataBackground();
innerDraw.drawDataTitle();
innerDraw.drawCompany();
int dataSize = mData.size();
for (int i=0; i<dataSize; i++) {
//设置数据,必须在第一行
int state = innerDraw.startDrawBody(mData.get(i), i);
if (state==0) {
continue;
} else if (state==-1) {
break;
}
innerDraw.drawDataTopText();
innerDraw.drawDataBar();
innerDraw.drawBottomMessage();
innerDraw.endDrawBody();
}
}
private int getTextHeight (Paint paint, int textSize){
String text = "测试";
Rect rect = new Rect();
paint.setTextSize(textSize);
paint.getTextBounds(text, 0, text.length(), rect);
return rect.height();
}
private int getTextWidth (Paint paint, String text, int textSize){
Rect rect = new Rect();
paint.setTextSize(textSize);
paint.getTextBounds(text, 0, text.length(), rect);
return rect.width();
}
private String getLeftValueMaxString (){
int size = mData.size();
String maxLengthString = "1";
String tempString;
for (int i=0; i<size; i++) {
tempString = mData.get(i).get(VALUE);
if (tempString.length()>maxLengthString.length()) {
maxLengthString = tempString;
}
}
if (maxLengthString.contains(".")) {
maxLengthString = maxLengthString.substring(0, maxLengthString.indexOf('.')+2);
}
return maxLengthString;
}
private String getBottomMaxLegthString (){
int size = mData.size();
String maxString = "你好我好大家好才是真的好";
String tempString;
for (int i=0; i<size; i++) {
tempString = mData.get(i).get(NAME);
if (maxString.length()>tempString.length()) {
maxString = tempString;
}
}
return maxString;
}
private int getMaxValue (){
int maxValue = Float.valueOf(mData.get(0).get(VALUE)).intValue();
int tempValue;
for (Map<String, String> map : mData) {
tempValue = Float.valueOf(map.get(VALUE)).intValue();
if (maxValue<tempValue) {
maxValue = tempValue + tempValue/10;
}
}
return maxValue;
}
private int getXTotalLength(){
int xTotalLength = 0;
Paint paint = new Paint();
for (Map<String, String> map : mData) {
xTotalLength += getTextWidth(paint, map.get(NAME), mBottomTextSize);
xTotalLength = xTotalLength + mSpanBottomText;
}
return xTotalLength;
}
private int getPiceValue (int maxValue){
int piceValue = 1;
while (maxValue>10) {
maxValue = maxValue/10;
piceValue = piceValue * 10;
}
if (maxValue<=5) {
piceValue = piceValue / 2;
}
return piceValue;
}
private int dpToPx(Context context, float dpValue) {
final float scale = context.getResources().getDisplayMetrics().density;
return (int) (dpValue * scale + 0.5f);
}
public MyChatView setData (List<Map<String, String>> data){
try {
this.mData = data==null? new ArrayList<Map<String, String>>():data;
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setDataBackgroundColor (int dataBackgroundColor){
try {
this.mDataBackgroundColor = dataBackgroundColor;
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setLeftTextColor (int leftTextColor){
try {
this.mLeftTextColor = leftTextColor;
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setBottomTextColor (int bottomTextColor){
try {
this.mBottomTextColor = bottomTextColor;
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setDataColor (int dataColor){
try {
this.mDataColor = dataColor;
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setmDataTopTextColor (int dataTopTextColor){
try {
this.mDataTopTextColor = dataTopTextColor;
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setTitleColor (int titleColor){
try {
this.mTitleColor = titleColor;
}catch (Exception e){
e.printStackTrace();
}
return this;
}
public MyChatView setBottomTextSize (int bottomTextSize){
try {
this.mBottomTextSize = dpToPx(mContext, bottomTextSize);
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setLeftTextSize (int leftTextSize){
try {
this.mLeftTextSize = dpToPx(mContext, leftTextSize);
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setDataTopTextSize (int dataTopTextSize){
try {
this.mDataTopTextSize = dpToPx(mContext, dataTopTextSize);
}catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setTitleTextSize (int titleTextSize){
try {
this.mTitleTextSize = dpToPx(mContext,titleTextSize);
} catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setDataCompany (String dataCompany){
try {
this.mDataCompany += dataCompany==null? "空":dataCompany;
} catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setDataTitle (String dataTitle){
try {
mDataTitle = dataTitle;
} catch (Exception e) {
e.printStackTrace();
}
return this;
}
public MyChatView setSpanBottomText (int spanBottomText){
try {
this.mSpanBottomText = dpToPx(mContext, spanBottomText);
} catch (Exception e){
e.printStackTrace();
}
return this;
}
/
private class InnerDraw{
private Canvas canvas;
private Paint paint;
private int bottomTextPainted;
private int bottomTitleHeight;
private int bottomMessageHeight;
private String leftValueMaxString;
private int dataTopTextHeight;
private int leftValueWidth;
private int chartDataHeight;
private int piceValueHeight;
private int piceValue;
private int dataBarWidth;
String bottomMessage;
private int bottomMessageWidth;
Map<String, String> data;
int index;
public InnerDraw (Canvas canvas){
initData(canvas);
}
public void initData(Canvas canvas){
this.canvas = canvas;
this.paint = new Paint();
this.bottomTitleHeight = mDataTitle==null? 0:(getTextHeight(paint, mTitleTextSize)+mSpanBottom/2);
this.bottomTextPainted = 0;
this.bottomMessageHeight = getTextHeight(paint, mBottomTextSize) + mSpanBottom + bottomTitleHeight;
this.leftValueMaxString = getLeftValueMaxString();
this.dataTopTextHeight = getTextHeight(paint, mDataTopTextSize);
this.leftValueWidth = getTextWidth(paint, leftValueMaxString , mLeftTextSize) + mSpanLeftText;
this.chartDataHeight = mHeight - bottomMessageHeight - mSpanBottom;
this.piceValueHeight = (chartDataHeight-dataTopTextHeight-getTextHeight(paint, mSpanDataTopText))/10;
this.piceValue = getPiceValue(getMaxValue());
this.dataBarWidth = getTextWidth(paint, getBottomMaxLegthString(), mBottomTextSize);
this.bottomMessage = "";
this.bottomMessageWidth = 0;
this.data = new HashMap<>();
this.index = 0;
}
public void drawLeftMenue(){
paint.setColor(mLeftTextColor);
paint.setTextSize(mLeftTextSize);
int textLeft;
int textTop;
String valueStr;
int strLength;
String maxValueStr = String.valueOf(piceValue * 10);
int textMaxLength = maxValueStr.length();
int topTextHeight = getTextHeight(paint, mDataTopTextSize);
int leftTextHeight = getTextHeight(paint, mLeftTextSize);
for (int i=0; i<=10; i++) {
textLeft = 0;
valueStr = String.valueOf(i * piceValue);
strLength = valueStr.length();
if (strLength<textMaxLength) {
textLeft = getTextWidth(paint, maxValueStr.substring(strLength), mLeftTextSize);
}
textTop = (10-i)*piceValueHeight + topTextHeight + mSpanDataTopText + leftTextHeight/2;
canvas.drawText(valueStr+"", textLeft, textTop, paint);
}
}
public void drawDataBackground() {
paint.setColor(mDataBackgroundColor);
Rect rect = new Rect(leftValueWidth, 0, mWidget, chartDataHeight);
canvas.drawRect(rect, paint);
}
public void drawDataTitle() {
if (mDataTitle != null) {
paint.setColor(mTitleColor);
paint.setTextSize(mTitleTextSize);
int titleWidget = getTextWidth(paint, mDataTitle, mTitleTextSize);
float titleLeft = (mWidget - titleWidget) / 2;
float titleTop = mHeight - mSpanBottom;
canvas.drawText(mDataTitle, titleLeft, titleTop, paint);
}
}
public void drawCompany() {
paint.setTextSize(mLeftTextSize);
paint.setColor(mLeftTextColor);
int comPanyLeft = mWidget - getTextWidth(paint, mDataCompany + "111", mLeftTextSize);
int companyBottom = dataTopTextHeight + getTextHeight(paint, mLeftTextSize);
canvas.drawText(mDataCompany, comPanyLeft, companyBottom, paint);
}
public int startDrawBody(Map<String, String> data, int index){
this.data = data;
this.bottomMessage = data.get(NAME).trim();
this.bottomMessageWidth = getTextWidth(paint, bottomMessage, mBottomTextSize);
this.index = index;
int bottomMsgBegainDrawX = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted;
if ((bottomMsgBegainDrawX+bottomMessageWidth)<leftValueWidth) {//需要绘制的区域在绘制区域的左侧
bottomTextPainted += bottomMessageWidth;
return 0;
}
if (bottomMsgBegainDrawX>mWidget) {//需要绘制的区域超出了控件的右边,结束绘制
return -1;
}
return 1;
}
public void endDrawBody(){
bottomTextPainted += bottomMessageWidth;
}
public void drawBottomMessage() {
paint.setColor(mBottomTextColor);
paint.setTextSize(mBottomTextSize);
int bottomLeft = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted;
int bottomTop = chartDataHeight + bottomMessageHeight - bottomTitleHeight - dpToPx(mContext, 2);
if (bottomLeft >= leftValueWidth && bottomLeft < mWidget) {
canvas.drawText(bottomMessage, bottomLeft, bottomTop, paint);
} else if ((bottomLeft+bottomMessageWidth)>leftValueWidth) {
int index = (leftValueWidth-bottomLeft)*bottomMessage.length()/bottomMessageWidth+1;
if (index>=0 && index <bottomMessage.length()) {
canvas.drawText(bottomMessage.substring(index), leftValueWidth, bottomTop, paint);
}
}
}
public void drawDataBar() {
paint.setColor(mDataColor);
int dataValue = Float.valueOf(data.get(VALUE)).intValue();
int bottomLeft = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted;
int dataLeft = bottomLeft + bottomMessageWidth / 2 - dataBarWidth / 4;
int dataBottom = chartDataHeight;
int dataTop = chartDataHeight - (dataValue * (chartDataHeight - dataTopTextHeight - mSpanDataTopText) / piceValue) / 10;
int dataRight = dataLeft + dataBarWidth / 2;
if (dataLeft < leftValueWidth && dataRight > leftValueWidth) {
dataLeft = leftValueWidth;
}
Rect dataRect = new Rect(dataLeft, dataTop, dataRight, dataBottom);
if (dataRight>leftValueWidth) {
canvas.drawRect(dataRect, paint);
}
}
public void drawDataTopText() {
String topTextMessage = data.get(VALUE);
int topTextWidth = getTextWidth(paint, topTextMessage, mDataTopTextSize);
paint.setColor(mDataTopTextColor);
paint.setTextSize(mDataTopTextSize);
int bottomLeft = (index + 1) * mSpanBottomText + mChartMovedSize + leftValueWidth + bottomTextPainted;
int topTextLeft = bottomLeft + (bottomMessageWidth - topTextWidth) / 2;
int dataValue = Float.valueOf(data.get(VALUE)).intValue();
int dataTop = chartDataHeight - (dataValue*(chartDataHeight-dataTopTextHeight - mSpanDataTopText)/piceValue)/10;
int topTextTop = dataTop - mSpanDataTopText * 2 / 3;
if (topTextLeft >= leftValueWidth && bottomLeft < mWidget) {
canvas.drawText(topTextMessage, topTextLeft, topTextTop, paint);
} else if ((topTextLeft+topTextWidth)>leftValueWidth) {
int index = (leftValueWidth-topTextLeft)*topTextMessage.length()/topTextWidth+1;
if (index>=0 && index <topTextMessage.length()) {
canvas.drawText(topTextMessage.substring(index), leftValueWidth, topTextTop, paint);
}
}
}
}
}
实现效果如下图
--结束END--
本文标题: Android表格自定义控件使用详解
本文链接: https://lsjlt.com/news/143298.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-01-21
2023-10-28
2023-10-28
2023-10-27
2023-10-27
2023-10-27
2023-10-27
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0