I'm trying to implement a custom SurfaceView in my activity's XML file, and then reference it within the activity's code for drawing etc. However, I'm getting the following error:
The following classes could not be instantiated:
- com.example.animateddrawable.MainActivity.DrawingPanel
MainActivity Code:
package com.example.animateddrawable;
import java.util.Timer;
import java.util.TimerTask;
import android.app.Activity;
import android.content.Context;
...
com.example.animateddrawable.MainActivity.DrawingPanel.PanelThread;
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dp = new DrawingPanel(this, null);
setContentView(R.layout.activity_main);
}
public class DrawingPanel extends SurfaceView implements SurfaceHolder.Callback {
public DrawingPanel( Context context, AttributeSet attributeSet){
super(context, attributeSet);
init();
}
public void init(){
getHolder().addCallback(this);
}
}
}
XML Code
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent" >
<com.example.animateddrawable.MainActivity.DrawingPanel
android:id="#+id/surfaceView"
android:layout_width = "fill_parent"
android:layout_height = "fill_parent"/>
</FrameLayout>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1" >
</LinearLayout>
Any ideas?
try to add a constructor like this:
public DrawingPanel(Context context) {
super(context);
getHolder().addCallback(this);
}
public DrawingPanel(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
getHolder().addCallback(this);
}
add this to your other constructer as well:
getHolder().addCallback(this);
Related
I have 3 views:
GLSurfaceView
Custom SurfaceView
View
The GLSurfaceView is at the bottom
The Custom SurfaceView should be above and on the top
The View is above and on the bottom
This is my code:
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
public class MainActivity extends AppCompatActivity {
GameGlSurfaceView gameGlSurfaceView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
gameGlSurfaceView = new GameGlSurfaceView(this);
setContentView(gameGlSurfaceView);
View hudView = getLayoutInflater().inflate(R.layout.activity_main, null);
addContentView(hudView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT));
View inpudPadView = getLayoutInflater().inflate(R.layout.input_pad, null);
LinearLayout.LayoutParams inpudPadViewParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
inpudPadViewParams.gravity = Gravity.TOP;
addContentView(inpudPadView, inpudPadViewParams);
}
}
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class SurfacePanel extends SurfaceView implements SurfaceHolder.Callback {
Context context;
Bitmap bitmapTest;
MyThread mythread;
public SurfacePanel(Context ctx, AttributeSet attrSet ) {
super(ctx, attrSet);
context = ctx;
bitmapTest = Bitmap.createBitmap(200, 100, Bitmap.Config.ARGB_8888);
bitmapTest.eraseColor(Color.TRANSPARENT);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
}
void doDraw(Canvas canvas) {
canvas.drawColor(Color.GREEN);
canvas.drawBitmap(bitmapTest, 50, 10, null);
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
mythread = new MyThread(holder, context,this);
mythread.setRunning(true);
mythread.start();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
mythread.setRunning(false);
boolean retry = true;
while(retry) {
try {
mythread.join();
retry = false;
}
catch(Exception e) {
}
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="de.batechniks.surfaceviewtest.MainActivity">
<de.batechniks.surfaceviewtest.SurfacePanel
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
android:text="Large Text"
android:id="#+id/textView"/>
</RelativeLayout>
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false"
xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="left">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/bt_down"
android:src="#mipmap/ic_launcher"
android:layout_gravity="bottom"/>
</LinearLayout>
The result is: I can see the GLSurfaceView and i can see the view above on the bottom.
On the top, i only see the textview "Large Text". The SurfaceView is not shown.
When i uncomment setContentView(gameGlSurfaceView), the SurfaceView is shown.
The main problem is to show the SurfaceView, the second problem will be to get the SurfaceView transparent.
Thanks a lot
You need to call the method
this.setZOrderOnTop(true);
in your constructors.
It's recommended to do constructors in custom views like this
public SurfacePanel (Context context) {
super(context);
init();
}
public SurfacePanel (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public SurfacePanel (Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
#TargetApi(21)
public SurfacePanel (Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
init();
}
private void init() {
if(!isInEditMode()) {
this.setZOrderOnTop(true);
}
}
Here is my code for class test.java
package com.example.testdroid;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.widget.TextView;
public class test extends TextView{
public test(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.setText("Hello World");
this.setTextSize(20f);
this.setTextColor(Color.RED);
}
protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
}
}
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:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity" >
<com.example.testdroid.test
android:id="#+id/test1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#+id/button1"
android:layout_alignRight="#+id/button1"
android:layout_marginBottom="68dp"
/>
</RelativeLayout>
Logcat :
FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.testdroid/com.example.testdroid.MainActivity}: android.view.InflateException: Binary XML file line #25: Error inflating class com.example.testdroid.test
Create a class for textview like as follow:-
public class TextViews extends TextView{
public TextViews (Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
public TextViews (Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public TextViews (Context context) {
super(context);
init();
}
private void init() {
if (!isInEditMode()) {
this.setText("Hello World");
this.setTextSize(20f);
this.setTextColor(Color.RED);
}
}
}
This seems like a simple thing, but it does not run. What am I doing wrong?
I'm subclassing ImageView, but if I put it inside XML layouts, it gives:
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.myappSubclass/com.example.myappSubclass.MyActivity}:
android.view.InflateException: Binary XML file line #21: Error
inflating class com.example.myappSubclass.ImageViewSubclass
Here is my code:
package com.example.myappSubclass;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.ImageView;
import java.util.jar.Attributes;
/**
* Created by me on 2014-07-11.
*/
public class ImageViewSubclass extends ImageView {
public Context thisContext;
public ImageViewSubclass(Context context, AttributeSet attrs, Context thisContext) {
super(context, attrs);
this.thisContext = thisContext;
}
public ImageViewSubclass(Context context, AttributeSet attrs, int defStyle, Context thisContext) {
super(context, attrs, defStyle);
this.thisContext = thisContext;
}
public ImageViewSubclass(Context context) {
super(context);
this.thisContext = context;
}
public void changeImage(){
this.setImageLevel(0);
}
And inside the XML I have it simply:
<?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:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Hello World, MyActivity"
/>
<Button android:layout_width="match_parent" android:layout_height="50dp"
android:layout_marginLeft="50dp"
android:layout_marginRight="50dp"
android:text="Test"
/>
<com.example.myappSubclass.ImageViewSubclass android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<!--<ImageView android:layout_width="fill_parent" android:layout_height="fill_parent"/>-->
</LinearLayout>
Custom views must have predefined constructors to be able to inflate them from an XML layout. You should remove thisContext from all of them.
public ImageViewSubclass(Context context) {
super(context);
...
}
public ImageViewSubclass(Context context, AttributeSet attrs) {
super(context, attrs);
...
}
public ImageViewSubclass(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
...
}
Why did you add that extra parameter anyway? All views have a getContext() method if that's what you needed.
New to Android development, and I'm having trouble doing a simple drawing to a view using a canvas.
From what I've understood, something like this:
import android.content.Context;
import android.graphics.Canvas;
import android.view.View;
public class DrawView extends View
{
public DrawView(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
canvas.drawRGB(255,0,0);
}
}
With this as my Activity:
public class Prototype1 extends Activity
{
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
And this for the 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"
>
<com.dhs2.prototype1.DrawView
android:id="#+id/map"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
</LinearLayout>
Should just draw red everywhere, but instead I just get a blank screen.
Any idea where I'm going wrong?
Since you added your custom view in an XML layout file, you should add 2 more constructors:
public DrawView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public DrawView(Context context, AttributeSet attrs) {
super(context, attrs);
}
This is because you pass some attributes to the view, like fill_parent, wrap_content, so the constructor public DrawView(Context context) won't be called.
This would work however, if you won't declare your custom view in the XML layout file, but setting it directly from the onCreate() like this:
setContentView(new DrawView(this));
I have a GraphicsView class that extends from the View class and I want to add this GraphicsView class to the main layout in my project. How can I do that?
static public class GraphicsView extends View {
public GraphicsView(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
// Drawing commands go here
Path rect = new Path();
rect.addRect(100, 100, 250, 50, Direction.CW);
Paint cPaint = new Paint();
cPaint.setColor(Color.LTGRAY);
canvas.drawPath(rect, cPaint);
}
}
and my main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/linnnnlayout"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<TextView
android:id="#+id/Customfont"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
<View
android:id="#+id/view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
</LinearLayout>
You need to give complete path of your class that extends View,
<com.blah.blah.GraphicsView
android:id="#+id/view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
If I remember correctly, you need to provide more constructors to use view from xml file (add it to xml file like "Me and We" suggested).
public GraphicsView(Context context) {
super(context);
}
public GraphicsView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public GraphicsView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
Update: fixed code.
i finaly got it here is the code
the XML code
<com.customfonts.namespace.BreakDownBar
android:id="#+id/gview"
android:layout_width="fill_parent"
android:layout_height="20dip"
android:layout_marginLeft="10dip"
android:layout_marginRight="10dip"
android:background="#color/BreakDownBarBack"/>
and the class
package com.customfonts.namespace;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Path.Direction;
import android.util.AttributeSet;
import android.view.View;
public class BreakDownBar extends View {
public BreakDownBar(Context context, AttributeSet attrs) {
super(context, attrs);
}
#Override
protected void onDraw(Canvas canvas) {
//Draw rectangle;
Path rect = new Path();
rect.addRect(0, 0,250, 150,Direction.CW);
Paint cpaint = new Paint();
cpaint.setColor(Color.GREEN);
canvas.drawPath(rect, cpaint);
}
}
you need to do this:
LinearLayout v = (LinearView) findViewById(R.id.linnnnlayout);
GraphicsView myView = new myGraphicsView(this);
v.addView(myView);
Because your custom View is an inner class in your Activity the java compiler will output the name ActivityName$GraphicsView for that class. You can't use that name directly as the View name in the xml layout because of the $ character but you can do it like this:
<view
class="com.package.here.ActivityName$GraphicsView"
android:id="#+id/view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
where ActivityName is the name of the activity where your GraphicsView class is declared.
public class MainActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout v = (LinearLayout) findViewById(R.id.linearLayout);
MyGraphics myView = new MyGraphics(this);
v.addView(myView);
}
}
public class MyGraphics extends View {
public MyGraphics(Context context) {
super(context);
}
#Override
protected void onDraw(Canvas canvas) {
// Drawing commands go here
Path rect = new Path();
rect.addRect(100, 100, 250, 50, Direction.CW);
Paint cPaint = new Paint();
cPaint.setColor(Color.LTGRAY);
canvas.drawPath(rect, cPaint);
}
}
XML:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:id="#+id/linearLayout">
<TextView
android:id="#+id/Customfont"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="#string/hello" />
</LinearLayout>
This is working for me and add the view in XML with full path and try giving wrapcontent for height and width.
public class RectangleView extends View {
public RectangleView(Context context) {
super(context);
}
public RectangleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public RectangleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint();
paint.setColor(Color.GRAY);
canvas.drawColor(Color.BLUE);
canvas.drawRect(10,10,50,50, paint);
}
}