簡述:
- 為什么要另寫這篇Demo博客?
上篇博客最后給出了一個折線圖的例子兽狭,記得當(dāng)時是說下篇博客給出其源碼腊尚,但是后來我又想了下,咱們既然是新手系列的自定義View庵佣,內(nèi)容就需要做到詳細(xì)歉胶,清楚和明白。如果隨意丟出一坨源碼對于新手來說太坑爹了巴粪,我們每一位老司機(jī)都是從新手走過來通今,相信大家對于動不動就扔出一坨代碼博主,心中很是無奈肛根。今天咱們就簡單分析下這個demo辫塌。
- 回答上篇博客的問題?
上篇博客說到如何在一個自定義View中對某個特定區(qū)域?qū)崿F(xiàn)點(diǎn)擊觸摸反饋派哲。我們都知道對于View獨(dú)立單一組件唯一可以設(shè)置點(diǎn)擊的就是對整個View設(shè)置點(diǎn)擊事件臼氨。對于一個View控件的某個區(qū)域也能實(shí)現(xiàn)點(diǎn)擊觸摸反饋嗎?答案是可以的芭届,本期的例子柱狀圖也是只有點(diǎn)擊矩形才會有事件觸發(fā)储矩,而不是整個View控件。這實(shí)際上就是用到了一個特殊的API的Region區(qū)域褂乍。它可以框出某個VIew的某個特定的區(qū)域持隧,然后在View的OnTouchEvent事件中,監(jiān)聽手指按下和抬起點(diǎn)是否落入對應(yīng)的Region區(qū)域逃片,如果落入就會給出回調(diào)屡拨,就這么簡單粗暴。
- 自定義View直方圖思路分析?
首先從整個控件角度出發(fā)洁仗,任何控件實(shí)現(xiàn)都得包括了數(shù)據(jù)接口定義和UI渲染繪制兩個方面。
對于數(shù)據(jù)接口定義性锭,從本控件可以看到就兩個數(shù)據(jù)因素赠潦,一是類型對應(yīng)的名稱(String),二是對應(yīng)類型占最大值得比例(float),用比例更加直觀反映出繪制的高度。兩個數(shù)據(jù)因素草冈,很多人認(rèn)為寫個類包一下她奥,個人感覺對于View層直接渲染數(shù)據(jù)越是簡單數(shù)據(jù)類型,它的通用性越強(qiáng)怎棱。所以我想到的時候通過外部傳入一個List < Pair < String, float> >即可哩俭。
對于UI渲染繪制,考慮有兩個方面靜態(tài)繪制和點(diǎn)擊交互拳恋。
對于靜態(tài)繪制可以分為純直方圖的繪制和折線圖繪制凡资。
直方圖的繪制包括坐標(biāo)系繪制、文字集合繪制谬运、矩形集合繪制隙赁。
對于坐標(biāo)系繪制為了計算繪制坐標(biāo)方便,將原來默認(rèn)為View左上角的坐標(biāo)原點(diǎn)梆暖,通過translate位移canvas畫布正好移動到直方圖坐標(biāo)的原點(diǎn)位置伞访。 文字的繪制就是上期博客講的,不過是文字集合通過一個循環(huán)來繪制轰驳,矩形集合的繪制使用的是循環(huán) + path.addRect方式厚掷,最后繪制整個Path就OK。
折線圖的繪制包括點(diǎn)的集合繪制级解、線段的集合繪制冒黑。
點(diǎn)集合繪制采用的是drawPoints繪制多個點(diǎn),線段集合繪制采用drawLines繪制多條線蠕趁。
對于點(diǎn)擊交互就比較麻煩點(diǎn)薛闪,思路是定義一個和View控件畫布一樣大小的Region,姑且定義為globalRegion.然后針對每一個矩形都定義一個Path和Region.把每個矩形通過path.addRect加入對應(yīng)的Path中,通過region.setPath(path, globalRegion)將path區(qū)域和clip區(qū)域取交集俺陋,捕獲出對應(yīng)path的region區(qū)域坐標(biāo)范圍豁延。最后把每個path添加到全局的mPath中,把每個region區(qū)域加入mRegionList集合中腊状。
通過重寫onTouchEvent,獲得點(diǎn)擊的點(diǎn)的坐標(biāo)诱咏,通過遍歷mRegionList集合判斷觸摸點(diǎn)是否落入對應(yīng)的區(qū)域的Region的position。然后再次重繪缴挖,在onDraw方法中針對相應(yīng)的position繪制不同顏色背景矩形即可袋狞。
最后一個坑就是坐標(biāo)轉(zhuǎn)換,因為在繪制的時候我們?yōu)榱擞嬎阕鴺?biāo)簡單將坐標(biāo)系原點(diǎn)移到直方圖坐標(biāo)原點(diǎn)位置,但是在onTouchEvent觸摸坐標(biāo)系卻還是以View左上角為原點(diǎn)的坐標(biāo)系苟鸯,所以需要有個觸摸點(diǎn)坐標(biāo)系向繪制坐標(biāo)系的轉(zhuǎn)換同蜻。利用了Matrix矩陣中逆矩陣的知識。
-
本篇博客包含哪些核心知識點(diǎn)內(nèi)容早处?
Canvas中繪制矩形(上篇博客已經(jīng)講過)
Canvas的繪制多條線段(上篇博客已經(jīng)講過)
Canvas的繪制多個點(diǎn)(上篇博客已經(jīng)講過)
Canvas繪制文字(上篇博客已經(jīng)講過)
Canvas的幾何變換使用translate移動繪圖坐標(biāo)系(后期博客會詳細(xì)講解湾蔓,可以先記住一下,下次講的時候不會太陌生)
Canvas的繪制Path(下期博客會詳細(xì)講解砌梆,可以先記住一下默责,下次講的時候不會太陌生)
Canvas中的Path與Region的組合使用裁切矩形區(qū)域。(難點(diǎn),下期會深入講解)
Region區(qū)域的使用判斷觸摸點(diǎn)是否落入柱狀圖形的范圍區(qū)域并給出觸摸反饋的回調(diào)咸包。(難點(diǎn),下期會深入講解)
變換坐標(biāo)系后桃序,通過Matrix類的逆矩陣實(shí)現(xiàn),觸摸坐標(biāo)系的坐標(biāo)向繪圖坐標(biāo)的坐標(biāo)轉(zhuǎn)換烂瘫。(難點(diǎn),下期會深入講解)
1媒熊、數(shù)據(jù)接口定義List < Pair < String, float> >類型
- 使用基本數(shù)據(jù)類型,有利于提高View的通用性
List<Pair<String,Float>> pairList = new ArrayList<>(); pairList.add(new Pair<>("Java",0.71f));
pairList.add(new Pair<>("Swift",0.61f));
pairList.add(new Pair<>("C",0.26f));
pairList.add(new Pair<>("C++",0.37f));
pairList.add(new Pair<>("Python",0.84f));
pairList.add(new Pair<>("Go",0.6f));
setContentView(new RectChart(this, pairList));//直接給contentView設(shè)置自定義View
2忱反、坐標(biāo)軸的繪制
- 為了繪制方便和坐標(biāo)計算方便泛释,采用translate位移畫布將原來View左上角原點(diǎn)移動到直方圖原點(diǎn)(控件中兩個坐標(biāo)軸交點(diǎn)位置)
//初始化坐標(biāo)系畫布
private void initCoordinateCanvas(Canvas canvas) {
canvas.drawColor(Color.parseColor("#eeeeee"));//繪制畫布純色背景
canvas.translate(100, mHeight - 100);//平移坐標(biāo)系,原來View左上角原點(diǎn)移動到直方圖原點(diǎn)
// 獲取測量矩陣(逆矩陣) 由于繪制畫布的View坐標(biāo)系被平移了温算,
// 但是所處的觸摸坐標(biāo)系并沒有改變怜校,需要利用Matrix矩陣實(shí)現(xiàn)觸摸坐標(biāo)系向繪制坐標(biāo)系轉(zhuǎn)化
if (mMatrix.isIdentity()) {
canvas.getMatrix().invert(mMatrix);
}
float[] opts = {0, 0, mWidth - 200, 0, 0, 0, 0, -(mHeight - 200)};//兩條線8個點(diǎn)坐標(biāo)數(shù)據(jù)
canvas.drawLines(opts, mCoordinatePaint);//繪制兩條線
mCoordinatePaint.setStrokeCap(Paint.Cap.ROUND);//繪制點(diǎn)為圓點(diǎn)
mCoordinatePaint.setStrokeWidth(20f);//設(shè)置點(diǎn)的大小
canvas.drawPoint(0, 0, mCoordinatePaint);//繪制兩條線段
}
3、文字集合的繪制
- 文字繪制采用了paint.setTextBounds方式拿到文字的尺寸
//初始化文字畫筆
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(Color.parseColor("#C2185B"));
mTextPaint.setTextSize(40);
if (mDataList == null || mDataList.isEmpty()) {
return;
}
//先取出數(shù)據(jù)中所有的文字測量每個文字尺寸注竿,并把每個文字尺寸信息記錄在對應(yīng)的rect中茄茁,通過paint.getTextBounds(text,start,end,rect),
// 最后把每個文字的rect保存在集合中
for (Pair<String, Float> pair : mDataList) {
Rect textBound = new Rect();
mTextPaint.getTextBounds(pair.first, 0, pair.first.length(), textBound);
mTextBounds.add(textBound);
}
//繪制對應(yīng)矩形居中的文字,通過每個矩形region中的left巩割,left + (矩形寬度 - 文字寬度) / 2 作為文字繪制的起點(diǎn)x, y 取文字高度裙顽。因為文字繪制起點(diǎn)很怪異是第一個字的左下角還要向左偏移一點(diǎn)距離。
private void drawTextList(Canvas canvas) {
for (int i = 0; i < mRegionList.size(); i++) {
canvas.drawText(mDataList.get(i).first, mRegionList.get(i).getBounds().left + (mRectWidth / 2 - mTextBounds.get(i).width() / 2), mTextBounds.get(i).height() + 20F, mTextPaint);
}
}
3宣谈、矩形集合的繪制
- 矩形集合繪制比較麻煩愈犹,需要裁剪每個rect的region,以及添加對應(yīng)的path
mGlobalRegion = new Region(-w, -h, w, h);//創(chuàng)建全局的region
mPointList.clear();//重置折線圖中點(diǎn)集合
mRegionList.clear();//重置region集合
for (int i = 0; i < mDataList.size(); i++) {
//根據(jù)每個矩形需要添加一個間隔距離,第一個矩形left就是間隔闻丑,第二個就是第一個矩形的left + 間隔
//反推第N個就是第 N-1 個矩形的left + 間隔漩怎。那么這個left = mGap * (i + 1) + mRectWidth * i
float left = mGap * (i + 1) + mRectWidth * i;
//top就是按比例算,負(fù)數(shù)因為繪制處于Y的負(fù)半軸嗦嗡,mHeight-200是為了留出坐標(biāo)軸頂點(diǎn)距離控件底部距離為200.
float top = -mDataList.get(i).second * (mHeight - 200);
float right = left + mRectWidth;
//-mCoordinatePaint.getStrokeWidth()一個細(xì)微處理為了防止矩形繪制勋锤,會蓋住底部坐標(biāo)軸
float bottom = -mCoordinatePaint.getStrokeWidth();
//創(chuàng)建折線圖中每個點(diǎn),每個點(diǎn)位置也正處于矩形寬度中點(diǎn)位置
Point point = new Point(left + mRectWidth / 2, top);
mPointList.add(point);
//為每個矩形創(chuàng)建一個path
Path path = new Path();
//向每個path中添加一個矩形
path.addRect(left, top, right, bottom, Path.Direction.CW);
//創(chuàng)建一個region
Region region = new Region();
//在全局的mGlobalRegion中裁剪出對應(yīng)path的矩形范圍侥祭,并把相應(yīng)的范圍信息保存在region
region.setPath(path, mGlobalRegion);
//把每個path添加全局的mPath中
mPath.addPath(path);
//保存每個region信息到集合中
mRegionList.add(region);
}
//繪制直方圖
private void drawHistogram(Canvas canvas) {
canvas.drawPath(mPath, mRectPaint);//繪制最后mPath
if (mClickPosition != -1) {//判斷點(diǎn)擊mClickPosition叁执,根據(jù)位置重新繪制點(diǎn)擊色的矩形
mRectPaint.setColor(mPressColor);
canvas.drawRect(mRegionList.get(mClickPosition).getBounds(), mRectPaint);
mClickPosition = -1;//重置ClickPosition
}
}
4茄厘、折線圖的繪制
- 折線圖繪制比較簡單,就是對一組點(diǎn)和一組線段的繪制谈宛,關(guān)鍵就是坐標(biāo)的計算次哈,我們在計算矩形的位置順帶就把點(diǎn)的信息計算好,最后保存在pointList集合吆录,直接拿來用即可亿乳。
//計算點(diǎn)的坐標(biāo),創(chuàng)建折線圖中每個點(diǎn)径筏,每個點(diǎn)位置也正處于矩形寬度中點(diǎn)位置
Point point = new Point(left + mRectWidth / 2, top);
mPointList.add(point);
//繪制折線圖
private void drawPolyline(Canvas canvas) {
for (int i = 0; i < mPointList.size(); i++) {
//繪制點(diǎn)交點(diǎn)
mCoordinatePaint.setStrokeWidth(20f);
canvas.drawPoint(mPointList.get(i).x, mPointList.get(i).y, mCoordinatePaint);
//繪制連線
if (i < mPointList.size() - 1) {
mCoordinatePaint.setStrokeWidth(5f);
canvas.drawLine(mPointList.get(i).x, mPointList.get(i).y, mPointList.get(i + 1).x, mPointList.get(i + 1).y, mCoordinatePaint);
}
}
}
5、點(diǎn)擊交互的實(shí)現(xiàn)
- 它實(shí)現(xiàn)核心在于region中提供一個region.contain(x, y)方法可以判斷傳入點(diǎn)的坐標(biāo)是否落入當(dāng)前的region內(nèi)丽涩,返回true or false
@Override
public boolean onTouchEvent(MotionEvent event) {
float[] pts = new float[2];
pts[0] = event.getX();
pts[1] = event.getY();
mMatrix.mapPoints(pts);//利用Matrix矩陣實(shí)現(xiàn)觸摸坐標(biāo)系向繪制坐標(biāo)系轉(zhuǎn)化
int touchX = (int) pts[0];
int touchY = (int) pts[1];
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
mClickPosition = findTouchPoint(touchX, touchY);
if (mClickPosition != -1) {
invalidate();
Toast.makeText(getContext(), String.format(Locale.US, "當(dāng)前選中: %s 數(shù)據(jù)為: %f", mDataList.get(mClickPosition).first, mDataList.get(mClickPosition).second), Toast.LENGTH_SHORT).show();
}
break;
}
return super.onTouchEvent(event);
}
//根據(jù)觸摸點(diǎn)的坐標(biāo)找到對應(yīng)的position
private int findTouchPoint(int touchX, int touchY) {
int position = -1;
for (int i = 0; i < mRegionList.size(); i++) {
Region region = mRegionList.get(i);
if (region.contains(touchX, touchY)) {//region中提供一個非常不錯的API旭咽,region.contains(x,y),可以判斷傳入點(diǎn)的坐標(biāo)是否落入當(dāng)前的region內(nèi)挑围,返回true or false
position = i;//觸摸點(diǎn)落入對應(yīng)region也就找到對應(yīng)region所在position
return position;
}
}
return position;
}
6、坐標(biāo)轉(zhuǎn)換的坑
- 由于一開始為了繪制方便變換了繪圖坐標(biāo)系恢氯,可是觸摸坐標(biāo)又不能變換,手指觸摸的坐標(biāo)系和畫布坐標(biāo)系不統(tǒng)一鼓寺,就可能引起手指觸摸位置和繪制位置不統(tǒng)一勋拟,只能將觸摸的坐標(biāo)轉(zhuǎn)化成繪圖坐標(biāo)系。這里需要用到Matrix矩陣知識,Matrix最大功能之一就是坐標(biāo)映射妈候,數(shù)值轉(zhuǎn)換敢靡,后期會專門了解Matrix。
canvas.translate(100, mHeight - 100);//平移坐標(biāo)系
// 獲取測量矩陣(逆矩陣) 由于繪制畫布的View坐標(biāo)系被平移了苦银,
// 但是所處的觸摸坐標(biāo)系并沒有改變啸胧,需要利用Matrix矩陣實(shí)現(xiàn)觸摸坐標(biāo)系向繪制坐標(biāo)系轉(zhuǎn)化
if (mMatrix.isIdentity()) {
canvas.getMatrix().invert(mMatrix);
}
mMatrix.mapPoints(pts);//利用Matrix矩陣實(shí)現(xiàn)觸摸坐標(biāo)系向繪制坐標(biāo)系轉(zhuǎn)化
7、最后附上全部源碼
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.MotionEvent;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
public class RectChart extends CanvasView {
private int mNormalColor;
private int mPressColor;
private Paint mRectPaint;//繪制矩形的畫筆
private Paint mTextPaint;//繪制文字的畫筆
private Paint mCoordinatePaint;//繪制坐標(biāo)軸的畫筆
private Matrix mMatrix;//用于坐標(biāo)轉(zhuǎn)換的矩陣Matrix的對象
private Path mPath = new Path();//定義全局所有矩形path集合幔虏,最后所有矩形的Path會加入到mPath中
private Region mGlobalRegion;//定義全局的Region
private List<Rect> mTextBounds = new ArrayList<>();//為了繪制文字的集合纺念,每個文字都用rect框住,便于拿到文字的寬度和高度想括。
private List<Point> mPointList = new ArrayList<>();//為了繪制折線圖中點(diǎn)集合陷谱,每個point對象包含了x,y坐標(biāo)
private List<Region> mRegionList = new ArrayList<>();//為每個矩形集合定義的region集合
private int mWidth;//控件的寬度
private int mHeight;//控件的高度
private float mGap = 40f;//每個矩形之間間隔大小
private float mRectWidth = 80f;//每個矩形寬度大小
private boolean isShowHistogram = true;//是否繪制矩形圖
private boolean isShowPolyline = true;//是否繪制折線圖
private int mClickPosition = -1;//用于記錄刷選出點(diǎn)擊落入對應(yīng)的region的position
private List<Pair<String, Float>> mDataList;//數(shù)據(jù)pair集合,pair對象第一個是用于底部文字繪制的內(nèi)容瑟蜈,第二個是比例對應(yīng)所畫實(shí)際矩形高度烟逊。
public RectChart(Context context, List<Pair<String, Float>> mDataList) {
super(context);
this.mDataList = mDataList;
}
@Override
protected void initDrawTools() {
//初始化矩形畫筆
mRectPaint = new Paint();
mRectPaint.setAntiAlias(true);
mRectPaint.setColor(mNormalColor);
mRectPaint.setStyle(Paint.Style.FILL);
//初始化坐標(biāo)系畫筆
mCoordinatePaint = new Paint();
mCoordinatePaint.setAntiAlias(true);
mCoordinatePaint.setColor(Color.RED);
mCoordinatePaint.setStyle(Paint.Style.STROKE);
mCoordinatePaint.setStrokeWidth(5f);
//初始化文字畫筆
mTextPaint = new Paint();
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(Color.parseColor("#C2185B"));
mTextPaint.setTextSize(40);
if (mDataList == null || mDataList.isEmpty()) {
return;
}
//先取出數(shù)據(jù)中所有的文字測量每個文字尺寸,并把每個文字尺寸信息記錄在對應(yīng)的rect中踪栋,通過paint.getTextBounds(text,start,end,rect),
// 最后把每個文字的rect保存在集合中
for (Pair<String, Float> pair : mDataList) {
Rect textBound = new Rect();
mTextPaint.getTextBounds(pair.first, 0, pair.first.length(), textBound);
mTextBounds.add(textBound);
}
//創(chuàng)建矩陣對象
mMatrix = new Matrix();
}
@Override
protected void fetchDefAttrValues(Context context, AttributeSet attrs, int defStyleAttr) {
//該方法用于接收自定義屬性的值焙格,本例子還沒來得及添加自定義屬性
mNormalColor = Color.parseColor("#ff9900");
mPressColor = Color.parseColor("#ff0000");
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(1080, 1000);//測量這里指定大小尺寸的畫布即控件大小
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
if (mMatrix != null) {
mMatrix.reset();
}
mWidth = w;
mHeight = h;
mGlobalRegion = new Region(-w, -h, w, h);//創(chuàng)建全局的region
mPointList.clear();//重置折線圖中點(diǎn)集合
mRegionList.clear();//重置region集合
for (int i = 0; i < mDataList.size(); i++) {
//根據(jù)每個矩形需要添加一個間隔距離,第一個矩形left就是間隔夷都,第二個就是第一個矩形的left + 間隔
//反推第N個就是第 N-1 個矩形的left + 間隔眷唉。那么這個left = mGap * (i + 1) + mRectWidth * i
float left = mGap * (i + 1) + mRectWidth * i;
//top就是按比例算予颤,負(fù)數(shù)因為繪制處于Y的負(fù)半軸,mHeight-200是為了留出坐標(biāo)軸頂點(diǎn)距離控件底部距離為200.
float top = -mDataList.get(i).second * (mHeight - 200);
float right = left + mRectWidth;
//-mCoordinatePaint.getStrokeWidth()一個細(xì)微處理為了防止矩形繪制冬阳,會蓋住底部坐標(biāo)軸
float bottom = -mCoordinatePaint.getStrokeWidth();
//創(chuàng)建折線圖中每個點(diǎn)蛤虐,每個點(diǎn)位置也正處于矩形寬度中點(diǎn)位置
Point point = new Point(left + mRectWidth / 2, top);
mPointList.add(point);
//為每個矩形創(chuàng)建一個path
Path path = new Path();
//向每個path中添加一個矩形
path.addRect(left, top, right, bottom, Path.Direction.CW);
//創(chuàng)建一個region
Region region = new Region();
//在全局的mGlobalRegion中裁剪出對應(yīng)path的矩形范圍,并把相應(yīng)的范圍信息保存在region
region.setPath(path, mGlobalRegion);
//把每個path添加全局的mPath中
mPath.addPath(path);
//保存每個region信息到集合中
mRegionList.add(region);
}
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
initDrawTools();//初始化繪制工具
initCoordinateCanvas(canvas);//初始化畫布坐標(biāo)軸
drawTextList(canvas);//繪制文字集合
if (isShowHistogram) {//繪制直方圖
drawHistogram(canvas);
}
if (isShowPolyline) {//繪制折線圖
drawPolyline(canvas);
}
}
@Override
public boolean onTouchEvent(MotionEvent event) {
float[] pts = new float[2];
pts[0] = event.getX();
pts[1] = event.getY();
mMatrix.mapPoints(pts);//利用Matrix矩陣實(shí)現(xiàn)觸摸坐標(biāo)系向繪制坐標(biāo)系轉(zhuǎn)化
int touchX = (int) pts[0];
int touchY = (int) pts[1];
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
mClickPosition = findTouchPoint(touchX, touchY);
if (mClickPosition != -1) {
invalidate();
Toast.makeText(getContext(), String.format(Locale.US, "當(dāng)前選中: %s 數(shù)據(jù)為: %f", mDataList.get(mClickPosition).first, mDataList.get(mClickPosition).second), Toast.LENGTH_SHORT).show();
}
break;
}
return super.onTouchEvent(event);
}
//根據(jù)觸摸點(diǎn)的坐標(biāo)找到對應(yīng)的position
private int findTouchPoint(int touchX, int touchY) {
int position = -1;
for (int i = 0; i < mRegionList.size(); i++) {
Region region = mRegionList.get(i);
if (region.contains(touchX, touchY)) {//region中提供一個非常不錯的API肝陪,region.contains(x,y),可以判斷傳入點(diǎn)的坐標(biāo)是否落入當(dāng)前的region內(nèi)驳庭,返回true or false
position = i;//觸摸點(diǎn)落入對應(yīng)region也就找到對應(yīng)region所在position
return position;
}
}
return position;
}
private void drawTextList(Canvas canvas) {
for (int i = 0; i < mRegionList.size(); i++) {
canvas.drawText(mDataList.get(i).first, mRegionList.get(i).getBounds().left + (mRectWidth / 2 - mTextBounds.get(i).width() / 2), mTextBounds.get(i).height() + 20F, mTextPaint);
}
}
//初始化坐標(biāo)系畫布
private void initCoordinateCanvas(Canvas canvas) {
canvas.drawColor(Color.parseColor("#eeeeee"));
canvas.translate(100, mHeight - 100);//平移坐標(biāo)系
// 獲取測量矩陣(逆矩陣) 由于繪制畫布的View坐標(biāo)系被平移了,
// 但是所處的觸摸坐標(biāo)系并沒有改變氯窍,需要利用Matrix矩陣實(shí)現(xiàn)觸摸坐標(biāo)系向繪制坐標(biāo)系轉(zhuǎn)化
if (mMatrix.isIdentity()) {
canvas.getMatrix().invert(mMatrix);
}
float[] opts = {0, 0, mWidth - 200, 0, 0, 0, 0, -(mHeight - 200)};
canvas.drawLines(opts, mCoordinatePaint);//繪制兩條線
mCoordinatePaint.setStrokeCap(Paint.Cap.ROUND);
mCoordinatePaint.setStrokeWidth(20f);
canvas.drawPoint(0, 0, mCoordinatePaint);
}
//繪制直方圖
private void drawHistogram(Canvas canvas) {
canvas.drawPath(mPath, mRectPaint);//繪制最后mPath
if (mClickPosition != -1) {//判斷點(diǎn)擊mClickPosition饲常,根據(jù)位置重新繪制點(diǎn)擊色的矩形
mRectPaint.setColor(mPressColor);
canvas.drawRect(mRegionList.get(mClickPosition).getBounds(), mRectPaint);
mClickPosition = -1;//重置ClickPosition
}
}
//繪制折線圖
private void drawPolyline(Canvas canvas) {
for (int i = 0; i < mPointList.size(); i++) {
//繪制點(diǎn)交點(diǎn)
mCoordinatePaint.setStrokeWidth(20f);
canvas.drawPoint(mPointList.get(i).x, mPointList.get(i).y, mCoordinatePaint);
//繪制連線
if (i < mPointList.size() - 1) {
mCoordinatePaint.setStrokeWidth(5f);
canvas.drawLine(mPointList.get(i).x, mPointList.get(i).y, mPointList.get(i + 1).x, mPointList.get(i + 1).y, mCoordinatePaint);
}
}
}
class Point {
private float x;
private float y;
public Point(float x, float y) {
this.x = x;
this.y = y;
}
}
}
結(jié)束
這個例子就算是講完,下篇博客咱們一起講下Path相關(guān)的內(nèi)容狼讨。一下子水了這么多贝淤,好渴喝水去了。對于還不是很不知道知識政供,可以先記住播聪。