How to draw vertical line between two buttons in android - android

I have a simple linear layout. I am adding button dynaically through code one below other with some space in between. I need to draw a vertical line between those two buttons (Vertical arrow headed line in specific).
Could you please let me know how to draw a vertical line from buttom of button1 to top of button2.
I used DrawLine() to draw a line but its getting drawn below button2 with some offset.
Here is my code:
import android.app.ActionBar.LayoutParams;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
public class SampleMethodActivity extends Activity {
Button b,b1;
public int width,height,bottom;
LinearLayout ll;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sample_method);
ll = (LinearLayout) findViewById(R.id.my_linear_layout);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
params.setMargins(0, 12, 0, 40);
b = new Button(this);
b.setText("This is a sample text");
b.setLayoutParams(params);
b.setGravity(Gravity.CENTER);
ll.addView(b);
b1 = new Button(this);
b1.setText("This is a sample text to chck the width and height of a button1 and need to check how long it gets stretched and to check the width");
b1.setLayoutParams(params);
b1.setGravity(Gravity.CENTER);
ll.addView(b1);
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
width = b.getWidth();
height = b.getHeight();
bottom = b.getBottom();
DrawView dv = new DrawView(this,width/2,bottom);
ll.addView(dv);
}
}
Below is DrawView class:
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.view.View;
public class DrawView extends View {
Paint paint = new Paint();
int x,y;
public DrawView(Context context,int x,int y) {
super(context);
this.x=x;
this.y=y;
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(3);
System.out.println("X: "+x);
canvas.drawLine(x, y, x, y+400, paint);
}
}

Drawing a Line with View
If you only need a straight horizontal or vertical line, then the easiest way may be to just use a View in your xml layout file. You would do something like this:
<View
android:layout_width="1dp"
android:layout_height="match_parent"
android:background="#android:color/black" />
Set first button gravity to left and other to right and in between them add a view in between them and set it's gravity to center.
Second Way
Add button (weight 45) view(10) button2(weight45) and you are done.
and you can also create an xml and inflate it to LinearLayout.
For vertical line width to 1dp and for horizontal line height to 1dp

Add this to colors.xml
<color name="streat_line">#D0D5D8</color>
apply this where you want to create a line
<TextView
android:id="#+id/TextView"
android:layout_width="1dp"
android:layout_height="wrap_content"
android:background="#color/streat_line" >

Related

How to get HorizontalScrollView to scroll with one custom View child

I'm not quite sure how to ask this but I need a scrollview that will scroll with an amplitude visualizer as it records audio. EDIT: To be clear, the ScrollView is not scrolling even with touches and gestures.
Here's a screenshot of the app with the custom view. The red bars show the average amplitude of a second.
The bars fill from left to right, but when it reaches the edge it does not scroll.
Here's the XML for the HorizontalScrollView and the AudioVisualizer view:
<HorizontalScrollView
android:id="#+id/hsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<com.blueteam.audiotes.AudioVisualizer
android:id="#+id/visualizer"
android:layout_width="match_parent"
android:layout_height="200dp" />
</HorizontalScrollView>
Here's the code for the AudioVisualizer element:
package com.blueteam.audiotes;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
/**
* Created by tanner on 3/21/17.
*/
public class AudioVisualizer extends View {
private final int BAR_WIDTH = 10;
private final int BAR_STARTING_POINT = 0;
private final int BAR_SPACE = 2;
private final int BAR_BOTTOM = 200;
private final int BAR_MINIMUM_HEIGHT = 20;
private ArrayList<Rect> bars;
private Paint paint;
private ArrayList<Tag> tags;
public AudioVisualizer(Context context, AttributeSet attrs) {
super(context, attrs);
bars = new ArrayList<Rect>();
paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
for(Rect r : bars)
canvas.drawRect(r.left, r.top, r.right, r.bottom, paint);
}
public void addBar(int height) {
if (height < BAR_MINIMUM_HEIGHT)
height = BAR_MINIMUM_HEIGHT;
else if (height > BAR_BOTTOM)
height = BAR_BOTTOM;
bars.add(new Rect(BAR_STARTING_POINT + bars.size() * (BAR_SPACE + BAR_WIDTH),
BAR_BOTTOM - height,
(BAR_STARTING_POINT + bars.size() * (BAR_SPACE + BAR_WIDTH)) + BAR_WIDTH,
BAR_BOTTOM));
}
}
I tried setting the AudioVisualizer width to something like 2000 just to see if it would scroll when the child was clearly larger than the ScrollView, but it still didn't work.
I'm guessing I'm missing something simple.
Change your xml like this:
<HorizontalScrollView
android:id="#+id/hsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<com.blueteam.audiotes.AudioVisualizer
android:id="#+id/visualizer"
android:layout_width="wrap_content"
android:layout_height="200dp" />
</HorizontalScrollView>
And whenever you addBar do this:
audioVisualizer.addBar(10);
parentHsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
I solved it. I didn't override onMeasure. Here's my code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = (BAR_WIDTH + BAR_SPACE) * bars.size();
setMeasuredDimension(width, MeasureSpec.getSize(heightMeasureSpec));
}
I also needed to call v.requestLayout() before v.invalidate() to update the size.

Android: How to create custom view

I have to create a custom view to show a little graph on Android. There are a lot of tutorials but they didn't help me. They are full of resource handling, performance optimizations etc.
But I fail at the simplest thing: The view is not visible. Neither in Android Studio, nor in the running app.
Here my approach:
/home/thomas/dev/AndroidStudioProjects/Test/app/src/main/java/clear/test/MainActivity.java:
package clear.test;
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
/home/thomas/dev/AndroidStudioProjects/Test/app/src/main/java/clear/test/MyView.java:
package clear.test;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
public class MyView extends View {
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(0xFF0000);
canvas.drawLine(0, 0, getMeasuredWidth(), getMeasuredHeight(), paint);
canvas.drawLine(getMeasuredWidth(), 0, 0, getMeasuredHeight(), paint);
}
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(500, 500);
}
}
/home/thomas/dev/AndroidStudioProjects/Test/app/src/main/res/layout/activity_main.xml:
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<clear.test.MyView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/view"
android:layout_alignParentTop="true"
android:layout_alignParentStart="true" />
</RelativeLayout>
Your problem is that you use wrap_content for your view but do not implement the measure functions
1) Your view is "visible" but its height and width is 0 because of wrap_content in activity_main.xml. Try to set some absolute values or match_parent.
2) Do NOT create new instances of Paint in every call of onDraw. It`s useless.
3) If you want to define custom view both by java and xml (or I don't understand existence of file sample_my_view.xml), look for View's method inflate().
I found my problem:
Color is 32 bit. Red must be 0xFFFF0000, not 0xFF0000.

Strange behavior with Android view.invalidate()

I have 3 custom views placed vertically in a LinearLayout, they are used to display different dynamic info, so they're supposed be invalidated and redrawn at different time. But I found the view invalidation is out of usual expectation, that is: if you invalidate the top view,all 3 views are invalidated at the same time, if you invalidate the middle view, the middle and bottom views are invalidated, the top one is not, if you invalidate the bottom view, only the bottom view itself is invalidated, this is what I want, so what happened with the first 2 cases ? I searched and got similar questions like:
https://stackoverflow.com/questions/26192491/invalidate-one-view-force-other-views-invalidate-too-how-separating-that
Android Invalidate() only single view
but it seems no exact answer. I post my code here, any comment is appreciated.
TestView.java
package com.vrb.myview;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
public class TestView extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void onTest(View view){
MyView1 mv1 = (MyView1)findViewById(R.id.mv1);
MyView1 mv2 = (MyView1)findViewById(R.id.mv2);
MyView1 mv3 = (MyView1)findViewById(R.id.mv3);
mv1.invalidate(); // all 3 views are invalidated
// mv2.invalidate(); // mv2 and mv3 are invalidated
// mv3.invalidate(); // only mv3 is invalidated,this is what I want
}
}
MyView1.java
package com.vrb.myview;
import java.util.Random;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
public class MyView1 extends View {
Rect rc=null;
Paint p=null;
Random r;
public MyView1(Context ctx){
super(ctx);
rc = new Rect();
p = new Paint();
r = new Random();
}
public MyView1(Context ctx, AttributeSet set){
super(ctx, set);
rc = new Rect();
p = new Paint();
r = new Random();
}
public void onDraw(Canvas canvas){
if(canvas.getClipBounds(rc)){
Log.d("MyView1","id="+getId()+" Rect: "+rc.left+","+rc.top+","+rc.right+","+rc.bottom);
p.setColor(Color.argb(0xff, Math.abs(r.nextInt())%255, Math.abs(r.nextInt())%255, Math.abs(r.nextInt())%255));
canvas.drawRect(rc, p);
}else{
Log.d("MyView1","id="+getId()+" Rect=null");
}
}
}
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:id="#+id/root"
android:orientation="vertical"
tools:context="com.vrb.myview.TestView" >
<com.vrb.myview.MyView1
android:layout_width="match_parent"
android:layout_height="100px"
android:id="#+id/mv1" />
<com.vrb.myview.MyView1
android:layout_width="match_parent"
android:layout_height="100px"
android:id="#+id/mv2" />
<com.vrb.myview.MyView1
android:layout_width="match_parent"
android:layout_height="100px"
android:id="#+id/mv3" />
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Invalidate"
android:onClick="onTest"
android:id="#+id/btn" />
</LinearLayout>
You shouldn't rely on the count or the time of the calls to onDraw() for the internal state of your View. Move the p.setColor() call to a separate public method, and call invalidate() at the end of it. For example:
public class MyView1 extends View {
...
public void changePaint() {
p.setColor(Color.argb(0xff, Math.abs(r.nextInt()) % 255, Math.abs(r.nextInt()) % 255, Math.abs(r.nextInt()) % 255));
invalidate();
}
}
Then in your onTest() method:
public void onTest(View view) {
MyView1 mv1 = (MyView1)findViewById(R.id.mv1);
...
mv1.changePaint();
...
}

Redraw canvas in Android

I am making an Android 2.2 application using Eclipse. My application should draw
images by clicking on buttons.
I have two buttons at the bottom of the screen, and I need to draw the shape in the same screen that has the buttons. I used FrameLayout in which the shapes are drawn.
My problem is, the two shapes are overwriting, so I need to redraw the canvas.
My Code
package draw.tab;
import android.app.Activity;
//import android.graphics.Color;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.FrameLayout;
public class DrawActivity extends Activity implements OnClickListener
{
DrawView drawview;
CircleView circleView;
FrameLayout Frame;
Button square,circle;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Frame=(FrameLayout)findViewById(R.id.MyFrame);
drawview=new DrawView(this);
circleView=new CircleView(this);
square=(Button)findViewById(R.id.buttonTest);
square.setOnClickListener(this);
circle=(Button)findViewById(R.id.circleButton);
circle.setOnClickListener(this);
}
public void onClick(View v)
{
switch (v.getId()) {
case R.id.circleButton:
Frame.addView(circleView);
/*circleView.setBackgroundColor(Color.rgb(40,100,20));
circleView.findViewById(R.id.CircleViewId);
setContentView(circleView);*/
break;
case R.id.buttonTest:
Frame.addView(drawview);
/*drawview.setBackgroundColor(Color.WHITE);
drawview.findViewById(R.id.DrawViewId);
drawview.layout(400,0,200,450);
setContentView(drawview);*/
break;
}
}
}
DrawView.java
package draw.tab;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
public class DrawView extends View
{
Paint paint=new Paint();
Path pat=new Path();
public DrawView(Context context)
{
super(context);
paint.setColor(Color.RED);
paint.setStyle(Style.STROKE);
//context.clearRect(70,140,400,450);
//pat.addRect(50,40,250,400,Path.Direction.CW);
}
public DrawView(Context con,AttributeSet atts)
{
super(con,atts);
}
#Override
public void onDraw(Canvas canvas)
{
//canvas.drawPath(pat,paint);
canvas.drawLine(20,40,450,40,paint);//horizontal top
canvas.drawRect(70,140,400,450,paint);
canvas.drawLine(20,40,20,600,paint);//vertical left
canvas.drawLine(20,600,450,600,paint);//horizontal bottom
canvas.drawLine(450,40,450,600,paint);//vertical right
//this.invalidate();
}
}
CircleView.java
package draw.tab;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.util.AttributeSet;
import android.view.View;
public class CircleView extends View
{
Paint p=new Paint();
Path path=new Path();
public CircleView(Context context)
{
super(context);
p.setColor(Color.BLUE);
p.setStyle(Style.STROKE);
//path.addCircle(250,250,50,Path.Direction.CW);
}
public CircleView(Context con,AttributeSet atts)
{
super(con,atts);
}
public void onDraw(Canvas c)
{
//c.drawPath(path,p);
//c.save();
c.drawLine(20,40,450,40, p);//horizontal top
c.drawCircle(250,350,100,p);
c.drawLine(20,40,20,600,p);//vertical left
c.drawLine(20,600,450,600,p);//horizontal bottom
c.drawLine(450,40,450,600,p);//vertical right
//c.restore();
this.invalidate();
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:visibility="visible"
android:id="#+id/MyFrame"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<draw.tab.DrawView
android:id="#+id/DrawViewId"
android:layout_width="320dp"
android:layout_height="600dp">
</draw.tab.DrawView>
<draw.tab.CircleView
android:id="#+id/CircleViewId"
android:layout_width="320dp"
android:layout_height="600dp">
</draw.tab.CircleView>
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal"
android:gravity="bottom">
<Button
android:layout_height="wrap_content"
android:text="Circle"
android:id="#+id/circleButton"
android:layout_width="160dp">
</Button>
<Button
android:layout_height="wrap_content"
android:text="Square"
android:id="#+id/buttonTest"
android:layout_width="160dp">
</Button>
</LinearLayout>
</FrameLayout>
The above is all my code. The shapes are overwriting, so I want to remove and redraw the canvas or redraw without overwriting.
Try calling invalidate() on your view.
Call canvas.save() then do drawing then call canvas.restore(). Also depends on the bitmaps you are drawing. The bitmaps should have a transparent background.
Edit
Call canvas.drawColor(Color.White); //Or whichever bg color before drawing the bitmap.
Edit
In drawview try this
canvas.drawRect(getLeft(), getTop(), getright() , getBottom() ,paint);
Similarly in CircleView
canvas.drawCircle(getLeft()+getwidth()/2, getTop()+getheight()/2, 100, paint);
One last try. Set children gravity..
<draw.tab.DrawView
android:id="#+id/DrawViewId"
android:layout_width="320dp"
android:layout_height="600dp"
android:layout_gravity="left">
</draw.tab.DrawView>
<draw.tab.CircleView
android:id="#+id/CircleViewId"
android:layout_width="320dp"
android:layout_height="600dp"
android:layout_gravity="right">
</draw.tab.CircleView>

Shape Drawable View in XML

I'm using the shapedrawable example word for word (nearly) and can't seem to call a shapedrawable class in xml. The only extra step stated by the documentation was to override the View(Context, AttributeSet), which I think I did. The docs I'm referring to are here: http://developer.android.com/guide/topics/graphics/2d-graphics.html Here is my code.
AndroidTest.java
package com.android.test;
import android.app.Activity;
import android.os.Bundle;
public class AndroidTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
ShapeSquare.java
package com.android.test;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.view.View;
public class ShapeSquare extends View {
private ShapeDrawable mDrawable;
public ShapeSquare(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);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
main.xml
<?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"
>
<com.android.test.shapedrawable.ShapeSquare
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
The error is a force quit error and I can't figure out where the problem lies. The shape properties will be dictated by user input (eventually), so the shape needs to be created in a class as opposed to all xml.
Figured out the problem here. I had to remove "shapedrawable" from:
<com.android.test.shapedrawable.ShapeSquare
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
Apparently, that was just the location of the demo. I thought it was referencing the class somehow.

Categories

Resources