I have used the following code to draw text,
public void drawText(Canvas canvas, int _x, int _y, float scale, float rotate) {
if (TextUtils.isEmpty(mText)) {
return;
}
int x = _x;
int y = _y;
mPaint.getTextBounds(mText, 0, mText.length(), mTextRect);
mTextRect.offset(x - (mTextRect.width() >> 1), y);
mHelpBoxRect.set(mTextRect.left - PADDING, mTextRect.top - PADDING
, mTextRect.right + PADDING, mTextRect.bottom + PADDING);
RectUtil.scaleRect(mHelpBoxRect, scale);
canvas.save();
canvas.scale(scale, scale, mHelpBoxRect.centerX(), mHelpBoxRect.centerY());
canvas.rotate(rotate, mHelpBoxRect.centerX(), mHelpBoxRect.centerY());
canvas.drawText(mText, x, y, mPaint);
canvas.restore();
}
Following is scaleRect method,
public static void scaleRect(RectF rect, float scale) {
float w = rect.width();
float h = rect.height();
float newW = scale * w;
float newH = scale * h;
float dx = (newW - w) / 2;
float dy = (newH - h) / 2;
rect.left -= dx;
rect.top -= dy;
rect.right += dx;
rect.bottom += dy;
}
The issue is that, the text is not wrapping in case if it is of multiline. How will I be able to let the text wrap in case of multi line text?
Related
#Override
public void onDraw(Canvas canvas) {
/*canvas.drawLine(0, 0, 20, 20, paint);
canvas.drawLine(200, 0, 0, 200, paint);*/
/*canvas.drawLine(downxpos, downypos, upxpos, upypos, paint);*/
for (Line l : lines) {
canvas.drawLine(l.startX, l.startY, l.stopX, l.stopY, paint);
}
}
example image
I Would like to draw the line like the image I show in canvas. I can draw the line but don't know how to add arrows to it.
Use these Methods to draw Arrow on both sides.
private void drawArrow1(Canvas canvas, Paint paint) {
double degree = calculateDegree(x, x1, y, y1);
float endX1 = (float) (x1 + ((10) * Math.cos(Math.toRadians((degree-30)+90))));
float endY1 = (float) (y1 + ((10) * Math.sin(Math.toRadians(((degree-30)+90)))));
float endX2 = (float) (x1 + ((10) * Math.cos(Math.toRadians((degree-60)+180))));
float endY2 = (float) (y1 + ((10) * Math.sin(Math.toRadians(((degree-60)+180)))));
canvas.drawLine(x1,y1,endX1,endY1,paint);
canvas.drawLine(x1, y1, endX2,endY2,paint);
}
private void drawArrow(Canvas canvas, Paint paint) {
double degree1 = calculateDegree(x1, x, y1, y);
float endX11 = (float) (x + ((10) * Math.cos(Math.toRadians((degree1-30)+90))));
float endY11 = (float) (y + ((10) * Math.sin(Math.toRadians(((degree1-30)+90)))));
float endX22 = (float) (x + ((10) * Math.cos(Math.toRadians((degree1-60)+180))));
float endY22 = (float) (y + ((10) * Math.sin(Math.toRadians(((degree1-60)+180)))));
canvas.drawLine(x,y,endX11,endY11,paint);
canvas.drawLine(x,y,endX22,endY22,paint);
}
public double calculateDegree(float x1, float x2, float y1, float y2) {
float startRadians = (float) Math.atan((y2 - y1) / (x2 - x1));
System.out.println("radian=====" + Math.toDegrees(startRadians));
startRadians += ((x2 >= x1) ? 90 : -90) * Math.PI / 180;
return Math.toDegrees(startRadians);
}
Where x,y is starting point and x1,y1 is ending point.
Hi i am creating indicator for doughnut chart but it is covering only three side. Here i added onDraw method.The selected chart index arc should be highlighted with indicator.The indicator should be cover all the four sides.
Code:
#Override
public void draw(Canvas canvas, int x, int y, int width, int height, Paint paint) {
paint.setAntiAlias(true);
paint.setStyle(Style.FILL);
int legendSize = getLegendSize(mRenderer, height / 5, 0);
int left = x;
int top = y;
int right = x + width;
int sLength = mDataset.getItemCount();
double total = 0;
String[] titles = new String[sLength];
for (int i = 0; i < sLength; i++) {
total += mDataset.getValue(i);
titles[i] = mDataset.getCategory(i);
}
if (mRenderer.isFitLegend()) {
legendSize = drawLegend(canvas, mRenderer, titles, left, right, y, width, height, legendSize, paint, true);
}
int bottom = y + height - legendSize;
drawBackground(mRenderer, canvas, x, y, width, height, paint, false, Renderer.NO_COLOR);
float currentAngle = mRenderer.getStartAngle();
float labelCurrentAngle = mRenderer.getStartAngle();
// int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));
// int radius = (int) (500 * 0.35) + 50;
//Log.i("radius++", "" + radius);
int mRadius = Math.min(Math.abs(right - left), Math.abs(bottom - top));
double rCoef = 0.35 * mRenderer.getScale();
double decCoef = 0.2 / sLength;
int radius = (int) (mRadius * rCoef);
if (mCenterX == 0) {
mCenterX = (left + right) / 2;
}
if (mCenterY == 0) {
mCenterY = (bottom + top) / 2;
}
// Hook in clip detection after center has been calculated
mPieMap.setDimensions(radius, mCenterX, mCenterY);
boolean loadPieCfg = !mPieMap.areAllSegmentPresent(sLength);
if (loadPieCfg) {
mPieMap.clearPieSegments();
}
float shortRadius = radius * 0.9f;
float longRadius = radius * 1.1f;
RectF oval = new RectF(mCenterX - radius, mCenterY - radius, mCenterX + radius, mCenterY + radius);
for (int i = 0; i < sLength; i++) {
float value = (float) mDataset.getValue(i);
float angle = (float) (value / total * 360);
int color = mRenderer.getRenderers().get(i).getColor();
if (mRenderer.getRenderers().get(i).isClicked()) {
ClickedArc.CANVAS = canvas;
ClickedArc.CURRENT_ANGLE = currentAngle;
ClickedArc.ANGLE = angle;
ClickedArc.COLOR = color;
ClickedArc.INDEX = mRenderer.getRenderers().get(i).getDataIndex();
} else {
Paint paint3 = new Paint(Paint.ANTI_ALIAS_FLAG);
paint3.setStrokeCap(Paint.Cap.ROUND);
paint3.setStyle(Style.FILL);
int[] colors = {color, color};
RadialGradient gradient3 = new RadialGradient(mCenterX, mCenterY, radius, colors, null, android.graphics.Shader.TileMode.CLAMP);
paint3.setShader(gradient3);
paint3.setAntiAlias(true);
canvas.drawArc(oval, currentAngle, angle, true, paint3);
}
try {
if (mRenderer.getRenderers().get(ClickedArc.INDEX).isClicked()) {
Paint paint3 = new Paint(Paint.ANTI_ALIAS_FLAG);
paint3.setStyle(Style.FILL);
paint3.setColor(Color.WHITE);
Paint shadow = new Paint(Paint.ANTI_ALIAS_FLAG);
int[] colors = {Color.BLACK, Color.BLACK};
RadialGradient gradient3 = new RadialGradient(mCenterX, mCenterY, radius, colors, null, android.graphics.Shader.TileMode.CLAMP);
shadow.setShader(gradient3);
shadow.setAntiAlias(true);
shadow.setColor(Color.BLACK);
shadow.setStrokeWidth(8);
shadow.setDither(true);
shadow.setStyle(Paint.Style.STROKE);
shadow.setStrokeCap(Paint.Cap.BUTT);
shadow.setAntiAlias(true);
int shadowRadius = radius + 2;
RectF shadowOval = new RectF(mCenterX - shadowRadius, mCenterY - shadowRadius, mCenterX + shadowRadius, mCenterY + shadowRadius);
canvas.drawArc(shadowOval, ClickedArc.CURRENT_ANGLE - 1, ClickedArc.ANGLE + 2, true, shadow);
canvas.drawArc(oval, ClickedArc.CURRENT_ANGLE, ClickedArc.ANGLE, true, paint3);
}
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
}
if (loadPieCfg) {
mRenderer.getRenderers().get(i).setDataIndex(i);
mPieMap.addPieSegment(i, value, currentAngle, angle + currentAngle);
}
currentAngle += angle;
}
radius -= (int) mRadius * decCoef;
shortRadius -= mRadius * decCoef - 2;
List<RectF> prevLabelsBounds = new ArrayList<RectF>();
for (int i = 0; i < sLength; i++) {
float value = (float) mDataset.getValue(i);
float angle = (float) (value / total * 360);
drawLabel(canvas, mDataset.getCategory(i), mRenderer, prevLabelsBounds, mCenterX, mCenterY, shortRadius / 2 + 50, longRadius / 2 + 50,
labelCurrentAngle, angle, left, right, mRenderer.getLabelsColor(), paint, true, mRenderer.getRenderers().get(i));
Point sPoint = mRenderer.getRenderers().get(i).getCenterPoint();
Point ePoint = new Point((int) mRenderer.getRenderers().get(i).getTextWidth(), (int) mRenderer.getRenderers().get(i).getTextHeight());
mPieMap.addLabelSegment(i, value, sPoint, ePoint);
labelCurrentAngle += angle;
}
prevLabelsBounds.clear();
}
I am able to plot bar graph using canvas and drawing rectangle in the view. But the onTouch interaction works for the whole view and hence I am not able to interact with each bar separately.I am not looking for using any library for plotting graphs. Any suggestions would be helpful. Thanks!
protected void onDraw(Canvas canvas) {
float border = 20;
float horstart = border * 2;
float height = getHeight();
float width = getWidth() - 1;
float max = getMax();
float min = getMin();
float diff = max - min;
float graphheight = height - (2 * border);
float graphwidth = width - (2 * border);
paint.setTextAlign(Align.LEFT);
int vers = verlabels.length - 1;
for (int i = 0; i < verlabels.length; i++) {
paint.setColor(Color.BLUE);
float y = ((graphheight / vers) * i) + border;
//canvas.drawLine(horstart, y, width, y, paint);
paint.setColor(Color.BLUE);
canvas.drawText(verlabels[i], 0, y, paint);
}
int hors = horlabels.length - 1;
for (int i = 0; i < horlabels.length; i++) {
paint.setColor(Color.BLUE);
float x = ((graphwidth / hors) * i) + horstart;
//canvas.drawLine(x, height - border, x, border, paint);
paint.setTextAlign(Align.CENTER);
if (i == horlabels.length - 1)
paint.setTextAlign(Align.RIGHT);
if (i == 0)
paint.setTextAlign(Align.LEFT);
paint.setColor(Color.BLUE);
canvas.drawText(horlabels[i], x, height - 4, paint);
}
paint.setTextAlign(Align.CENTER);
canvas.drawText(title, (graphwidth / 2) + horstart, border - 4, paint);
if (max != min) {
paint.setColor(Color.BLUE);
if (type == BAR) {
float datalength = values.length;
float colwidth = (graphwidth / hors);
for (int i = 0; i < values.length; i++) {
float val = values[i] - min;
float rat = val / diff;
float h = graphheight * rat;
canvas.drawRect((i * colwidth) + horstart, (border - h)
+ graphheight+curY, ((i * colwidth) + horstart)
+ (colwidth - 1), height - (border - 1), paint);
}
} else {
float datalength = values.length;
float colwidth = (width - (2 * border)) / datalength;
float halfcol = colwidth / 2;
float lasth = 0;
float h = 0;
for (int i = 0;i<values.length;i++)
canvas.drawLine(((i - 1) * colwidth) + (horstart + 1)
+ halfcol, (border - lasth) + graphheight+curY,
(i * colwidth) + (horstart + 1) + halfcol,
(border - h) + graphheight, paint);
lasth = h;
}
}
}
onTouch method for the view :
public boolean onTouch(View v, MotionEvent event)
{
boolean result=false;
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
curX= (int)event.getX();
curY= (int)event.getY();
result=true;
break;
case MotionEvent.ACTION_MOVE:
curX= (int)event.getX();
curY= (int)event.getY();
result=true;
break;
case MotionEvent.ACTION_UP:
curX= (int)event.getX();
curY= (int)event.getY();
result=true;
break;
}
if (result) invalidate();
return result;
}
Whenever an user touches that view, it causes the onTouch method gets called. Once it's getting called, you're given two float numbers: x and y indicating where user's finger touches your view relative to the view coordination system.
As you might grasped the idea, you should get those numbers and internally in your custom view (i.e. bar chart) calculate which bar is affected. Then, you can for example apply a hover effect or do something else.
Note: For updating appearance of your view, you should store changes in data models of your chart view and then issue invalidate(). Subsequently, as a result, your onDraw is invoked and in which you can re-draw your chart. (i.e. You should each time, re-draw your whole chart again)
I am using MapViewCompassDemo sample from
\add-ons\addon-google_apis-google_inc_-7\samples\MapsDemo\
for rotating map view based on user direction.This is working
perfectly if the map is without overlays.But if i add overlays to map the ontap not working exactly
on marker while rotating.can any one help me regarding this.
in this sample it only rotate dispatchDraw method only.Along with dispatchDraw rotate
dispatchTouchEvent also.find below code to rotate toouch events also
#Override
public void dispatchDraw(Canvas canvas) {
canvas.save();
canvas.rotate(getRotation(), getWidth() / 2, getHeight() / 2);
super.dispatchDraw(canvas);
canvas.restore();
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
float[] coords = new float[] {
event.getX(), event.getY()
};
adjustCoords(coords, getRotation());
MotionEvent evt = MotionEvent.obtain(event.getDownTime(), event.getEventTime(), event
.getAction(), coords[0], coords[1], event.getPressure(), event.getSize(), event
.getMetaState(), event.getXPrecision(), event.getYPrecision(), event.getDeviceId(),
event.getEdgeFlags());
return super.dispatchTouchEvent(evt);
}
protected void adjustCoords(float[] coords, float deg) {
float x = coords[0];
float y = coords[1];
int centerX = getWidth() / 2;
int centerY = getHeight() / 2;
// convert to radians
float rad = (float) ((deg * Math.PI) / 180F);
float s = (float) Math.sin(rad);
float c = (float) Math.cos(rad);
// translate point back to origin:
x -= centerX;
y -= centerY;
// apply rotation
float tmpX = x * c - y * s;
float tmpY = x * s + y * c;
x = tmpX;
y = tmpY;
// translate point back:
x += centerX;
y += centerY;
coords[0] = x;
coords[1] = y;
}
See this below link
http://evancharlton.com/thoughts/android-rotating-touch-events/
i want to custom view,it can include some effect:first draw a pic on the view as a background then draw a rectangle on the image,and draw other image named A in the rectangle, we know the rectangle have four fixed point,when i drag one of these,the rectangle can scale,at the same time A also is scale, i have read more link,but not find good example,i have done something,but cannot finish the scale rectangle,my code is:
public class DrawView extends View implements OnTouchListener {
private static final String TAG = "DrawView";
private static final int LineLength = 30;
Paint paint = new Paint();
float locationX, locationY;
private int mLastTouchX;
private int mLastTouchY;
private int mPosX;
private int mPosY;
private int mPosX1;
private int mPosY1;
Bitmap bitmap, bmp, xiao;
int screenWidth, screenHeight;
int xLength;
boolean isFirst = true;
boolean isLeft = false;
Rect r, rBig,outRect;
public DrawView(Context context) {
super(context);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener(this);
WindowManager wm = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
screenHeight = wm.getDefaultDisplay().getHeight();
screenWidth = wm.getDefaultDisplay().getWidth();
mPosX = screenWidth / 2;
mPosY = screenHeight / 2;
paint.setColor(Color.RED);
paint.setAntiAlias(true);
bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.meinv);
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
xiao = BitmapFactory.decodeResource(getResources(),
R.drawable.msn_protocol);
xLength = (int) Math.hypot(xiao.getWidth(), xiao.getHeight());
r = new Rect();
r.set((int) mPosX - LineLength - xiao.getWidth(), (int) mPosY
- LineLength - xiao.getHeight(), (int) mPosX - LineLength,
(int) mPosY - LineLength);
// Log.i("r", r.left + " " + r.top + " " + r.right + " " + r.bottom);
rBig = new Rect();
rBig.set((int) mPosX - LineLength, (int) mPosY - LineLength,
(int) mPosX + LineLength, (int) mPosY + LineLength);
//Log.i("r", rBig.left + " " + rBig.top + " " + rBig.right + " " + rBig.bottom);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawBitmap(bitmap, 0, 0, null);
canvas.drawBitmap(xiao, mPosX - LineLength - xiao.getWidth(), mPosY
- LineLength - xiao.getHeight(), null);
canvas.drawLine(mPosX - LineLength,
mPosY - LineLength - xiao.getHeight() / 2, mPosX + LineLength,
mPosY - LineLength - xiao.getHeight() / 2, paint);
canvas.drawLine(mPosX - LineLength - xiao.getWidth() / 2, mPosY
- LineLength, mPosX - LineLength - xiao.getWidth() / 2, mPosY
+ LineLength, paint);
canvas.drawBitmap(xiao, mPosX + LineLength,
mPosY - LineLength - xiao.getHeight(), null);
canvas.drawBitmap(xiao, mPosX - LineLength - xiao.getWidth(), mPosY
+ LineLength, null);
canvas.drawBitmap(xiao, mPosX + LineLength, mPosY + LineLength, null);
canvas.drawLine(mPosX + LineLength + xiao.getWidth() / 2, mPosY
- LineLength, mPosX + LineLength + xiao.getWidth() / 2, mPosY
+ LineLength, paint);
canvas.drawLine(mPosX - LineLength,
mPosY + LineLength + xiao.getHeight() / 2, mPosX + LineLength,
mPosY + LineLength + xiao.getHeight() / 2, paint);
if (isLeft) {
Matrix matrix = new Matrix();
matrix.preScale(0.8f, 0.8f);
Bitmap rotatedBitmap = Bitmap.createBitmap(bmp, 0, 0,
bmp.getWidth(), bmp.getHeight(), matrix, true);
canvas.drawBitmap(rotatedBitmap, mPosX - LineLength, mPosY
- LineLength, null);
}
}
public boolean onTouch(View view, MotionEvent event) {
isFirst = false;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN: {
mPosX1 = (int) event.getX();
mPosY1 = (int) event.getY();
mLastTouchX = mPosX1;
mLastTouchY = mPosX1;
// Log.i("r", r.left + " " + r.top + " " + r.right + " " + r.bottom);
Log.i("ACTION_DOWN", "" + mPosX1 + " " + mPosY1);
if (r.contains(mPosX1, mPosY1)) {
isLeft = true;
invalidate();
}
break;
}
case MotionEvent.ACTION_MOVE: {
int x = (int) event.getX();
int y = (int) event.getY();
Log.i("aa",""+x+""+y);
int dx = x - mLastTouchX;
int dy = y - mLastTouchY;
mLastTouchX = x;
mLastTouchY = y;
mPosX += dx;
mPosY += dy;
r.set((int) mPosX - LineLength - xiao.getWidth(), (int) mPosY
- LineLength - xiao.getHeight(), (int) mPosX - LineLength,
(int) mPosY - LineLength);
rBig.set((int) mPosX - LineLength, (int) mPosY - LineLength,
(int) mPosX + LineLength, (int) mPosY + LineLength);
// Log.i("r", rBig.left + " " + rBig.top + " " + rBig.right + " " + rBig.bottom);
invalidate();
break;
}
case MotionEvent.ACTION_UP: {
break;
}
case MotionEvent.ACTION_CANCEL: {
break;
}
}
return true;
}
}
the pic as :http://i.stack.imgur.com/wxi35.png,the effect have finished by system gallery,but i debug the source ,i failed, as my other question: Imitate crop function of system Gallery
and https://stackoverflow.com/questions/6724218/i-cannot-find-the-initial-value-in-gallery-the-source
I dont know about drawing the Rectangle but, this is how I moved the image
MainPinchView.java
public class MainPinchView extends Activity {
int menuid = 0;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
MainPinchImageView obj = new MainPinchImageView(this);
Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.my);
obj.setImage(bmp, 100, 100);
setContentView(obj);
}
}
MainPinchImageView.java
public class MainPinchImageView extends ImageView {
private static final String TAG = "Touch";
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
int flag = 0;
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
// Remember some things for zooming
PointF start = new PointF();
PointF mid = new PointF();
float oldDist = 1f;
Context context;
public MainPinchImageView(Context context) {
super(context);
super.setClickable(true);
this.context = context;
matrix.setTranslate(1f, 1f);
setImageMatrix(matrix); // sets the default matrix
setScaleType(ScaleType.MATRIX); //Controls how the image should be resized or moved to match the size of this ImageView.
setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix); //
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG");
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
// ...
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x, event.getY()- start.y);
}
break;
}
setImageMatrix(matrix);
return true; // indicate event was handled
}
});
}
public void setImage(Bitmap bm, int displayWidth, int displayHeight) {
super.setImageBitmap(bm);
int displayheight = (getResources().getDisplayMetrics().heightPixels)/2;
int displaywidth = (getResources().getDisplayMetrics().widthPixels)/2;
int imgw = displayWidth/2;
int imgh = displayHeight/2;
// Fit to screen.
float scale;
if ((displayHeight / bm.getHeight()) >= (displayWidth / bm.getWidth())) {
scale = (float) displayWidth / (float) bm.getWidth();
} else {
scale = (float) displayHeight / (float) bm.getHeight();
}
savedMatrix.set(matrix);
matrix.set(savedMatrix);
matrix.postScale(scale, scale, mid.x, mid.y);
setImageMatrix(matrix);
savedMatrix.set(matrix);
matrix.set(savedMatrix);
matrix.postTranslate(displaywidth - imgw, displayheight - imgh);
setImageMatrix(matrix);
}
}