I have a library that shows a camera preview. I want to add a rectangle overlay on top of the preview. I tried 2 different approaches. But both of them display the rectangle shortly then disappear.
approach (using view.getOverlay)
mPreview.setZOrderMediaOverlay(true);
mPreview.setZOrderOnTop(true);
ViewGroup rootView = (ViewGroup)mActivity.getWindow().getDecorView().findViewById(android.R.id.content);
rootView.addView(mPreview);
final ViewOverlay overlay = mPreview.getOverlay();
final Bracket bracket = new Bracket();
mPreview.post(new Runnable() {
#Override
public void run() {
bracket.setBounds(0, 0, mPreview.getWidth(), mPreview.getHeight());
overlay.add(bracket);
}
});
approach (overriding draw function in surfaceview)
#Override
public void draw(Canvas canvas) {
super.draw(canvas);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setStrokeWidth(10);
//center
int x0 = canvas.getWidth()/2;
int y0 = canvas.getHeight()/2;
int dx = canvas.getHeight()/3;
int dy = canvas.getHeight()/3;
//draw guide box
canvas.drawRect(x0-dx, y0-dy, x0+dx, y0+dy, paint);
}
mPreview extends SurfaceView
Bracket extends Drawable
UPDATE
If I use setContentView instead of rootView.addView it works as expected. But in this case I can not remove the view.
I used a new Activity and setContentView. That solved the problem.
To remove the view I finished the action.
Related
Whenever extending the class, the bar will be drawn in the vertical center of its container. I need to place text above the bar and increasing the height (I am setting an arbitrary height on the view) causes a bunch of blank space beneath the bar. I've been googling for quite some time now but all I find is regarding the thumb mostly, and I need to draw the bar on the bottom of its container.
This is what I'm trying to achieve as a single view (notice how the bar's position in not centered):
The only "useful" code I could find was this:
Window window = ((Activity) getContext()).getWindow();
window.setGravity(Gravity.BOTTOM);
WindowManager.LayoutParams wmlp = window.getAttributes();
wmlp.y = getHeight() / 4;
window.setAttributes(wmlp);
But it has no effect whatsoever.
My custom class, nothing out of the ordinary:
public class RateSeekbar extends AppCompatSeekBar {
private Paint lettersPaint;
private Paint numberPaint;
// constructors and call to init()
private void init() {
lettersPaint = new Paint();
numberPaint = new Paint();
... // style the two different paints
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
... // get a couple of strings from resources and measure them
int middleHor = getWidth() / 2;
canvas.drawText(text1, getPaddingLeft(), 40, lettersPaint);
canvas.drawText(text2, getWidth() - text2Size - getPaddingRight(), 40, lettersPaint);
canvas.drawText(String.valueOf(getProgress()), middleHor - (text3Size / 2), 50, numberPaint);
}
}
Any ideas?
I wrote the following code and it works well. But I have other purpose. I want to click only on a view to doing the operations.First, Please see the following image:
MY CODE IS AS FOLLOWS:
public class MainActivity extends Activity {
RelativeLayout relativeLayout;
#Override
protected void onCreate(Bundle bundle)
{ super.onCreate(bundle);
relativeLayout = new RelativeLayout(getApplicationContext());
setContentView(relativeLayout);
A a = new A(this);
relativeLayout.addView(a);
a.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
B b = new B(getApplicationContext());
relativeLayout.addView(b);
}
});
}
}
class A extends View {
Paint paint;
A(Context context) {
super(context);
paint = new Paint();
}
#Override
protected void onDraw(Canvas canvas) {
paint.setAntiAlias(true);
paint.setColor(Color.RED);
canvas.drawRect(20,60,100,150,paint);
}
}
class B extends View {
Paint paint;
B(Context context){
super(context);
paint = new Paint();
}
#Override
protected void onDraw(Canvas canvas){
paint.setAntiAlias(true);
paint.setColor(Color.GREEN);
canvas.drawRect(100,150,200,250,paint);
}
}
when I run the above code I can see the green rectangle after press on the red rectangle. But the problem is that when I press another places on the screen I can do this operations also. I want that only I can see the green rectangle to press on the red rectangle and not in the another places on the screen to doing this operations.
Use onTouch event
a.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getX(0)>=20 && event.getY(0)>=60 && event.getX(0)<=160 && event.getY(0)<=150) {
B b = new B(getApplicationContext());
relativeLayout.addView(b);
}
return true;
}
});
You are defining the red square's parameters but not the parameters of the canvas in which you are drawing. You are creating the view (A) without defining the width and height of it, so it is set to match_parent by default, which means it will take the whole size of your RelativeLayout (the whole screen). So, when you click "outside" the red square you are actually clicking the view (A).
Try to define an specific height and width for the view in which you are drawing, like this.
A a = new A(this);
a.setLayoutParams(new RelativeLayout.LayoutParams(300,300));
Remember that LayoutParams takes pixels as parameters, so you should really convert the dps to px as specified here
Also, setting some background colors to your views (relativeLayout, A) will help you visualize what you are doing.
# nukeforum, your guess helped me very much. I thank all of you. My problem was exactly from the canvas and its size. I added the following operation in my code and solved my problem.
relativeLayout.addView(a,70,70);
For A class, I changed as follows:
canvas.drawRect(10,20,30,40,paint);
I have the following class:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
String value = "0";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(new GaugeAnimation(this));
}
}
My GuageAnimation class is as follows:
public class GaugeAnimation extends View{
private Path p;
private Paint cPaint = new Paint();
private int width = 200;
private int angleStart = 135;
private int sweep = 90;
private int value=0;
Bitmap bottom = BitmapFactory.decodeResource(getResources(), R.drawable.dashboard_rpm_bottom);
Bitmap top= BitmapFactory.decodeResource(getResources(), R.drawable.dashboard_rpm_active);
public GaugeAnimation(Context context){
super (context);
//Arc Equations & etc....
}
#Override
public void onDraw(Canvas c){
Paint paint = new Paint();
paint.setFilterBitmap(false);
paint.setColor(Color.BLUE);
c.translate(55,320);
//Draw bottom image on canvas
c.save();
p.addArc(new RectF(0,0,width,width), angleStart, sweep);
p.lineTo(width/2, width/2);
c.clipPath(p);
//draw Image on top
c.restore();
invalidate()
}
}
so basically this crops a circular image one piece at a time based on arc equations. I want to show an animation like the circle's pieces all being filled in (so showing each clipped path which demonstrates a circle being built). So i was thinking of doing a for loop like:
for (int i=0; i<100; i++) {
sweep=i;
p.addArc(new RectF(0,0,width,width), angleStart, sweep);
p.lineTo(width/2, width/2);
c.clipPath(p);
invalidate();
}
but this doesn't work it just draws the end result when i=100, anyone have an idea as to how i can do this?
Currently your loop is performed on the main thread and keeps it busy, so it will not actually update the UI until you finish.
You should do the loop in a background thread (using Timer or AsyncTask) and perform the paint on main thread. Note that without a short sleep, it will probably would look like an animation too much, it will be pretty fast.
What is the simplest way to draw pixels, lines and circles on a View?
I want to move a cross cursor around, so nothing particularly intensive.
I thought I could extend SurfaceView and add it to an XML and it would just work, but it just appears black, however, when I look at the layout view of localmap.xml in eclipse, the graphics appear as expected.
Any ideas? My onDraw is never called on the emulator, and even calling invalidate on the class makes no difference. I shall keep trying but can anyone see anything I've missed? or is there a better way entirely?
Frink
localmap.xml contains the following (in a RelativeLayout)
<com.example.android.game.LocalMapView
android:id="#+id/localmap_map"
android:layout_width="fill_parent"
android:layout_above="#id/localmap_planettext"
android:layout_below="#id/header"/>
LocalMapView.java contains the following (amongst other things)
public class LocalMapView extends SurfaceView {
Paint mPaint = new Paint();
//Construct a LocalMapView based on inflation from XML
public LocalMapView(Context context, AttributeSet attrs) {
super(context, attrs);
// allow the map to receive the focus
setFocusable(true);
}
private void drawPixel(Canvas canvas, int x, int y, int colour) {
mPaint.setColor(colour);
if ((x >= MAP_MIN_X) && (x < MAP_MAX_X) && (y >= MAP_MIN_Y) && (y < MAP_MAX_Y)) {
canvas.drawPoint(((float)x * mScaleMapToScreenX), ((float)y * mScaleMapToScreenY), mPaint);
}
}
private void drawCircle(Canvas canvas, int x, int y, int radius, int colour) {
mPaint.setColor(colour);
canvas.drawCircle(((float)x), ((float)y), ((float)radius), mPaint);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
drawCircle(canvas, MAP_MAX_X/2, MAP_MAX_Y/2, 1, 0xFF00FFFF);
drawPixel(canvas, MAP_MAX_X/2, MAP_MAX_Y/2, 0xFF000000);
}
With SurfaceView you don't do the drawing in onDraw(). You have to grab a canvas from the underlying surface and draw in there. It seems to me you don't really know why you are using a SurfaceView. Just use a normal View instead and onDraw() will work just fine.
I'm trying to draw a shape on a Canvas and get information about the clicks that the user performs on that Canvas.
I created a class which extends the Button class.
class CustomDrawableButton extends Button {
private final ShapeDrawable mDrawable;
int x = 50;
int y = 50;
int width = 30;
int height = 30;
public CustomDrawableButton (Context context) {
super(context);
mDrawable = new ShapeDrawable (new OvalShape ());
mDrawable.getPaint().setColor(Color.GREEN);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
Then, in a class which also extends View, I added the instantiation and a listener:
CustomDrawableButton mCustomDrawableButton = new CustomDrawableButton(getBaseContext());
layout.addView(mCustomDrawableButton);
mCustomDrawableButton.draw(canvas);
mCustomDrawableButton.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
System.out.println("Yey clicked");
Toast.makeText(view.getContext(), "Yey", Toast.LENGTH_LONG).show();
}});
When this is executed, it is not able to detect the clicks on the image / button. I have read that ShapeDrawable objects can't be "clickable", but I was expecting this to work since I'm extending the Button (which is a View and is "clickable").
Is this possible? If not this way, can you direct me to some way to get information about the screen coordinates that were pressed on a Canvas or a View ?
Thanks in advance.
After some searching here's a tutorial that shows how to do it using by getting the touched screen position.
http://marakana.com/tutorials/android/2d-graphics-example.html
Still don't know how to do it by automatically binding the touched event to a button. If anyone knows how to do it, please say so.
Thanks.