I have created custom widget which inherits View.
<com.test.www.view.ElementView
android:id="#+id/surface1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_weight="1"
/
>
and
public class ElementView extends View {
private final int width=100;
private final int height=100;
private Paint paint=null;
private Canvas canvas=null;
public ElementView(Context context) {
super(context);
paint = new Paint();
}
public ElementView(Context context, AttributeSet attr) {
super(context, attr);
paint = new Paint();
}
public ElementView(Context context, AttributeSet attr, int defaultStyles) {
super(context, attr, defaultStyles);
paint = new Paint();
}
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
int measuredWidth = MeasureSpec.getSize(widthSpec);
int measuredHeight = MeasureSpec.getSize(heightSpec);
setMeasuredDimension(this.width,this.height);
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas=canvas;
// get the size of your control based on last call to onMeasure
int height = getMeasuredHeight();
int width = getMeasuredWidth();
// Now create a paint brush to draw your widget
paint.setColor(Color.GREEN);
//define border
this.canvas.drawLine(0, 0, 0, 99, paint);
this.canvas.drawLine(0, 0, 99,0, paint);
this.canvas.drawLine(99, 0, 99, 99, paint);
this.canvas.drawLine(0, 99, 99,99, paint);
//define cells
this.canvas.drawLine(0,50,99,50,paint);
this.canvas.drawLine(30,0,30,50,paint);
//draw green rectangle
this.canvas.drawRect(new Rect(0,0,50,50),paint);
//draw some text
paint.setTextSize(8);
paint.setColor(Color.RED);
String displayText = "test";
Float textWidth = paint.measureText(displayText);
int px = width / 2;
int py = height / 2;
this.canvas.drawText(displayText, px - textWidth / 2, py, paint);
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
paint.setColor(Color.RED);
//change color of first cell
canvas.drawRect(new Rect(0,0,50,50),paint);
return super.dispatchTouchEvent(event);
}
}
Problem is that this ElementView doesn't react on click. I have override of dispatch event but it doesn't come in. Can anybody help me ? What to do to make this ElementView react on click ?
I would probably do something like this:
ElementView ev = (ElementView)findViewById(R.id.surface1);
ev.setOnClickListener(evOnClick);
public OnClickListener evOnClick = new OnClickListener() {
#Override
public void onClick(View v, int arg1) {
//DO ONCLICK STUFF
}
};
I'm not sure if you can actually put the onClick inside the view definition like you are trying to, but Id like if someone could show me how.
Related
I wanted to show map inside a circle view where circle's outside area filled with a color. I referred a post Draw transparent circle filled outside. But now the problem is touch events. Map can be touched through outside circle view while I need map can be touched (zoom or move) only form inside Circle view (where the map is visible).
What I tried,
setEnabled=false
clickable=false
but still map is touched from outside circle view.
Is that possible to achieve that map can be touched from inside circle view.
public class RadiusOverlayView extends LinearLayout {
private Bitmap windowFrame;
public RadiusOverlayView(Context context) {
super(context);
}
public RadiusOverlayView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RadiusOverlayView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
#Override
protected void dispatchDraw(Canvas canvas) {
super.dispatchDraw(canvas);
if (windowFrame == null) {
createWindowFrame(); // Lazy creation of the window frame, this is needed as we don't know the width & height of the screen until draw time
}
canvas.drawBitmap(windowFrame, 0, 0, null);
}
#Override
public boolean isEnabled() {
return false;
}
#Override
public boolean isClickable() {
return false;
}
protected void createWindowFrame() {
windowFrame = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888); // Create a new image we will draw over the map
Canvas osCanvas = new Canvas(windowFrame); // Create a canvas to draw onto the new image
RectF outerRectangle = new RectF(0, 0, getWidth(), getHeight());
Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG); // Anti alias allows for smooth corners
paint.setColor(Color.CYAN); // This is the color of your activity background
osCanvas.drawRect(outerRectangle, paint);
//paint.setColor(Color.TRANSPARENT); // An obvious color to help debugging
paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)); // A out B http://en.wikipedia.org/wiki/File:Alpha_compositing.svg
float centerX = getWidth() / 2;
float centerY = getHeight() / 2;
float radius = Math.min(getWidth(), getHeight()) / 2 - 50;
osCanvas.drawCircle(centerX, centerY, radius, paint);
}
#Override
public boolean isInEditMode() {
return true;
}
#Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
windowFrame = null; // If the layout changes null our frame so it can be recreated with the new width and height
}
}
XML layout
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!--loading map in container-->
<FrameLayout
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<mypackage.RadiusOverlayView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
/>
</RelativeLayout>
Result:
Any help will be appreciated.
You could set a View.OnTouchListener to your RadiusOverlayView and calculate whether the RadiusOverlayView needs to manage the touch events or not.
In this example I calculate this by testing if the RadiusOverlayView color touched is != 0 (maybe you want to improve this):
final RadiusOverlayView radiusOverlayView = (RadiusOverlayView) findViewById(R.id.radiusView);
radiusOverlayView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(final View view, final MotionEvent motionEvent) {
view.setDrawingCacheEnabled(true);
Bitmap bmp = Bitmap.createBitmap(view.getDrawingCache());
view.setDrawingCacheEnabled(false);
return bmp.getPixel((int) motionEvent.getX(), (int) motionEvent.getY()) != 0;
}
});
I'm trying to display Text in RectShape which uses ShapeDrawable to display in Canvas.
I'm able to display RectShape in this code, but looking for how to display the String on that!
public class CustomDrawableView extends View {
private ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
or
public class ShapeDrawableTest extends View {
ShapeDrawable shapes = new ShapeDrawable();
public ShapeDrawableTest(Context context) {
super(context);
}
public ShapeDrawableTest(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
shapes.draw(canvas);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX(); // Use getX(int) for multi-finger
// gestures
int y = (int) event.getY();
makeShapeDrawable(x, y);
invalidate();
return (true); // Handled touch event
} else {
return (false); // Did not handle touch event
}
}
private void makeShapeDrawable(int x, int y) {
int maxWidth = getWidth() / 10;
int maxHeight = getHeight() / 10;
Shape shape;
shape = new RectShape();
shapes = new ShapeDrawable(shape);
int width = RandomUtils.randomInt(maxWidth) + 5;
int height = RandomUtils.randomInt(maxHeight) + 5;
shapes.setBounds(x - width / 2, y - height / 2, x + width / 2, y
+ height / 2);
shapes.getPaint().setColor(Color.BLUE);
}
}
What I tried is:
public class CustomDrawableView extends View {
public ShapeDrawable mDrawable;
public CustomDrawableView(Context context) {
super(context);
}
public CustomDrawableView(Context context, AttributeSet attrs) {
super(context, attrs);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
//mDrawable.getPaint().setColor(0xff74AC23);
final String s = "Hello";
Paint p = new Paint();
Rect bounds = new Rect();
bounds.set(x, y, x + width, y + height);
p.setTextSize(20);
p.setColor(Color.YELLOW);
p.getTextBounds(s, 0, s.length(), bounds);
mDrawable.getPaint().getTextBounds(s, 0, s.length(), bounds);
mDrawable.setBounds(x, y, x + width, y + height);
}
// public CustomDrawableView(Context context, AttributeSet attrs, int defStyle) {
// super(context, attrs, defStyle);
//
// }
public void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
Screenshot:
The best option for me is to create a custom TextDrawable that handles properly how to display a piece of text. Then in your CustomDrawableView in your onDraw(Canvas c) method you can call it to display the text and the oval.
Take a look at this answer I wrote recently as it contains how to do it properly.
I'm trying to draw text in a custom view that has an image as a background. Three things are being drawn.
The bitmap behind the circle
The red circle and
Text over it.
At the moment the circle and bitmap draw perfectly but the text doesn't display.
Code for custom view.
public class NotificationButtonView extends Button
{
private int mNumberOfNotifications = 0;
private Paint mNotificationPaint = new Paint();
private Paint mTextPaint = new Paint();
public NotificationButtonView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public NotificationButtonView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public NotificationButtonView(Context context) {
super(context);
}
public void setNotificationNumber(int number)
{
this.mNumberOfNotifications = number;
this.invalidate();
}
public void addNotification()
{
this.mNumberOfNotifications++;
this.invalidate();
}
#Override
protected void onAttachedToWindow()
{
super.onAttachedToWindow();
mNotificationPaint.setColor(Color.rgb(255,69,0));
mNotificationPaint.setAlpha(220);
mTextPaint.setAntiAlias(true);
mTextPaint.setColor(Color.BLACK);
mTextPaint.setStyle(Style.FILL);
mTextPaint.setTextSize(this.getWidth() / 3);
mTextPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
mTextPaint.setTextAlign(Align.CENTER);
mTextPaint.setLinearText(true);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
int diameter = this.getWidth() / 3;
/*
canvas.drawCircle(
this.getWidth() - diameter,
this.getHeight() - diameter,
diameter,
this.mNotificationPaint
);
*/
//Get the text bounds.
Rect foundBounds = new Rect();
mTextPaint.getTextBounds("1", 0, "1".length(), foundBounds);
foundBounds.offset(0, diameter);
canvas.drawText(
//String.valueOf(mNumberOfNotifications),
"1",
0,
foundBounds.bottom,
this.mTextPaint
);
//For testing the location of the text bounds.
canvas.drawRect(foundBounds, mNotificationPaint);
}
}
You are getting this.getWidth() 0 in onAttachedToWindow() as a result the text size is set to 0.
But you are getting this.getWidth() value in onDraw so in onDraw add this line
mTextPaint.setTextSize(this.getWidth() / 3);
is it possible to change the color of the underline from a EditText dynamically?
Like the effect, when i focus it, then it turns into blue.
Hope you understand what i want to do.
Create your own customized EditText control.
Here's an example that I made just for you:
When selected, you just have to change mPaint.setColor(Color.GREEN); to another color
public class CustomEditText extends EditText {
private Rect mRect;
private Paint mPaint;
int widthMsSize;
int heightMsSize;
// we need this constructor for LayoutInflater
public CustomEditText(Context context, AttributeSet attrs) {
super(context, attrs);
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setStrokeWidth(5);
mPaint.setColor(Color.GREEN);
System.out.println("constructor");
}
protected void onMeasure(final int widthMeasureSpec,
final int heightMeasureSpec) {
// Extract the Ms (MesaureSpec) parameters
widthMsSize = MeasureSpec.getSize(widthMeasureSpec);
heightMsSize = MeasureSpec.getSize(heightMeasureSpec);
System.out.println("on measure");
// Satisfy contract by calling setMeasuredDimension
setMeasuredDimension(widthMsSize,
heightMsSize);
}
protected void onDraw(Canvas canvas) {
canvas.drawLine(5, heightMsSize - 10, widthMsSize - 5, heightMsSize - 10, mPaint); //draw underline
canvas.drawLine(8, heightMsSize - 10, 8, heightMsSize - 20, mPaint); //draw left corner
canvas.drawLine(widthMsSize - 8, heightMsSize - 10, widthMsSize - 8, heightMsSize - 20, mPaint); //draw right corner
super.onDraw(canvas);
}
}
main.xml
<LinearLayout 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:orientation="vertical" >
<com.example.testanimationfadeinfadeout.CustomEditText
android:id="#+id/textedit"
android:layout_width="228dp"
android:layout_height="41dp"
android:ems="10"
android:hint="color is changed" />
</LinearLayout>
public static void setEditTextUnderlineColor(final EditText editText, final int focusedColor, final int unfocusedColor) {
editText.setOnFocusChangeListener(new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
editText.getBackground().setColorFilter(focusedColor, PorterDuff.Mode.SRC_ATOP);
return;
}
editText.getBackground().setColorFilter(unfocusedColor, PorterDuff.Mode.SRC_ATOP);
}
});
editText.getBackground().setColorFilter(unfocusedColor, PorterDuff.Mode.SRC_ATOP);
To customize edit Text I did the following way. It worked for me pretty simple way.
public class CardNumberText extends EditText {
boolean isFocus;
Paint mPaint;
Rect mRect;
int widthSize, heightSize;
public CardNumberText(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
initStyle();
}
private void initStyle() {
mRect = new Rect();
mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.parseColor("#B3B3B3"));
}
public CardNumberText(Context context, AttributeSet attrs) {
super(context, attrs);
initStyle();
}
public CardNumberText(Context context) {
super(context);
initStyle();
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Rect rect = mRect;
Paint paint = mPaint;
if (isFocus) {
mPaint.setStrokeWidth(3.0f);
mPaint.setColor(Color.parseColor("#80CBC4"));
} else {
mPaint.setStrokeWidth(1.5f);
mPaint.setColor(Color.parseColor("#B3B3B3"));
}
for (int i = 0; i < getLineCount(); i++) {
int baseline = getLineBounds(i, rect);
canvas.drawLine(rect.left, baseline + 20, rect.right, baseline,
paint);
}
}
#Override
protected void onFocusChanged(boolean focused, int direction,
Rect previouslyFocusedRect) {
super.onFocusChanged(focused, direction, previouslyFocusedRect);
if (focused) {
isFocus = true;
} else {
isFocus = false;
}
}
}
I have problem with refreching canvas in my widget. I create custom widget and I want to repaint first cell on click.
There ins activity
public class TestView extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ElementView ev = (ElementView)findViewById(R.id.surface2);
ev.setOnClickListener(evOnClick);
}
public OnClickListener evOnClick = new OnClickListener() {
#Override
public void onClick(View v) {
ElementView temp=(ElementView)v;
temp.paint.setColor(Color.RED);
temp.canvas.drawRect(new Rect(0,0,90,90),temp.paint);
temp.postInvalidate();
}
};
}
and there is ElementView ( widget which I want to repaint )
public class ElementView extends View {
private final int width=100;
private final int height=100;
public Paint paint=null;
public Canvas canvas=null;
public ElementView(Context context) {
super(context);
paint = new Paint();
}
public ElementView(Context context, AttributeSet attr) {
super(context, attr);
paint = new Paint();
}
public ElementView(Context context, AttributeSet attr, int defaultStyles) {
super(context, attr, defaultStyles);
paint = new Paint();
}
#Override
protected void onMeasure(int widthSpec, int heightSpec) {
int measuredWidth = MeasureSpec.getSize(widthSpec);
int measuredHeight = MeasureSpec.getSize(heightSpec);
setMeasuredDimension(this.width,this.height);
}
#Override
protected void onDraw(Canvas canvas) {
this.canvas=canvas;
// get the size of your control based on last call to onMeasure
int height = getMeasuredHeight();
int width = getMeasuredWidth();
// Now create a paint brush to draw your widget
paint.setColor(Color.GREEN);
//define border
this.canvas.drawLine(0, 0, 0, 99, paint);
this.canvas.drawLine(0, 0, 99,0, paint);
this.canvas.drawLine(99, 0, 99, 99, paint);
this.canvas.drawLine(0, 99, 99,99, paint);
//define cells
this.canvas.drawLine(0,50,99,50,paint);
this.canvas.drawLine(30,0,30,50,paint);
//draw green rectangle
this.canvas.drawRect(new Rect(0,0,50,50),paint);
//draw some text
paint.setTextSize(8);
paint.setColor(Color.RED);
String displayText = "test";
Float textWidth = paint.measureText(displayText);
int px = width / 2;
int py = height / 2;
this.canvas.drawText(displayText, px - textWidth / 2, py, paint);
}
#Override
public boolean dispatchTouchEvent(MotionEvent event) {
paint.setColor(Color.RED);
//change color of first cell
canvas.drawRect(new Rect(0,0,50,50),paint);
return super.dispatchTouchEvent(event);
}
}
When I click on ElementView it enter in Activity in onClick and pass through code without mistake or exception , but doesn't change view . Can anybody tell me where is mistake ?
I don't think writing to the Canvas outside of the onDraw method will have any effect on the screen.
Try setting a flag in your onClick method that you read in onDraw which will trigger your drawing routine.