I want to show a statistic page as a popup from an activity. My question is how do I hand off the data to the canvas drawing it?
My popupWindow xml is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/gradient_dark_teal_bg">
<LinearLayout
android:id="#+id/llvStats"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:background="#drawable/gradient_teal_bg"
android:orientation="vertical">
<TextView
android:id="#+id/txtBanner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginBottom="10dp"
android:gravity="center_vertical|center_horizontal|center"
android:text="STATISTICS"
android:textColor="#color/colorTeal1"
android:textSize="24sp"
android:textStyle="bold|italic" />
<com.mairyu.app.lingoflash.StatsDrawCanvas
android:id="#+id/statsCanvasDraw"
android:layout_below="#+id/txtBanner"
android:layout_width="400dp"
android:layout_height="500dp"
android:layout_column="1"
android:layout_gravity="left|top"
android:background="#drawable/gradient_light_teal_bg"
android:layout_row="0" />
</LinearLayout>
</RelativeLayout>
My popup launch snippet is:
case R.id.btnDatabaseStats:
layoutInflater = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
popupView = layoutInflater.inflate(R.layout.stats_popup_window,null);
popupWindow = new PopupWindow(popupView,STATS_POPUP_WIDTH,STATS_POPUP_HEIGHT);
popupWindow.showAtLocation(findViewById(R.id.database_page),
Gravity.CENTER, STATS_POPUP_GRAVITY_X, STATS_POPUP_GRAVITY_Y);
LinearLayout llvStats = (LinearLayout) popupView.findViewById(R.id.llvStats);
llvStats.setOnTouchListener(new OnSwipeTouchListener(this) {
#Override
public void onSwipeLeft() {
popupWindow.dismiss();
}
});
I want to see something like this:
Since this is not a new activity, I can't use the intent/bundle method to exchange variables (or can I ?). If it would be simple textview or other widgets, I could use setText etc., but I need to get the data inside the canvas.
I think I still lack understanding of how to use onDraw and other canvas features, but right now I just hardcoded the numbers. Is there an easy way to simply get those numbers (5/15/25) from the launching activity ? (I tried a global variable, but it wasn't visible within onDraw)
#Override
protected void onDraw(Canvas c) {
CanvasWidth = c.getWidth();
CanvasHeight = c.getHeight();
Paint myPaint = new Paint();
myPaint.setStyle(Paint.Style.FILL);
myPaint.setColor(getResources().getColor(R.color.colorTeal1));
myPaint.setStrokeWidth(10);
c.drawRect(160, 60, 800, 110, myPaint);
c.drawRect(160, 160, 250, 210, myPaint);
c.drawRect(160, 260, 400, 310, myPaint);
brush.reset();
brush.setColor(getResources().getColor(R.color.colorTeal1));
brush.setTextSize(36);
brush.setTypeface(Typeface.DEFAULT_BOLD);
c.drawText("1 Day:", 20, 100, brush);
c.drawText("2 Days:", 20, 200, brush);
c.drawText("3 Days:", 20, 300, brush);
brush.setColor(getResources().getColor(R.color.colorTeal3));
c.drawText("5", 167, 99, brush);
c.drawText("15", 167, 198, brush);
c.drawText("25", 167, 298, brush);
}
Hope this is clear and not too amateurish ...
Actually seems to be pretty simple, now I'm just using a method call within my canvas class:
public void setBar(ArrayList<Integer> left, ArrayList<Integer> top, ArrayList<Integer> right, ArrayList<Integer> bottom) {
barCoordLeft = left;
barCoordTop = top;
barCoordRight = right;
barCoordBottom = bottom;
invalidate();
}
and access these global variables within onDraw.
In my activity where I launch the popup, I get the canvas via:
statsDrawCanvas = (StatsDrawCanvas) popupView.findViewById(R.id.statsCanvasDraw);
and then pass on the data via the method call:
statsDrawCanvas.setBar(CanvasBarLeftArray, CanvasBarTopArray, CanvasBarRightArray, CanvasBarBottomArray);
Related
How can I make a line with Button in the same Activity?
After I made a Button in XML file, I tried to make a line.
But when I tried to make line, I could not use
setContentView(R.layout.activity_main);
I could use this:
ViewMenu vm = new ViewMenu(this);
vm.setBackgroundColor(Color.BLACK);
setContentView(vm);
How can I make line with Button in the same Activity?
Could anyone add an example code??
add code
activity_main.xml
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin" tools:context=".MainActivity">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Button"
android:id="#+id/button" />
</RelativeLayout>
Methode onCreate() in MainActivity.java
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView(R.layout.activity_main);
ViewMenu vm = new ViewMenu(this);
vm.setBackgroundColor(Color.BLACK);
setContentView(vm);
}
ViewMenu class
public class ViewMenu extends View {
Paint paint = new Paint();
public ViewMenu(Context context) {
super(context);
paint.setColor(Color.WHITE);
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawLine(0, 0, 1000, 1000, paint);
canvas.drawLine(500, 1000, 700, 10, paint);
}
}
Add your custom view to the layout's xml file
You can use an custom view to draw the line such as LineView.
In your XML put the code like below to achieve the layout you want. So you can set the line whenever you want(At specific position like at above, below, left or right of any component).
<com.android.drawable.LineView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/firstButton"
android:layout_toLeftOf="#id/secondButton"
android:layout_below="#id/leftButton"
android:layout_above="#id/rightButton"
/>
I have a android.graphics.Path variable which I want to convert into an ImageView in my activity.
What I do right now and does NOT work (but it does run without error, it just displays a blank activity) is:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Path p = ... // some bezier curves
PathShape pathShape = new PathShape(path, (float)20.0, (float)20.0);
ShapeDrawable shapeDrawable = new ShapeDrawable(pathShape);
ImageView testImage = (ImageView) findViewById(R.id.testImage);
testImage.setImageDrawable(shapeDrawable);
}
}
The corresponding activity_main.xml is:
<RelativeLayout 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:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
android:paddingBottom="#dimen/activity_vertical_margin"
tools:context="com.tg.MindGames.set.MainActivity">
<ImageView
android:id="#+id/testImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
What did I do wrong and what is considered best practice to put Path into an ImageView?
Additional Information: I want to use the Paths to draw the images of cards in a simple card game. Several cards and additional text fields should be displayed on the activity at the same time, cards should be able to have an onClickListener.
The size of 20.0 x 20.0 is arbitrary and should be altered later when I use the ImageViews in a GridView.
so here you have a red triangle drawn on the view's background:
View v = new View(this);
Path path = new Path();
path.moveTo(0, 1);
path.lineTo(0.5f, 0);
path.lineTo(1, 1);
ShapeDrawable sd = new ShapeDrawable(new PathShape(path, 1, 1));
sd.getPaint().setColor(Color.RED);
v.setBackgroundDrawable(sd);
setContentView(v);
I'm new on Android, and I am having trouble with the following:
I have an image of an empty test-tube (png or bmp).
And I need to draw lines on top of it to make the illusion that its being filled in with liquid.
I really don't know how to proceed. I have read google's documentation about animations, but that didn't help much.
I'd appreciate if you guys could give me some suggestions of how it can be done, and point to some tutorials/documentation that can help me.
Thanks in advance.
UPDATE:
The tube is not retangular, the bottom is oval.
I think I need to make the liquid fall into the test tube, then paint line by line, starting from the bottom. And I have to check for the borders of the tube (right and lef black pixels).
Any ideas of how this can be done?
UPDATE 2:
Here is the tube image: http://i61.tinypic.com/2nw0eb9.png
You can use a SurfaceView to draw what ever you want:
Basicly, you lock the surface's canvas by
Canvas canvas = mSurfaceView.getHolder().lockCanvas();
Then, use the canvas's methods to draw on it. canvas.drawBitmap, canvas.drawLine etc..
When you're finished lock the canvas with mSurfaceView.getHolder().unlockCanvasAndPost(canvas); and you're done.
here's an example from a quick google search:
http://android-coding.blogspot.co.il/2011/05/drawing-on-surfaceview.html
Best way to do this would be with a custom View. Make a new class, that extends View, then in its onDraw method first draw the picture, then draw your animations. If you want to do it by hand, you can do something like this:
private class TestTubeView extends View {
private int top = 0;
private Paint myPaint;
public MyView(Context context) {
super(context);
myPaint = new Paint();
myPaint.setColor(getResources().getColor(R.color.blue));
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
//First draw your bitmap
canvas.drawBitmap(BitmapFactory.decodeResource(getResources(), R.drawable.my_testtube), 0, 0, myPaint); //might need to use a different paint
//Then your "animation" as a static image, that has its position set from a variable, in this case "y" and "x"
canvas.drawRect(0, top, getWidth(), getHeight(), myPaint);
}
//In this method update your variables, that define the positions of your animated lines / bubbles
public boolean updateAnimation() {
top++;
invalidate();
//So it stops animationg
return top > getHeight();
}
}
Then in your layout you put it in like a normal view:
<com.example.TestTubeView
android:id="#+id/my_testtube"
android:layout_width="20dp"
android:layout_height="200dp" />
And then you animate it with a self-repeating Runnable:
final MyView testTube = findViewById(R.id.my_testtube);
final Handler myHandler = new Handler();
myHandler.post(new Runnable() {
#Override
public void run() {
if(testTube.updateAnimation()){
myHandler.postDelayed(this, 200);
}
}
});
You'll have to play around with sizes / heights and things like that though. Another way of doing this is with an ObjectAnimatior
Tube Drawable: (this is for test purposes. you will use your tube image)
tube.xml (drawable folder)
<shape xmlns:android="http://schemas.android.com/apk/res/android" >
<stroke android:width="5dp" android:color="#ffccffff" />
<solid android:color="#00000000" />
</shape>
tube_activity.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:gravity="center" >
<FrameLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
android:id="#+id/orangeJuiceLinearLayout"
android:layout_width="140dp"
android:layout_height="0dp"
android:layout_gravity="bottom"
android:orientation="vertical"
android:background="#fff58225">
</LinearLayout>
<ImageView
android:id="#+id/tubeImageView"
android:layout_width="140dp"
android:layout_height="220dp"
android:layout_gravity="center"
android:background="#drawable/tube"
android:onClick="fillJuice"
android:clickable="true" />
</FrameLayout>
</LinearLayout>
TubeAcivity.java
public class TubeActivity extends Activity {
LinearLayout orangeLL;
ImageView tubeIV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.tube_activity);
orangeLL = (LinearLayout)findViewById(R.id.orangeJuiceLinearLayout);
tubeIV = (ImageView)findViewById(R.id.tubeImageView);
}
public void fillJuice(View view) {
ValueAnimator va = ValueAnimator.ofInt(0, tubeIV.getMeasuredHeight());
va.setDuration(1500);
va.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
public void onAnimationUpdate(ValueAnimator animation) {
Integer value = (Integer) animation.getAnimatedValue();
orangeLL.getLayoutParams().height = value.intValue();
orangeLL.requestLayout();
}
});
va.start();
}
}
I have the following problem with my application: I have created a custom View Class:
private class MyCustomPanel extends View {
private int width;
private int height;
public MyCustomPanel(Context context,int width,int height)
{
super(context);
this.height=height;
this.width=width;
}
#Override
public void draw(Canvas canvas) {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setStyle(Style.STROKE);
paint.setStrokeWidth(2);
paint.setColor(getResources().getColor(R.color.pending));
float radius=(height)/2;
float center_x = (width)/2;
float center_y = (height)/2;
Log.d("DEBUG","R="+radius+" cx="+center_x+" cy="+center_y);
final RectF oval = new RectF();
oval.set(center_x- radius,
center_y - radius,
center_x + radius,
center_y + radius);
//Draw a left semicircle
canvas.drawArc(oval, 90, 180, false, paint);
}
}
This class is an inner class and I am trying to add in it a RelativeLayout in front of a Button.
I have successfully tried to add it to another layout, so it is added and drawn correctly (see here screenshot).
In the previous case the draw function is called and the semicircle is drawn.
In the following though the draw function is not called..
I use this code:
ViewGroup p=(ViewGroup)button.getParent();
MyCustomPanel c=new MyCustomPanel(p.getContext(),p.getWidth(),p.getHeight());
((ViewGroup)p.findViewById(R.id.semicircleFrame)).addView(c);
and the XML in of the RelatedLayout is:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/button_selector"
android:id="#+id/frame">
<Button
android:id="#+id/button"
android:layout_gravity="center"
android:textColor="#FFFFFF"
android:background="#drawable/calendar_button_selector"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
>
</Button>
<RelativeLayout
android:id="#+id/semicircleFrame"
android:layout_width="match_parent"
android:layout_height="fill_parent"
>
</RelativeLayout>
</RelativeLayout>
The hierarchy viewer shows the following:
screenshot
I have also try to add it directly to the parent frame but the same.
Please Help me
I also had problems with a view in Relative layout thatwas dependent on the Relative layout's size.
I solved this problem problematically by updating the inner view size
private void updateViewSize()
if(rootContainer == null || rootContainer.getLayoutParams() == null)
return;
rootContainer.measure(View.MeasureSpec.makeMeasureSpec(ScalingUtil.getScreenSize().getWidth(), View.MeasureSpec.EXACTLY), View.MeasureSpec.makeMeasureSpec(ViewGroup.LayoutParams.WRAP_CONTENT, View.MeasureSpec.EXACTLY));
RelativeLayout.LayoutParams oldLayoutParams = (RelativeLayout.LayoutParams) rootContainer.findViewById(R.id.deals_card_center_bg).getLayoutParams();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(rootContainer.getMeasuredWidth(), rootContainer.getMeasuredHeight());
layoutParams.setMargins(oldLayoutParams.leftMargin, oldLayoutParams.topMargin, oldLayoutParams.rightMargin, oldLayoutParams.bottomMargin);
rootContainer.findViewById(R.id.deals_card_center_bg).setLayoutParams(layoutParams);
I'm tryin to draw a shape on a canvas under all buttons.
Here's the code:
Paint paint = new Paint();
paint.setColor(R.color.Kolor);
View view;
LayoutInflater inflater = (LayoutInflater)
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.menu_glowne, null);
Canvas can = new Canvas(Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888));
can.drawRect(0, 0, 200, 200, paint);
setContentView(view);
view.draw(can);
Don't know why I'm still getting the layout without anything drawn underneath.
Any ideas on what I'm doing wrong?
Thanx in advance!
In your example you are drawing the view on your canvas rather than on canvas of the view.
You should use a simple approach, don't inflate your layout but load it normally, then find the root container and set its background. Something like this:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Paint paint = new Paint();
paint.setColor(Color.MAGENTA);
Bitmap bgr = Bitmap.createBitmap(480, 800, Bitmap.Config.ARGB_8888);
Canvas can = new Canvas(bgr);
can.drawRect(50, 50, 200, 200, paint);
LinearLayout ll = (LinearLayout) findViewById(R.id.ll);
ll.setBackgroundDrawable(new BitmapDrawable(bgr));
}
main layout:
<?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"
android:id="#+id/ll">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello"
/>
</LinearLayout>
You don't draw this way in android. Everything happens through a method override (onDraw). Follow this tutorial to get started :
http://www.helloandroid.com/tutorials/how-use-canvas-your-android-apps-part-1
Regards,
Stéphane