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));
Related
I have a menu activity that gets user setting of font and size and line spacing of text in all of TextView's, so i need a CustomTextView class to set these changes but my custom TextView does't work and give inflate Exception in logcat window. tank's a lot for your helps!
my CustomTextView:
package com.niloo.test2;
import android.content.Context;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.widget.TextView;
public class CustomTextView extends TextView {
Context context;
SharedPreferences shp = context.getSharedPreferences("text", Context.MODE_PRIVATE);
int size = shp.getInt("size", 22);
int fasle = shp.getInt("fasle", 1);
String font = shp.getString("font", "bmitra");
public CustomTextView(Context context) {
super(context);
if (!isInEditMode())
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
if (! isInEditMode())
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
if (!isInEditMode())
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
protected void onDraw (Canvas canvas) {
super.onDraw(canvas);
}
}
my XML code:
<com.niloo.test2.CustomTextView
android:id="#+id/tv_onv_amoozsh"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginTop="10dp"
android:layout_weight="0.5"
android:textColor="#color/sabz_lajani"
android:textSize="25sp"
android:textStyle="bold" />
<com.niloo.test2.CustomTextView
android:id="#+id/tv_num_amoozsh"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_gravity="center_vertical|center_horizontal"
android:layout_marginBottom="2dp"
android:layout_weight="0.75"
android:textColor="#color/sabz_lajani"
android:textSize="35sp" />
and my main class:
final CustomTextView tv_onv_amoozsh= (CustomTextView) findViewById(R.id.tv_onv_amoozsh);
tv_onv_amoozsh.setText("page");
final CustomTextView tv_num_amoozsh=(CustomTextView) findViewById(R.id.tv_num_amoozsh);
tv_num_amoozsh.setText(sfhe_num);
LogCat Error:
02-03 22:41:38.329: E/AndroidRuntime(19952): FATAL EXCEPTION: main
02-03 22:41:38.329: E/AndroidRuntime(19952): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.niloo.test2/com.niloo.test2.MainActivity}: android.view.InflateException: Binary XML file line #143: Error inflating class com.niloo.test2.CustomTextView
The problem is most likely that you're initializing shp, size, fasle, and font outside of the constructor. These initializations happen before any constructor code is run. context is never set and is null when getSharedPreferences is called on it.
Try this:
public class CustomTextView extends TextView {
private SharedPreferences shp;
private int size;
private int fasle;
private String font;
public CustomTextView(Context context) {
super(context);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
private void init(Context context) {
if (isInEditMode()) {
return;
}
shp = context.getSharedPreferences("text", Context.MODE_PRIVATE);
size = shp.getInt("size", 22);
fasle = shp.getInt("fasle", 1);
font = shp.getString("font", "bmitra");
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/" + font));
setTextSize(size);
setLineSpacing(fasle, 1);
}
}
Do you have this at the first view in your layout?
xmlns:custom="http://schemas.android.com/apk/res-auto"
Please post the full layout file (reduce it in your project to the minimum that is still failing. Maybe only have one view in it - your custom text )
EDIT:
The xml code you posted is invalid. Here is the fixed version that should work (do not omit "http://", remove semicolons)
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:custom="http://schemas.android.com/apk/res-auto"
android:id="#+id/linearLayout1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/sabzabi_kmrng"
android:gravity="top"
android:orientation="vertical"
tools:context="com.niloo.test2.MainActivity">
</LinearLayout>
The error is coming from this line:
setTypeface(Typeface.createFromAsset(context.getAssets(), "fonts/"+font));
Here we don't need to mention the keyword "fonts/" for path, because getAssets() method giving the route path of assets folder. So you can directly give font name like below:
setTypeface(Typeface.createFromAsset(context.getAssets(), font));
I want to pass some data to a custom class that extends android.view.View.
However, I get a warning message saying that :
Custom view LinePlot is missing constructor used by tools: (Context)
or (Context,AttributeSet) or (Context,AttributeSet,int)
However, I run the code and all seems to work smoothly.
What is happening?
How should I pass my data to my class?
Why can't I use a custom constructor?
Thanks!
import android.graphics.Canvas;
import android.graphics.Paint;
import android.view.View;
import java.util.ArrayList;
public class LinePlot extends View {
private ArrayList<Float> mPoints;
private int dx;
private int dy;
Paint paint=new Paint();
public LinePlot(Context context,int dx_plot, int dy_plot, ArrayList<Float> points) {
super(context);
mPoints=points;
dx=dx_plot;
dy=dy_plot;
}
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
// plotting my data here
}
}
so a couple of steps have to followed here -
(i) in values/attrs.xml add the following code -
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="NinjaView">
<attr name="addButtonBackgroundDrawable" format="integer"/>
</declare-styleable>
</resources>
(ii) call your custom view in you layout.xml file. For e.g. -
<com.example.act.ui.utils.NinjaView
android:id="#+id/ninja_view_product_desc"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
custom:addButtonBackgroundDrawable="#drawable/add_button_back_about_product"/>
(Don't forget to declare your custom namespace : xmlns:custom="http://schemas.android.com/apk/res-auto")
(iii) In your custom view's class you'll have to add a couple of things. Example -
public class NinjaView extends LinearLayout {
#BindView(R.id.button_add_to_cart_product) Button mAddToCart;
public NinjaView(Context context) {
super(context);
initializeNinjaView(context);
}
public NinjaView(Context context, AttributeSet attrs) {
super(context, attrs);
initializeNinjaView(context);
setAddButtonBack(context, attrs);
}
public NinjaView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initializeNinjaView(context);
setAddButtonBack(context, attrs);
}
private void initializeNinjaView(Context context) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.ninja_view, this);
}
#Override
protected void onFinishInflate() {
super.onFinishInflate();
ButterKnife.bind(this);
}
private void setAddButtonBack(Context context, AttributeSet attrs) {
TypedArray typedArray = context.getTheme().obtainStyledAttributes(attrs, R.styleable.NinjaView, 0, 0);
Drawable backgroundDrawable;
try {
backgroundDrawable = typedArray.getDrawable(R.styleable.NinjaView_addButtonBackgroundDrawable);
} finally {
typedArray.recycle();
}
if (backgroundDrawable != null) {
(findViewById(R.id.button_add_to_cart_product)).setBackground(backgroundDrawable);
}
}
The warning means you won't be able to use your custom view in any xml layout.
If you are not intended to do that it's still good to implement those constructors for your custom view like this:
CustomView(Context ctx) {
super(ctx)
}
Any additional attributes are normally passed as custom attributes not as constructor parameters. Read on custom view attribytes in the docs or elsewhere http://www.tutorialspoint.com/android/create_custom_attributes_for_custom_component.htm
In your LinePlot class add constructors:
public LinePlot(Context context) {
super(context);
}
public LinePlot(Context context, AttributeSet attrs) {
super(context, attrs);
}
you need to add constructors with parameters
(Context), (Context,AttributeSet) and (Context,AttributeSet,int)
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);
I write a simple extend view class,the code is following:
public class MyView extends View
{
public MyView(Context context)
{
super(context);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
protected void OnDraw(Canvas canvas)
{
super.onDraw(canvas);
}
}
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" >
<com.main.sufaceview.MyView
android:id="#+id/myview"
android:layout_width="300dp"
android:layout_height="300dp"
android:background="#drawable/tt"/>
</RelativeLayout>
When entry the virtual machine. It shows the breakdown:
why this is? i think the custom view should very easy.I did not add other code,it has the error.
Edit:the logcat displays:
I think you need another constructor, at least, thats what I read in other posts.
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
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);
}
}