I'm quite new to Android programming and I'm stuck on how to get this right.
My situation is I want to draw a rectangle inside a RelatativeLayout and be able to change the shape of the rectangle dynamically relative to the size of the RelativeLayout which does not encompass the whole screen.
My problem is when I try to implement this, the size of the rectangle is still relative to the screen size
Is there a way where I can restrict the canvas size to the RelativeLayout size or is there a better way?
Here is part of my code from the maim activity
RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
blueView = new Bar(this);
blueView.setLayoutParams(rl);
blueLayout.addView(blueView);
And I also have a Bar class that extends View
public class Bar extends View{
Rect theBar;
public Bar(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
theBar = new Rect();
theBar.set(0, 0, canvas.getWidth(), canvas.getHeight()/2);
Paint blue = new Paint();
blue.setColor(Color.BLACK);
blue.setStyle(Paint.Style.FILL);
canvas.drawRect(theBar, blue);
}
}
Related
I'm currently making a simple game with the surfaceview but I find it hard to position the buttons or texts within the Relative layout programmatically in android. For example, in the sample below Im setting the relativelayouts with texts in a relative layout, and I want to set it to the right side of the screen with few margins to the right. How should I understand where I'm positioning the contents ? And are there some tips on positioning contents programmatically?
RelativeLayout Rs = new RelativeLayout(this);
Rs.setBackgroundResource(R.drawable.btn);
Rs.setGravity(Gravity.CENTER);
Regame.addView(RR,400,150);
Rs.setX(0);
txt= new TextView(this);
I guess it would be sufficient if you accessed the canvas from within the surfaceView.Probably would be more efficient if you used onSizeChange
for the width and height but i guess the canvas getWidth and getHeight would suffice.Also my example is just drawing once the surface is created, you'll have to make your own update logic.Also i am ditching the relative layout but i think this could suffice your needs:
public class GameView extends SurfaceView {
protected SurfaceHolder holder;
public GameView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(new SurfaceHolder.Callback() {
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
});
}
protected void onDraw(Canvas canvas) {
Paint paint = new Paint();
paint.setColor(Color.BLACK);
paint.setTextSize(20);
int width=canvas.getWidth();
int height=canvas.getHeight();
//Just for example
int desiredHeight=height/2;
int desiredMargin=10;
String desiredText="Some text";
int textWidth=Math.round(paint.measureText(desiredText));
int desiredWidth=width-textWidth-desiredMargin;
canvas.drawText(desiredText, desiredWidth,desiredHeight, paint);
}
}
In my application,I am setting an image in my imageview. I just need to place a marker on that imageview. I am doing it with onDraw function in my custom image view class.The problem is,for example if I take x position and y position as 40 respectively.The marker position shown above image in my mobile is different when compared with running same application on tablet.
I want a solution such that when I give coordinates then the position of marker on image in mobile and tablet appears same.
Here is the code my main activity:
public class PointOnImageActivity extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_point_on_image);
CustomImag ev= new CustomImag(this);
ev.setBackgroundResource(R.drawable.stad);// set background
setContentView(ev);
}
}
Here is the code of my custom imageview class:
public class CustomImag extends ImageView
{
public CustomImag(Context context)
{
super(context);
}
#Override
public void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Paint mPaint = new Paint();
mPaint.setColor(Color.RED);
canvas.drawCircle(40,40,10,mPaint);
}
}
that's because 40 is pixel value, you actually need 40dp instead. so you can convert 40dp to px value dynamically, like this:
int pxValue1 = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 40, context.getResources()
.getDisplayMetrics());
int pxValue2 = (int)TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 10, context.getResources()
.getDisplayMetrics());
canvas.drawCircle(pxValue,pxValue,pxValue2,mPaint);
You have to position your custom View according to the screen dimensions. This way, no matter what size screen displays your app, your positioning will be relative.
In your onDraw(Canvas) method, you can get the screen dimensions and draw the circle using them. In the following example(which is mostly your code), I place the red circle at screen_width / 4 and screen_height / 4:
public class MyCustomImageViewActivity extends Activity{
CustomImag ev;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ev = new CustomImag(this);
ev.setBackgroundResource(R.drawable.stad);// set background
setContentView(ev);
}
public class CustomImag extends ImageView {
Paint mPaint;
public CustomImag(Context context) {
super(context);
mPaint = new Paint();
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
Point point = new Point();
getWindowManager().getDefaultDisplay().getSize(point);
mPaint.setColor(Color.RED);
canvas.drawCircle(point.x / 4, point.y / 4, 10, mPaint);
}
}
}
I want to add text in a circle or half circle programmatically, in such a way that instead of having a circle with line edges, the edges are the words. See image for a better explanation.
How can I do this in Android, or what resources could I read in order to help me with this problem?
In order to do this, you will need to draw your text onto a Canvas. Any subclass of View is passed a Canvas in onDraw() that you can use to draw your custom text. The method drawTextOnPath() lets you put text on any Path object you choose. You can create a semi-circle path by creating a new instance and using addArc().
you can Use Below Code. and Make it as you Want your Textview.
Here if you want Something as Backgroung image then use setBackgroundResource(R.drawable.YOUR_IMAGE);
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GraphicsView(this));}
static public class GraphicsView extends View {
private static final String QUOTE = "text in a half-circle";
private Path circle;
private Paint cPaint;
private Paint tPaint;
public GraphicsView(Context context) {
super(context);
int color = Color.argb(127, 255, 0, 255);
circle = new Path();
circle.addCircle(230, 350, 150, Direction.CW);
cPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
cPaint.setStyle(Paint.Style.STROKE);
cPaint.setColor(Color.LTGRAY);
cPaint.setStrokeWidth(3);
// For Background Image
setBackgroundResource(R.drawable.YOUR_IMAGE);
tPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
tPaint.setStyle(Paint.Style.FILL_AND_STROKE);
//TextColor you want to set
tPaint.setColor(Color.BLACK);
//TextSize you want to set
tPaint.setTextSize(50);}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawTextOnPath(QUOTE, circle, 485, 20, tPaint);}
}
}
try it out. hope it will help you.
I've created a bar that is supposed to contain multiple views of different colors. A line has to be drawn that indicates the current position in the bar. Below is my simplified code:
public class Abar extends LinearLayout {
final Paint line_paint = new Paint();
private Context context;
public Abar(Context context) {
super(context);
this.context = context;
line_paint.setColor(Color.WHITE);
setWeightSum(2000);
setBackgroundResource(R.color.blue);
View view = new View(context);
view.setBackgroundResource(R.color.yellow);
this.addView(view, new LinearLayout.LayoutParams(0, LayoutParams.MATCH_PARENT, 1000));
}
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawLine(20, 80, 100, 80, line_paint);
}
}
Now, this does not seem to work. No matter if I swap the canvas.drawLine with super.onDraw, the line is not visible unless I remove the view.setBackgroundResource. How can I draw a line over the LinearLayout. I'd rather not use FrameLayout if possible.
Below are pictures of what I'm trying to achieve (adding a white line) on top of the bars (note: the white bar on the first picture is just exaggerated big for clearness on SO):
Override dispatchDraw() instead of onDraw(). You want to draw the line after the child views draw (which isn't in super.onDraw).
I can add this logo to the canavas if I do this:
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(200,200);
ImageView boo = new ImageView(ExampletouchActivity.this);
boo.setImageResource(R.drawable.ic_launcher);
boo.setLayoutParams(lp);
fr.addView(boo); //this works fine
But if I try to add the same logo to the canvas like this it does not show anything up:
fr.addView(new Toucher(ExampletouchActivity.this));
My Toucher class is like so...
public class Toucher extends View{
ImageView boo;
public Toucher(Context context)
{
super(context);
FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(200,200);
boo = new ImageView(context);
boo.setImageResource(R.drawable.ic_launcher);
boo.setLayoutParams(lp);
}
#Override
public void onDraw(Canvas c)
{
boo.draw(c);
}
I have been trying for ages and cannot work out why this imageview will not draw itself to the canvas?
Many Thanks
Layout and Canvas aren't the same thing. Layout is "draw this for me", and Canvas is "I'm drawing this". In your working example, you're taking a static image and putting it into a Layout.
When you are using the canvas, in a view things are different, so try using:
canvas.drawBitmap(bg, src, dst, paint);