1

I'm new to android development and really struggling with using a custom view. I've read a lot of stuff on SO and its been really helpful with everything else, I just cant seem to work this one out. You guys are very smart and know your stuff so well. I hope to one day give back on SO as opposed to always taking! Any help would be very much appreciated. Thanks.

activity_display_message.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"
>
    <TextView  
        android:layout_width="fill_parent" 
        android:layout_height="wrap_content" 
        android:text="@string/share"
    />
    <view class="me.myfirstapp.DisplayMessageActivity$MyView"
        android:layout_width="150dp"
        android:layout_height="100dp"
    />

DisplayMessageActivity.java

package me.myfirstapp;
import android.os.Bundle; 
import android.app.Activity;
import android.util.AttributeSet;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ShareActionProvider;
import android.support.v4.app.NavUtils;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.os.Build;

@SuppressLint({ "NewApi", "DrawAllocation" }) public class DisplayMessageActivity extends Activity {

@SuppressLint("NewApi")
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_display_message);

    // Make sure we're running on Honeycomb or higher to use ActionBar APIs
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        // Show the Up button in the action bar.
        getActionBar().setDisplayHomeAsUpEnabled(true);
    }

}

public class MyView extends View {

    private int mWidth;
    private int mHeight;

    public MyView(Context context) {
         super(context);
    }

    public MyView(Context context, AttributeSet attribs) {
        super(context, attribs);
    }

    public MyView(Context context, AttributeSet attribs, int defStyle) {
        super(context, attribs, defStyle);
    }

    @Override        
    protected void onDraw(Canvas canvas) {

       super.onDraw(canvas);
       Paint paint = new Paint();

       Bitmap b1=BitmapFactory.decodeResource(getResources(), R.drawable.logolong);
       b1 = Bitmap.createScaledBitmap(b1, 100, 20, false);
       canvas.drawBitmap(b1, 600, 880, paint);

       Typeface tf = Typeface.createFromAsset(getAssets(), "fonts/regencielight.TTF");
       paint.setTypeface(tf);
       paint.setColor(Color.parseColor("#ffffff"));
       paint.setTextSize(46);
       canvas.drawText(message, x1, 880, paint);

       }  

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            mWidth = View.MeasureSpec.getSize(widthMeasureSpec);
            mHeight = View.MeasureSpec.getSize(heightMeasureSpec);
            setMeasuredDimension(mWidth, mHeight);
        }

   }


@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        NavUtils.navigateUpFromSameTask(this);
        return true;
    }
    return super.onOptionsItemSelected(item);
}

}

logcat output

03-15 21:14:23.382: E/AndroidRuntime(25443): FATAL EXCEPTION: main
03-15 21:14:23.382: E/AndroidRuntime(25443): Process: me.myfirstapp, PID: 25443
03-15 21:14:23.382: E/AndroidRuntime(25443): java.lang.RuntimeException: Unable to start     activity ComponentInfo{me.myfirstapp/me.myfirstapp.DisplayMessageActivity}:     android.view.InflateException: Binary XML file line #12: Error inflating class     me.myfirstapp.DisplayMessageActivity$MyView
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2195)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2245)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.ActivityThread.access$800(ActivityThread.java:135)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.os.Handler.dispatchMessage(Handler.java:102)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.os.Looper.loop(Looper.java:136)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.ActivityThread.main(ActivityThread.java:5017)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at java.lang.reflect.Method.invokeNative(Native Method)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at java.lang.reflect.Method.invoke(Method.java:515)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at dalvik.system.NativeStart.main(Native Method)
03-15 21:14:23.382: E/AndroidRuntime(25443): Caused by: android.view.InflateException: Binary XML file line #12: Error inflating class me.myfirstapp.DisplayMessageActivity$MyView
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.view.LayoutInflater.createView(LayoutInflater.java:603)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:696)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.view.LayoutInflater.inflate(LayoutInflater.java:492)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.view.LayoutInflater.inflate(LayoutInflater.java:397)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.view.LayoutInflater.inflate(LayoutInflater.java:353)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:290)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.Activity.setContentView(Activity.java:1929)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at me.myfirstapp.DisplayMessageActivity.onCreate(DisplayMessageActivity.java:44)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.Activity.performCreate(Activity.java:5231)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2159)
03-15 21:14:23.382: E/AndroidRuntime(25443):    ... 11 more
03-15 21:14:23.382: E/AndroidRuntime(25443): Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]
03-15 21:14:23.382: E/AndroidRuntime(25443):    at java.lang.Class.getConstructorOrMethod(Class.java:472)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at java.lang.Class.getConstructor(Class.java:446)
03-15 21:14:23.382: E/AndroidRuntime(25443):    at android.view.LayoutInflater.createView(LayoutInflater.java:568)
03-15 21:14:23.382: E/AndroidRuntime(25443):    ... 22 more
5
  • Normally that exception means it can't find a constructor that takes a Context and an AttributeSet, or that the function isn't public.That doesn't seem to be the case here though. Commented Mar 16, 2014 at 4:29
  • 1
    Try making the MyView class static, or define it in it's own source file. I'm not certain that will fix the problem, but try it out and let us know the result. Commented Mar 16, 2014 at 4:38
  • Also this is unrelated, but you should not be creating a new Paint object, constructing new bitmaps, or creating typefaces from assets in the onDraw() method, especially since in your case the results are always the same. Make each of your constructors call a private initialization method and do the processing there. onDraw() should only have to draw the result. Commented Mar 16, 2014 at 4:46
  • @Karakuri - Thanks for replying. Making MyView class static worked, though it created errors for getIntent() and getAssets(). Error is "Cannot make a static reference to the non-static method getIntent() from the type Activity". I guess this may be fixed by trying your second suggestion about removing from onDraw()? Commented Mar 17, 2014 at 2:34
  • You can use getContext().getAssets() inside your custom view. And yes, I highly recommend doing that work only once -- that typeface isn't going to change between draws, for instance, so why read it more than once? (Even if you want to support setting a different typeface, you can make a method for that and call invalidate() at the end of that method.) Commented Mar 17, 2014 at 6:02

3 Answers 3

1

I am sure that you are missing one of the constructor whenever you are creating a customView you have to override these constuctor And after seeing you stacktrace.

 Caused by: java.lang.NoSuchMethodException: <init> [class android.content.Context, interface android.util.AttributeSet]

// this above consturctor is misssing

Note: And also override onMeasure while creating custom View . it is mandatory

It's not mandatory, and most times you don't even have to worry about it as long as you provide constructors from View that pass them along to super().but you have to override second constructor to get your work done...

public CustomView(Context context)  // No Attributes in this one.
{
  super(context);
  // Your code here
}

public CustomView(Context context, AttributeSet attrs)
{
  super(context, attrs);
  // Your code here
}

public CustomView(Context context, AttributeSet attrs, int default_style)
{
  super(context, attrs, default_style);
  // Your code here
}
Sign up to request clarification or add additional context in comments.

Comments

1

If you're using an inner class as a custom view class, it must be static. The inflater doesn't have a reference to the outer class to instantiate it.

It's better to have your custom view classes on their own and not as inner classes.

Comments

0

The problem here is clearly that you are defining your View as an inner non static class of the activity. That means that the view to be instantiated needs an instance of the Activity. At least make it static. Btw the onDraw you are using is too heavy. You are creating a new typeface, decoding and scaling bitmaps for every draw. Try to refactor it a bit

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.