How to avoid calling bringToFront() in onDraw of custom view? - android

I have a custom view as you can see in activity_main.xml. Right now it is hidden under the camera fragment. I want it to show up on top of it.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.snappiesticker.cwac4.StickerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
This is the class itself:
public class StickerView extends View {
Bitmap bitmap;
float x = 2;
float y = 2;
public StickerView(Context context, AttributeSet attrs) {
super(context,attrs);
bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.paunch);
}
#Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(bitmap, x, y, null);
// I wanted to put it here but that would cause the loop described below.
}
}
by loop, I mean: onDraw is called, which calls bringToFront, which asks the layout to be re-rendered. which calls onDraw, which calls bringToFront, etc. etc.
This is what I want to avoid.
This is instantiated in the mainActivity.
public class MainActivity extends Activity implements CameraHostProvider {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DemoCameraFragment current = new DemoCameraFragment();
getFragmentManager().beginTransaction()
.add(R.id.fragment_container, current)
.commit();
// can I somehow tell it to render the custom sticker view at the front here?
}
}

Did I understand correctly, you want to have your custom StickerView to remain on top of camera fragment? If that is the case you could simply refine your layout to something like this too ;
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<com.snappiesticker.cwac4.StickerView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Using this layout your camera fragment is added below StickerView and there's no need to call bringToFront() at all. If you use your root layout as fragment container the fragment is added after your custom view i.e above it.

Related

setContentView and buttons in Android

I have an Activity which has a button and by code I draw a Circle, so my Circle class is:
public class Circle extends View {
private float x = 100;
private float y = 100;
private float radius = 50;
public Circle(Context context) {
super(context);
}
protected void onDraw(Canvas canvas){
Paint paint = new Paint();
canvas.drawCircle(x, y, radius, paint);
}
}
And the code of my activity is:
public class AnotherTest extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Circle c = new Circle(this);
setContentView(c);
}
}
But when I invoke setContentView, the button seems to be deleted. Any tips to show the circle and preserve the button?
The button you mentioned is in your activity's layout XML file? If so, could you provide the code? setContentView() will only show the circle. If you want to add the circle to your existing layout you have to add it to a ViewGroup in your Activity's XML.
You could do something like this:
public class AnotherTest extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.anothertest_activity);
}
}
And the (res/layout/)anothertest_activity.xml file could look like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<your.package.Circle
android:id="#+id/myCircle"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
In Android Studio, right below the xml code are two tabs: "Design" and "Text". Switch to "Text" to paste code, switch back to "Design" to position your elements.
If you drag your views, you have an layout XML file. In the Activity you need to set this file as your content view, otherwise you wouldn't see your views. But you can add views dynamically by doing something like this:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:id="#+id/content"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/my_viewgroup"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/myButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
And in your Activity:
public class AnotherTest extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Still your xml with your button but without circle
setContentView(R.layout.anothertest_activity);
// First find your ViewGroup to add Views to
RelativeLayout viewGroup = (RelativeLayout) findViewById(R.id.my_viewgroup);
// Add a new circle to existing layout
viewGroup.addView(new Circle());
}
}
You also could add everything dynamically:
public class AnotherTest extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewGroup viewGroup = new LinearLayout(this);
setContentView(viewGroup);
viewGroup.addView(new Button());
viewGroup.addView(new Circle());
}
}
But I strongly recommend using xml layouts. Might want to take a look at Android Layouts

Android - Custom View and ImageView on XML but Custom View not visible

I try to use setContentView (R.layout.main) to display both an imageview and a Custom View. Somehow only the imageview can be shown but the Custom view is not visible (i.e. Bitmap ButtonStart not visible). I tested my code for onDraw and Texture class (responsible to load a bitmap object) somewhere else and it works fine. So I dunno what goes wrong...
Code for Custom view
public class TitleView extends View {
private Bitmap ButtonStart;
public TitleView (Context context, AttributeSet attrs) {
super (context, attrs);
Texture t2 = new Texture(context);
t2.loadFromAsset("button_Start.png");
ButtonStart = t2.getBitmap();
}
#Override
protected void onDraw (Canvas canvas) {
canvas.drawBitmap (ButtonStart, 0, 0, null);
}
}
MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature (Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.main_screen_image);
}
}
main_screen_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainScreenLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
>
<ImageView
android:id="#+id/mainScreenImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:scaleType="centerCrop"
android:src="#drawable/screenimage"
>
</ImageView>
<com.lowbband.chimera.TitleView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/titleview"/>
</LinearLayout>
With the code above, only screenimage was shown...
<ImageView
android:id="#+id/mainScreenImage"
android:layout_width="fill_parent"
android:layout_height="fill_parent" //it should be wrap_content otherwise it will take whole space
android:scaleType="centerCrop"
android:src="#drawable/screenimage"
>
</ImageView>
<com.lowbband.chimera.TitleView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/titleview"/>
And if the image is large and still fills the screen then put ScrollView outside LinearLayout

Draw a LinearLayout on SurfaceView

I have a class called Panel like this:
public class Test extends Activity{
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new Panel(this));
...
}
class Panel extends SurfaceView implements SurfaceHolder.Callback {
private LinearLayout layout;
public Panel(Context context) {
super(context);
layout = //get layout resource in layouts folder
}
public void onDraw(Canvas canvas) {
//I want to draw my xml layout
layout.draw(canvas);
}
}
I have tried to use LayoutInflater in order to get my layout:
LayoutInflater inflater = LayoutInflater.from(context);
layout = new LinearLayout(getApplicationContext());
inflater.inflate(R.layout.mylayout, layout);
... but I cant see anything on the screen, only a black background :S
as far as I know you can't draw a linear layout inside the SurfaceView you can draw anything you want in your SurfaceView if you want to add elements to your view like buttons or something like that I recommend using the XML and putting all your elements there. Something like this:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<SurfaceView android:id="#+id/mySurfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1">
</SurfaceView>
<Button android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true"
android:text="myButton"/>
</LinearLayout>
and then you may set your content of your view with setContentView(R.layout.my_xml);

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.

Android override onDraw() issue

I have a small issue here is the code i have so far:
public class MainActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(new GraphicView(this));
TextView mainLabel = (TextView)findViewById(R.id.title);
mainLabel.setText("Android Circle Path");
}
static class GraphicView extends View{
public GraphicView(Context context){
super(context);
}
#Override
public void onDraw(Canvas canvas){
}
}
}
And the main.xml file:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="30dip"
>
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="20dip"
android:layout_marginRight="20dip">
<TextView
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="20dip"
android:textSize="24.5sp"
android:id="#+id/title">
</TextView>
</LinearLayout>
</LinearLayout>
When i try to set the text in the onDraw() function the app crashes, what am i doing wrong?
A view's onDraw method should be used to render to that view alone. You should not be calling UI update methods in another view. Move the code for setting the title into your activity's onCreate method, since that only needs to be done once. Then just draw your circle in your custom view. Also, since your custom view does not implement ViewParent, it shouldn't be used to hold the title TextView. Reorganize your xml to move the title view outside the GraphicsView
TextView is a local variable created in the onCreate method of that Activity. So the scope of TextView is confined within that onCreate method only. You can't access it outside that method. Moreover what you are trying to do is not the right way, inside GraphView's onDraw method you are supposed to draw the GraphView components alone, not the outside views or anything else.

Categories

Resources