自定义的textView,满足一些的特殊的需求。
效果如下:
1.自定义的类
package com.zhang.test; import android.content.Context; import android.content.res.TypedArray; import android.graphics.Canvas; import android.graphics.Paint; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; import android.view.MotionEvent; import android.view.View; /** * @author Zhang * * @date 2016-7-12 */ public class MyTextView extends View { private final static String TAG = "MyTextView"; /** 文字颜色 */ private int textColor; /** Button文字颜色 */ private int buttonTextColor; /** 文字大小 */ private float textSize; /** 文字内容 */ private String text; /** button文字内容 */ private String buttonText; /** 绘制文字的画笔 */ private Paint mPaint; /** 绘制button文字的画笔 */ private Paint mPaint2; /** 最后的文字 */ private String buttonString = "阅读全文"; /** 每行文字间的距离 默认是0个dp */ private float gap; // 后面能点击的文字的宽度 private float buttonWidth; private float paddingLeft; private float paddingRight; private float paddingTop; private float paddingBottom; // private float width; private int backSrcId; private int DEFAULT_WIDTH; private GestureDetector myDetector; private int mlineNumber;//行数 private MyClickListener l; /** 绘制…需要的宽度 */ private float dianWidth; public MyTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); //context通过调用obtainStyledAttributes方法来获取一个TypeArray, // 然后由该TypeArray来对属性进行设置 // 调用结束后务必调用recycle()方法,否则这次的设定会对下次的使用造成影响 TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.mytextView); // 字体默认为黑色 textColor = a.getColor(R.styleable.mytextView_textColor, 0xff000000); // button文字颜色默认为黑色 buttonTextColor = a.getColor(R.styleable.mytextView_buttonTextColor, 0xffffffff); // 文字大小默认15sp textSize = spToPx(a.getInt(R.styleable.mytextView_textSize, 15)); // 文字 text = a.getString(R.styleable.mytextView_text); // button 文字 buttonText = a.getString(R.styleable.mytextView_buttonText); //设置padding paddingLeft = dpToPx(a.getInt(R.styleable.mytextView_paddingLeft, 5)); paddingRight = dpToPx(a.getInt(R.styleable.mytextView_paddingRight, 5)); paddingTop = dpToPx(a.getInt(R.styleable.mytextView_paddingTop, 5)); gap = dpToPx(a.getInt(R.styleable.mytextView_linegap, 0)); backSrcId = a.getResourceId(R.styleable.mytextView_backgroud, -1); paddingBottom = dpToPx(a .getInt(R.styleable.mytextView_paddingBottom, 5)); a.recycle(); mPaint = new Paint(); mPaint.setColor(textColor); mPaint.setTextSize(textSize); dianWidth = mPaint.measureText("..."); myDetector = new GestureDetector(context, new MyDetectorListener()); mPaint2 = new Paint(); mPaint2.setColor(buttonTextColor); mPaint2.setTextSize(textSize); buttonWidth = mPaint2.measureText(buttonString); // DEFAULT_WIDTH=(int) (paddingTop + (3) * textSize + gap // * (3) + paddingBottom); // getDefaultHeigt(text); } /** * 获取真实的高度 * * @param text */ public void getDefaultHeigt(String text) { int width = getWidth(); // Log.d(TAG, "myWidth="+width); float textWidth = mPaint.measureText(text); //判断是否大于两行, if (((paddingLeft + paddingRight) * 2 + textWidth) > width * 2) { mlineNumber = 3; } else if ((paddingLeft + paddingRight + textWidth) > width) { mlineNumber = 2; } else { mlineNumber = 1; } // Log.d(TAG, "lineNumber="+lineNumber); DEFAULT_WIDTH = (int) (paddingTop + mlineNumber * textSize + gap * mlineNumber + paddingBottom); } public void setText(String text) { this.text = text; requestLayout(); invalidate(); } public MyTextView(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyTextView(Context context) { this(context, null); } @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); // 控件的宽度 float width = getWidth(); width = width - paddingLeft - paddingRight; // 当前文字的行数 int lineNumber = 0; if (text == null) { return; } char[] charArray = text.toCharArray(); // 已绘制的宽度 float drawWidth = 0; // 字符的长度 float charWidth = 0; for (int i = 0; i < charArray.length; i++) { charWidth = mPaint.measureText(charArray, i, 1); if (lineNumber > mlineNumber - 1) { break; } if (charArray[i] == '\n') { lineNumber++; continue; } if (lineNumber == mlineNumber - 1) { // 剩余留给“…”的位置 float yuWidth = width - buttonWidth - drawWidth-charWidth; if (yuWidth > dianWidth) { canvas.drawText(charArray, i, 1, paddingLeft + drawWidth, paddingTop + (lineNumber + 1) * textSize + lineNumber * gap, mPaint); } else { canvas.drawText("...", paddingLeft + drawWidth, paddingTop + (lineNumber + 1) * textSize + lineNumber * gap, mPaint); break; } drawWidth += charWidth; } else { if (drawWidth + charWidth > width) { lineNumber++; drawWidth = 0; } canvas.drawText(charArray, i, 1, paddingLeft + drawWidth, paddingTop + (lineNumber + 1) * textSize + lineNumber * gap, mPaint); drawWidth += charWidth; } } canvas.drawText("阅读全文", getWidth() - paddingRight - buttonWidth, paddingTop + (lineNumber + 1) * textSize + lineNumber * gap, mPaint2); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); Log.d(TAG, "onMeasure"); getDefaultHeigt(text); Log.d(TAG, DEFAULT_WIDTH + ""); //最大尺寸 if (heightSpecMode == MeasureSpec.AT_MOST) { setMeasuredDimension(widthSpecSize, DEFAULT_WIDTH); } else if (heightSpecMode == MeasureSpec.UNSPECIFIED) {//未指定尺寸 setMeasuredDimension(widthSpecSize, DEFAULT_WIDTH); } } public float spToPx(int value) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value, getResources().getDisplayMetrics()); } public float dpToPx(int value) { return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, getResources().getDisplayMetrics()); } @Override public boolean onTouchEvent(MotionEvent event) { myDetector.onTouchEvent(event); return true; } public interface MyClickListener { public void onClick(); } private class MyDetectorListener extends SimpleOnGestureListener { @Override public boolean onSingleTapUp(MotionEvent e) { // Log.d(TAG, "onSingleTapUp"); float y = e.getY(); float x = e.getX(); float xstart = getWidth() - paddingRight - buttonWidth; float xend = getWidth() - paddingRight; float ystart = paddingTop + (mlineNumber - 1) * (textSize + gap); float yend = ystart + textSize; if (x > xstart && x < xend && y > ystart && y < yend) { if (l != null) { l.onClick(); return true; } } return true; } } public void setMyClickListener(MyClickListener l) { this.l = l; } }
2.布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:myText="http://schemas.android.com/apk/res/com.zhang.test"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.zhang.test.MyTextView
android:id="@+id/myTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="20dp"
myText:buttonTextColor="@color/blue"
myText:paddingLeft="10"
myText:paddingRight="10"
myText:paddingTop="10"
myText:text="\u3000\u3000外交部发言人陆慷12日表示,所谓南海仲裁庭一开始就是建立在菲律宾违法行为和非法诉求基础上,它的存在不具备合法性,它做的一切裁决都是徒劳的、没有任何效力的。针对美国对自己及其盟友打开海洋法治的“违法之门”的行为,陆慷表示美方对国际法“合则用不合则弃”的投机做法才是危险的,值得国际社会高度警惕。"
myText:textSize="18"
myText:linegap="10"
android:background="@drawable/backgroubd"
android:clickable="true">
</com.zhang.test.MyTextView>
</LinearLayout>
3.attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="mytextView">
<attr name="textColor" format="reference|color"></attr>
<attr name="text" format="reference|string"></attr>
<attr name="textSize" format="reference|integer"></attr>
<attr name="buttonText" format="reference|string"></attr>
<attr name="buttonTextColor" format="reference|color"></attr>
<attr name="backgroud" format="reference">></attr>
<!-- 行与行之间的距离 -->
<attr name="linegap" format="reference|integer"></attr>
<attr name="paddingLeft" format="reference|integer"></attr>
<attr name="paddingRight" format="reference|integer"></attr>
<attr name="paddingBottom" format="reference|integer"></attr>
<attr name="paddingTop" format="reference|integer"></attr>
</declare-styleable>
</resources>
4.Textactivity.java
package com.zhang.test;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
/**
* @author zhang
*
*/
public class TextActivity02 extends Activity {
// private TextView textView,btn,text01;
private MyTextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.text02);
textView=(MyTextView) findViewById(R.id.myTextView);
textView.setMyClickListener(new MyTextView.MyClickListener() {
@Override
public void onClick() {
Toast.makeText(TextActivity02.this,"dianjil",Toast.LENGTH_LONG).show();
}
});
}
}