How to draw beyound view translation limits? - android

The following program draws a pie (partial circle, a sector) while I expect it draw entire (full round) circle. How to draw entire circle?
The code of custom view:
public class CentralCircleView extends View {
private Paint circlePaint = new Paint();
{
circlePaint.setColor(Color.RED);
circlePaint.setAntiAlias(true);
}
public CentralCircleView(Context context) {
super(context);
}
public CentralCircleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawCircle(0, 0, 100, circlePaint);
}
}
The code of activity:
public class TransformsActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
CentralCircleView centralCircleView = (CentralCircleView) findViewById(R.id.centralCircleView);
centralCircleView.setTranslationX(200f);
centralCircleView.setTranslationY(200f);
centralCircleView.invalidate();
}
}
The code of layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.inthemoon.incubation.CentralCircleView
android:id="#+id/centralCircleView"
android:layout_marginLeft="0dp"
android:layout_marginTop="0dp"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</RelativeLayout>
This is what it draws. Where is the rest of the circle?

Your View has its height set to wrap_content which means you need to implement the method onMeasure() to tell RelativeLayout how big the view wants to be.

To draw "outside the view" one should use clipRect() method. For example, in my case, I was to write onDraw() in the following way:
protected void onDraw(Canvas canvas) {
canvas.clipRect(new Rect(-100,-100,100,100), Region.Op.UNION);
canvas.drawCircle(0, 0, 100, circlePaint);
}

Related

Android : Custom View not drawing

I'm getting a problem with a part of my Android application. I need to draw a graph in a custom Dialog box but it doesn't work even when I follow all the solutions found on the internet. My goal is to show a Dialog box when a user is clicking on a button on my main frame. To do this, I want to draw it in a very simple Dialog Box. My graph need to be "scrollable" because it can be bigger than the Dialog box. Here are the sources codes :
public class GraphDialog extends Dialog implements android.view.View.OnClickListener
{
Canvas canvas;
public GraphDialog(Context context)
{
super(context);
System.out.println("Test");
this.setContentView(R.layout.dialog_graph_layout);
this.setTitle(R.string.title_dialog_graph);
((Button) this.findViewById(R.id.button_ok)).setOnClickListener(this);
}
#Override
public void onClick(View v)
{
Controller.getPollManager().setPoll(null);
Controller.getPollManager().setTab(null);
this.cancel();
}
}
Here is my xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin" >
<ScrollView
android:id="#+id/scroll_layout"
android:layout_width="500px"
android:layout_height="800px"
android:layout_weight="1"
android:drawingCacheQuality="low"
android:scrollbars="vertical" >
<be.ac.ucl.lfsab1509.proxipoll.GraphView
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</be.ac.ucl.lfsab1509.proxipoll.GraphView>
</ScrollView>
<Button
android:id="#+id/button_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_weight="0"
android:text="#string/ok" />
</LinearLayout>
And here is my custom View :
public class GraphView extends View
{
Paint paint;
public GraphView(Context context)
{
super(context);
System.out.println("test GraphView");
this.setWillNotDraw(false);
init();
}
public GraphView(Context context, AttributeSet attrs)
{
super(context, attrs);
System.out.println("test GraphView");
this.setWillNotDraw(false);
init();
}
public void init()
{
paint = new Paint();
paint.setColor(Color.BLACK);
}
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
System.out.println("test onDraw");
canvas.drawText(Controller.getPollManager().getPoll().name, 50, 50, paint);
this.draw(canvas);
}
}
To check what goes wrong, you can see that I have added some println(). When I try to show the Dialog box, I get all lines except the on of the onDraw() method. Does someone know what to do to make it work ?
Thank you
Try overriding onMeasure: when I last did any custom charting, I needed to do something like this.
#Override protected void onMeasure( int widthMeasureSpec, int heightMeasureSpec )
{
viewWidth = MeasureSpec.getSize( widthMeasureSpec );
viewHeight = MeasureSpec.getSize( heightMeasureSpec );
if(box.getWidth() != 0){
// use the screen width: oldViewWidth -> screenWidth, viewWidth -> maxXRange
boxWidth = box.getWidth() - box.getPaddingRight() - box.getPaddingLeft() - 10;
if(screenWidth <= 0) viewWidth = boxWidth;
else viewWidth = (int)((getMaxXRange()*boxWidth)/screenWidth);
if(viewWidth < boxWidth) viewWidth = boxWidth;
}
setMeasuredDimension( viewWidth, viewHeight );
}
This basically checks the size of the window and tells the graphics layer how big I want it to be.

Extending View class and layouts in Android

I am playing with layouts and views in Android. My layout looks like:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/LinearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<com.mycode.MyView
android:id="#+id/MyView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<LinearLayout
android:id="#+id/leftpane"
android:layout_width="55dp"
android:layout_height="wrap_content"
android:layout_weight="0.95"
android:background="#color/leftpane_background"
android:gravity="center"
android:orientation="vertical"
android:scrollbarStyle="insideOverlay" >
</LinearLayout>
</LinearLayout>
If i comment the lines <com.mycode.MyView .... />, the left linear layout (with id leftpane) is showed, otherwise not. If i add another layout after the leftpane layout (for example a scroll view layout), it does not get showed as well.
Why using my custom view (MyView) makes disappear all other layouts?
What i would like to do is to have my custom View for the background of the application, where i would show images, and some other view over the background, like scroll views, buttons and so on.
This is the code of MyView class. Keep in mind that i need to draw on the background of the activity an images (on the whole background, obviously not including the action bar):
/**
*/
class MyView extends View
{
TextPaint text_paint;
Paint paint;
private void InitView()
{
text_paint = new TextPaint( Paint.ANTI_ALIAS_FLAG );
text_paint.setColor( Color.BLACK );
paint = new Paint();
}
public MyView(Context context)
{
super(context);
InitView();
}
public MyView(Context context, AttributeSet attrs)
{
super(context, attrs);
InitView();
}
public MyView(Context context, AttributeSet attrs, int defaultStyle)
{
super(context, attrs, defaultStyle);
InitView();
}
#Override
protected void onDraw( Canvas canvas )
{
super.onDraw(canvas);
//int w, h;
//w = canvas.getWidth();
//h = canvas.getHeight();
//paint.setColor( Color.WHITE );
//canvas.drawRect(0, 0, w-1, h-1, paint );
//canvas.drawText( "ciao", 100, 100, text_paint);
}
};
Try to change your view's height as:
android:layout_height="wrap_content"
Maybe you did some error work when you overrode the onMeasure method in your custom MyView,
and so the MyView's match all the parent view.
Can you show your code which in the onLayout and onMeasure method of the MyView.

android: how to implement canvas draws into a exist view in XML

I have a XML file in my program like:
<LinearLayout android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1">
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ef3"
android:id="#+id/img01"/>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#E8A2B4"
android:id="#+id/img02"/>
</LinearLayout>
Also, I have a canvas draw function in my activity.
public class ImgTestActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
private class iniView extends View {
public iniView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
//set background color
canvas.drawColor(Color.WHITE);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeWidth(3);
canvas.drawCircle(this.getWidth()/2, this.getHeight()/2, 30, paint);
}
}
}
I read some articles from Internet. Some people create there own view in activity and set the paint into it.
public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        MyView myView=new MyView(this);
        setContentView(myView);
    }
But I want to set my paint into this two LinearLayout.
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ef3"
android:id="#+id/img01"/>
<LinearLayout android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#E8A2B4"
android:id="#+id/img02"/>
How can I do that? (I want to draw two same circles in the center of this two linear layout)
One solution would be to extract the initView (should be CamelCase btw) and then inject it into the xml with the full path name of the class of the View as the tag name. Let's see an example. The resultant class should look like this:
package your.package;
// imports
private class CircleView extends View {
public iniView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
// your painting stuff
}
}
And the the xml should be something like this:
<your.package.CircleView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#ef3"
android:id="#+id/img01"/>
<your.package.CircleView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_weight="1"
android:background="#E8A2B4"
android:id="#+id/img02"/>
Although you may want to have a look at the available Drawable resources in Android: http://developer.android.com/guide/topics/resources/drawable-resource.html
There is a Shape Drawable type that may allow you to do what you want in a simpler way and separated from the business logic of the Activity.
Hope it helps
You can render your xml view using this:
View viewalias = (View) this.findViewById(R.layout.yourxml);, then draw on it as you like, for more details, see this.
try this :
...
import android.util.AttributeSet;
...
public iniView(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
...

How to scroll bitmaps?

I have one image view (assigned one bitmap to it) and another bitmap (Transparent) for painting. How it is possible to scroll this bitmap and background bitmap at the same time to be painted at different places.
From what I understood you are trying to draw on top of a image. If thats the case, create a custom view and get the image using BitmapFactory. After you get a bitmap object, use its copy method and use that copy for the canvas of the view.
Now you can override the onDraw method of a custom view and draw anything on top of it.
This view can be added to the layout, and scrolling will happen to the view.
Edit: Sample Code
Ok this is some code that might help you. I dont have the time to go through all your code.
But I tried to understand your requirement.
I am showing the code for an activity, its xml and custom view
Activity.java
public class DrawDemo extends Activity {
private FrameLayout container;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.draw_demo_layout);
container = (FrameLayout)findViewById(R.id.sc);
container.addView(new DrawView(this));
}
public void drawHandler(View target){
container.addView(new DrawView(this));
}
public void clearHandler(View target){
if(container.getChildCount() != 1){
container.removeViewAt(container.getChildCount()-1);
}
}
}
draw_demo_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<FrameLayout android:orientation="vertical"
android:layout_width="fill_parent" android:layout_height="0dip"
android:id="#+id/sc" android:scrollbars="horizontal"
android:layout_weight="1.0">
<ImageView android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:src="#drawable/chips"/>
</FrameLayout>
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Draw"
android:onClick="drawHandler"/>
<Button android:layout_width="fill_parent"
android:layout_height="wrap_content" android:text="Clear"
android:onClick="clearHandler"/>
</LinearLayout>
DrawView.java
public class DrawView extends View {
public DrawView(Context context) {
super(context);
setLayoutParams(new LayoutParams(LinearLayout.LayoutParams.FILL_PARENT
,LinearLayout.LayoutParams.FILL_PARENT));
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint p = new Paint();
p.setColor(Color.RED);
p.setStrokeWidth(5);
canvas.drawLine(50, 50, 100, 150, p);
canvas.drawLine(100, 150, 20, 50, p);
}
}
This activity has a framelayout which has a imageview as the base which holds the bitmap.
We add a custom draw view on top of it and do our drawings on it.When we want to clear the drawing we remove the drawview and add another one if we need to draw again.
This might not be the most efficient way. But should get you started.

main.xml hiding the view help

I am unable to display both the setContentView(R.layout.main) and View together. I think I am not getting the concept right. Could anyone explain me where I am going wrong. Thank you. //please read the comment in code
I am trying to display a image on main.xml using BitmapFactory.
public class TryGraph extends Activity
{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);//I think this is where I need your help
setContentView(new myView(this));//I want this to be displayed in main.xml
}
private class myView extends View{
public myView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
Bitmap myBitmap = BitmapFactory.decodeResource(getResources(), R.drawable.sinewave);
Bitmap resizedBitmap = Bitmap.createBitmap(myBitmap, 0, 0,
300, 143);
canvas.drawBitmap(resizedBitmap, 60, 50, null);
Paint myPaint = new Paint();
myPaint.setColor(Color.RED);
myPaint.setStyle(Paint.Style.STROKE);
myPaint.setStrokeWidth(5);
canvas.drawRect(250,255,260,250, myPaint);
}
}
}
THE XML FILE IS
When you call setContentView you are telling the device to load the entire layout that should be displayed to the user. In most cases this view will occupy the entire screen. Now this Layout file is considered the root and may contain child views, one of which should be your ImageView.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<TextView
android:id="#+id/banner"
android:text="hello world"
>
<ImageView
android:id="#+id/myImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/sampleimage"
/>
<?LinearLayout>
This ImageView can now be accessed by code through the use of findViewById(R.id.myImageView) and you can then use the BitmapFactory to set your image. If the image is not going to be changed, you can just set it in the layout file android:src="#drawable/sampleimage"

Categories

Resources