Android how to draw several lines on an ImageView as another layer? - android

I would like to have the app draw several lines for showing user directions by using a background image as a base view and the app "draws" onto it in another layer on top of the background ImageView. Several lines would be made for the objectives to be met, and also in a specific location, so it has to have several layers too right??
I found a trick for drawing a single line using XML
<View
android:id="#+id/line"
android:layout_width="2dip"
android:layout_height="300dip"
android:background="#000000"
/>
But that code doesn't show positions and not in a layered form.
Update :
I would like the lines to appear through drawing, not through another picture

You can make a custom SurfaceView class, set the image as background and paint your lines on its Canvas. If I correctly understood what you want to achieve, that's probably the easiest way.
SurfaceView is a widget from the Android framework. Extend it to make your own: MySurfaceView extends SurfaceView. Then override public void onDraw(Canvas canvas), as android_user77 noted. Use this canvas object to paint on. Finally, add your class in the layout xml:
<com.your.app.MySurfaceView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/my_image" />
For details as why to use SurfaceView instead of View:
Difference between SurfaceView and View?

You can extend view and do the drawing by overriding the onDraw method

Use FrameLayout to create many "layers". I do not think you want to draw anything on the view. So do not use onDraw(), SurfaceView...
The code is like:
<FrameLayout ...>
<ImageView id="#+id/layer1"...>
<ImageView id="#+id/layer2"...>
</FrameLayout>

Related

Set background on SurfaceView

I’m developing an Android drawing app, using a SurfaceView (to be more specific it’s a class that extends SurfaceView). I already saw a lot of topics on this forum, but I didn’t get my answer.
My activity is basically a FrameLayout, which contains all of my views. I would like to set my SurfaceView on the lowest level of my FrameLayout, in order to see the upper elements (buttons, fragments, etc.). I also would like to set the background of my SurfaceView with a drawable but I’m facing problems.
I tried first to set the background of my SurfaceView itself and it works. Unfortunately, my painting content (canvas and bitmap) was overload by this background so I tried a second solution. I apply the drawable background to my FrameLayout, and I set my SurfaceView background as transparent, using setZOrderOnTop. My SurfaceView was indeed transparent, but my drawing stuff was above my buttons and fragments.
So my first question is: why do we need to setZOrderOnTop to get a transparent background? Then, how can I set a simple drawable background, keeping my structure hierarchy?
Thank’s for your answers!
XML View:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/mainFrame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/repeat_background"
tools:context=".MyActivity">
<!-- Option menu -->
<fragment ... />
<Button ... />
<Button ... />
<Button ... />
...
</FrameLayout>
#drawable/repeat_background
<?xml version="1.0" encoding="utf-8"?>
<bitmap xmlns:android="http://schemas.android.com/apk/res/android"
android:src="#drawable/drawing_font_texture"
android:tileMode="repeat" />
MyActivity
#Override
protected void onCreate(Bundle p_savedInstanceState) {
super.onCreate(p_savedInstanceState);
setContentView(R.layout.main_controller_activity);
// Getting my FrameLayout
FrameLayout mainFrame = (FrameLayout) findViewById(R.id.mainFrame);
// Instantiating my SurfaceView
this.drawableView = new MCustomDrawableView(getApplicationContext());
// Don't works
//setZOrderMediaOverlay(true);
this.drawableView.setZOrderOnTop(true);
this.drawableView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
FrameLayout.LayoutParams style = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT);
// Add the SurfaceView to the FrameLayout, on lowest position
mainFrame.addView(this.drawableView, 0, style);
}
I think your solution is on the right way. Set the background to the framelayout or add another layout under the surfaceview for your drawable. Then increase the z indices of the surfaceview AND the z indices of the buttons/elements that should be over the surfaceview,otherwise they are under it.
If you use material design, you can also set the elevation in dp for nice shadows.

Draw a line on top of existing layout programmatically

I have an existing layout that I am setting my current activity to. However, I want to draw a line (horizontal) and move it down in slow motion. Most articles talk about creating custom view and doing
setContentView(myView) .
How ever I dont want to set my activity view to only this view. I already did setContentView(R.layout.main). And I just want to draw the line on top of moving contents.
Something like drawLine(fromX, fromY, toX, toY) and then add a loop while increasing Y to show it in motion.
I hope I am clear. Please point me to the right direction.
Thank you
create a view and then animate it.
<View
android:id="+#id/ivHorizontalLine"
android:layout_width="match_parent"
android:layout_height="1px"
android:background="#000000" />
change the height of the view to match how thick you want the line to be. and the background color for the color of the line.
TranslateAnimation horizontalLineAnimation = new TranslateAnimation(0, 0, YstartPoint, YendPoint);
horizontalLineAnimation.setDuration(duration);
ivHorizontalLine.startAnimation(horizontalLineAnimation);
change YstartPoint and YendPoint to match where you want the line to move from and to. and the duration to match how fast you want the line to move.
The best way to do this is create a View that takes up the entire container that you would like to paint on top of. No background is necessary, as it is only to be used to create a canvas on it. An example would be like this:
<FrameLayout 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"
>
<com.packagename.PaintView
android:id="#+id/paintView"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</FrameLayout>
And PaintView would be a public class PaintView extends View

Draw a shape over a view

I have an activity with several ListViews in it. I need a rectangle with transparent background that overlaps some of the ListViews and I got lost a little.
I have some drawing coordinates that are known after all views are loaded and I want to put the graphics above the views programmatically.
Should I create a separate view that overlaps the activity window and draw on it or use the existing views? How do I start?
You can just add this in your layout xml:
<View android:id="#+id/view"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#android:color/transparent"/>
if you want views to overlaps another views use relative layout and build it correctly.

Sharing data with custom canvas view

I'm a beginner at android programming, so excuse me if my wording is slightly incorrect.
I have a custom canvas view along with a TextView inside a linear layout, defined in the layout file as
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
>
<TextView
android:id="#+id/blah"
android:layout_width="fill_parent"
android:layout_height="60dp"
android:gravity="top|center_horizontal"
/>
<com.*.Overlay android:id="#+id/combined"
android:layout_width="fill_parent"
android:layout_height="100dp"
/>
</LinearLayout>
I need to be able to read the text contained in the TextView from within the Overlay custom class that I created.
(The overlay class takes in 2 bitmaps and puts one on top of the other. The bitmaps used will depend on the text in the TextView.)
I considered using intents, but the Overlay class doesn't have an onCreate method.. All my code is within the onDraw method. I also added the necessary constructors.
I'm not sure what to try next, perhaps try accessing the parent linearlayout and then its child textview?
Hope I managed to explain everything in a non-confusing manner
Ok, managed to fix the issue... sort of
I found out that Views need to be contained in Activities.. so I created a new Activity with my custom view as an inner class, passed an intent with the necessary data to the activity and was able to use it successfully in my custom canvas view.
I was a bit surprised I didn't get any responses, but I guess that's because I'm new here

redundant onDraw() calls in FrameLayout

I have the following layout structure in my xml:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<MyEntireView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</MyEntireView>
<FrameLayout
android:id="#+id/focusedlayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom">
<MyDetailedView
android:id="#+id/focus"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
</MyDetailedView>
</FrameLayout>
</FrameLayout>
MyEntireView is a map (a Drawable) and MyDetailedView pops up on top of it upon onTouch() and contains only a certain piece of the whole map (also Drawable) that displays in greater detail the area which the user touched on the entire map in MyEntireView.
When MyDetailedView is shown - i.e. its setVisibility(View.VISIBLE) - there appear some transparent shapes (also some Bitmaps) on top and are redrawn regularly (e.g., 1 sec interval). The shapes are added dynamically as children of the #+id/focusedlayout as there is always a different number of them and their position is relevant to the detailed map picture.
And the problem is that each single update is processed multiple times. Each time a shape updates, then MyEntireView's onDraw() is called, MyDetailedView's onDraw() is called, and then these two are called again. And only after this the shape itself is invalidated.
As a result, this behaviour makes the shape flicker, since MyDetailedView redraws and hides the shape for 10ms or so.
I must probably be overlooking some simple logic, but I really can't get if there is a way to force only one View of a ViewGroup invalidate().
Or maybe there is an alternate structure/layout that I could use to fit my purpose?
Thanks a lot!
P.S.
The entire code is quite big to put here but I'm willing to insert any pieces upon request

Categories

Resources