0

I know you'll have seen this question before. I know I have :-). But still, combing all the answers I have found I still get the inflating class error. My layout has an extended webView as I want to be able to swipe left and right in order to load previous and next html pages. I include the entire layout as I find that most of the answers I have found present a solution in a somewhat abstract manner dealing with just the webView and not as a part of a larger picture. Hopefully when this is answered it will help others to get the bigger picture as well.

The scrollview at the bottom wil contain buttons as an alternative means of navigating the html pages. The view imageView2 will contain a transparent header partly obscuring the underlying webView. The textView helloText will display the chapter titles. I had all of this working until I had to extend the webView to deal with the left right swipes.

Here's the layout xml:

<LinearLayout 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:orientation="vertical"
    tools:context=".MainActivity" >

    <RelativeLayout
        android:id="@+id/relativeLayout1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.8"
        android:orientation="vertical" >

        <com.example.test.MyWebView
            android:id="@+id/webView1"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_alignParentLeft="true"
            android:layout_alignParentTop="true" />

        <View
            android:id="@+id/imageView2"
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true" 
            android:background="#88FF0000"/>
    </RelativeLayout>

    <TextView
        android:id="@+id/helloText"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.05"
        android:gravity="center_horizontal"
        android:text="Hello World" />

    <HorizontalScrollView
        android:id="@+id/horizontalScrollView1"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.15"
            android:background="#0000FF" >

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="fill_parent"
            android:orientation="horizontal" >

             <Button
            android:id="@+id/button1"
            android:layout_width="110dp"
            android:layout_height="45dp"
            android:background="#00FF00" />

        </LinearLayout>
    </HorizontalScrollView>

</LinearLayout>

and this is the code:

package com.example.test;

import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Menu;
import android.view.MotionEvent;
import android.webkit.WebView;
import android.widget.Toast;

public class MainActivity extends Activity {

int currentPage = 2; // page number for current html file

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    //get a pointer to the webview
    MyWebView webview = (MyWebView) findViewById(R.id.webView1);

    webview.getSettings().setUseWideViewPort(true); 
    webview.getSettings().setSupportZoom(true);
    webview.getSettings().setBuiltInZoomControls(true);

    // put html page in the webView
    webview.loadUrl("file:///android_asset/chapter" + currentPage + ".html");
}

public void changePage(int page) {

    Log.v("test", "change page to " + page);

    //get a pointer to the webview
    MyWebView webview = (MyWebView)findViewById(R.id.webView1);

    // put html page in the webView
    webview.loadUrl("file:///android_asset/chapter" + page + ".html");

    }

class MyWebView extends WebView {
     Context context;
     GestureDetector gd;

    public MyWebView(Context context, AttributeSet attrs) {
    super(context, attrs);

    this.context = context;
         gd = new GestureDetector(context, sogl);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return (gd.onTouchEvent(event) 
                || super.onTouchEvent(event));
    }

     GestureDetector.SimpleOnGestureListener sogl = new GestureDetector.SimpleOnGestureListener() {
      public boolean onDown(MotionEvent event) {
       return false;
      }
      public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
       if (event1.getRawX() > event2.getRawX() && StrictMath.abs(event1.getRawY()-event2.getRawY())<100) {
        show_toast("swipe left");
        currentPage += 1;
        if (currentPage >= 19) currentPage = 19;
        changePage(currentPage);
       } else if(event1.getRawX() < event2.getRawX() && StrictMath.abs(event1.getRawY()-event2.getRawY())<100){
        show_toast("swipe right");
        currentPage -= 1;
        if (currentPage <= 1) currentPage = 1;
        changePage(currentPage);
       } else {
         return false;
       }
    return true;
      }
     };

     void show_toast(final String text) {
      Toast t = Toast.makeText(context, text, Toast.LENGTH_SHORT);
      t.show();
     }
    }
}

The actual error reads:

java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.test.MyWebView

Thanks in advance for your help. Much appreciated.

Mr. Jigs

As requested the full error trace:

01-23 10:21:51.980: E/AndroidRuntime(29514): FATAL EXCEPTION: main
01-23 10:21:51.980: E/AndroidRuntime(29514): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.test/com.example.test.MainActivity}: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.test.MyWebView
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2100)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.ActivityThread.access$600(ActivityThread.java:140)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1227)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.os.Looper.loop(Looper.java:137)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.ActivityThread.main(ActivityThread.java:4898)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at java.lang.reflect.Method.invokeNative(Native Method)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at java.lang.reflect.Method.invoke(Method.java:511)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1006)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:773)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at dalvik.system.NativeStart.main(Native Method)
01-23 10:21:51.980: E/AndroidRuntime(29514): Caused by: android.view.InflateException: Binary XML file line #15: Error inflating class com.example.test.MyWebView
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:698)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:749)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:308)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.Activity.setContentView(Activity.java:1924)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at com.example.test.MainActivity.onCreate(MainActivity.java:21)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.Activity.performCreate(Activity.java:5206)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1083)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
01-23 10:21:51.980: E/AndroidRuntime(29514):    ... 11 more
01-23 10:21:51.980: E/AndroidRuntime(29514): Caused by: java.lang.ClassNotFoundException: com.example.test.MyWebView
01-23 10:21:51.980: E/AndroidRuntime(29514):    at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:61)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at java.lang.ClassLoader.loadClass(ClassLoader.java:501)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at java.lang.ClassLoader.loadClass(ClassLoader.java:461)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.createView(LayoutInflater.java:552)
01-23 10:21:51.980: E/AndroidRuntime(29514):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:687)
01-23 10:21:51.980: E/AndroidRuntime(29514):    ... 22 more
Mr. Jigs
  • 73
  • 1
  • 11
  • Post all exception trace, and MyWebView code and layout – Dimmerg Jan 23 '14 at 08:43
  • add this `public MyWebView(Context context) { super(context); // this constructor used when programmatically creating view }` constructor also and try and you could move the custom web view to separate .java file – Raghunandan Jan 23 '14 at 08:43
  • @ Dimmerg: all trace included as requested. The MyWebView code starts in the posted code section with line: "class MyWebView extends WebView {" the layout section starts at line beginning with: " – Mr. Jigs Jan 23 '14 at 09:26
  • @Raghunandan: I believe that code already to be present. See the posted code where the webView class is extended. About four lines down from: "class MyWebView extends WebView {" – Mr. Jigs Jan 23 '14 at 09:31
  • @Mr.Jigs move it to sparate file and add another constructor as suggested and try – Raghunandan Jan 23 '14 at 09:32
  • That was actually the solution. Although you did not explain why you came up with it first. I am not sure as how to accept your comment as the right solution. – Mr. Jigs Jan 23 '14 at 11:52

3 Answers3

2

Make sure you add all these constructors in your custom webview class.

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

    public CustomWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public CustomWebView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public CustomWebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

And also don't forget to use this CustomWebView class in xml layout file with your complete package name.

 <com.kittykitty.meowmeow.CustomWebView
                android:id="@+id/my_webview"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                />
KrzyShzy
  • 156
  • 7
1

MyWebView class is internal of MainActivity class. Inflater does not see this class. Make your WebView in defferent .java file.

Also you can try to use that name in your layout file <com.example.test.MainActivity.MyWebView/>, but i'm not sure about it.

Roman Black
  • 3,501
  • 1
  • 22
  • 31
  • I believe that code already to be present. See the posted code where the webView class is extended. About four lines down from: "class MyWebView extends WebView {" – Mr. Jigs Jan 23 '14 at 09:32
  • MyWebView class is internal of MainActivity class. Inflater does not see this class. Make your WebView in defferent .java file. – Roman Black Jan 23 '14 at 09:59
  • Also you can try to use that name in your layout file , but i'm not sure about it. – Roman Black Jan 23 '14 at 10:01
  • Yes, you are right. What is more you actually explained why. That was a big help. Thank you. If I can't accept Raghunadan's comment ad the right answer, he did get there first, I'll accept this. – Mr. Jigs Jan 23 '14 at 11:55
  • I've updated my post. This information more actual for this question. – Roman Black Jan 23 '14 at 12:25
1
// try this way
1. Custom WebView Class
public class MyWebView extends WebView {
    Context context;
    GestureDetector gd;
    OnPageChangleListener listener;
    private int currentPage=1;
    private int startPageIndex;
    private int lastPageIndex;

    public MyWebView(Context context) {
        super(context);
       init(context);
    }

    public MyWebView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    public MyWebView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init(context);
    }

    private void init(Context context){
        this.context = context;
        gd = new GestureDetector(context, sogl);
    }


    @Override
    public boolean onTouchEvent(MotionEvent event) {
        return (gd.onTouchEvent(event)
                || super.onTouchEvent(event));
    }

    public void setOnPageChangeListener(OnPageChangleListener listener){
        this.listener = listener;
    }

    public void setStartPageIndex(int startPageIndex){
        this.startPageIndex = startPageIndex;
    }

    public int getStartPageIndex(){
        currentPage = startPageIndex;
        return startPageIndex;
    }

    public int getLastPageIndex(){
        return lastPageIndex;
    }

    public void setLastPageIndex(int lastPageIndex){
        this.lastPageIndex = lastPageIndex;
    }
    GestureDetector.SimpleOnGestureListener sogl = new GestureDetector.SimpleOnGestureListener() {
        public boolean onDown(MotionEvent event) {
            return false;
        }
        public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) {
            if (event1.getRawX() > event2.getRawX() && StrictMath.abs(event1.getRawY()-event2.getRawY())<100) {
                currentPage += 1;
                if (currentPage > lastPageIndex){
                    currentPage = lastPageIndex;
                    show_toast("Last Page");
                }else{
                    show_toast("swipe left");
                    listener.onPageChange(currentPage);
                }
            } else if(event1.getRawX() < event2.getRawX() && StrictMath.abs(event1.getRawY()-event2.getRawY())<100){
                currentPage -= 1;
                if (currentPage < startPageIndex) {
                    currentPage = startPageIndex;
                    show_toast("First Page");
                }else{
                    show_toast("swipe right");
                    listener.onPageChange(currentPage);
                }
            } else {
                return false;
            }
            return true;
        }
    };

    void show_toast(final String text) {
        Toast t = Toast.makeText(context, text, Toast.LENGTH_SHORT);
        t.show();
    }

}

2. Custom Interface for you Custom WebView page change listener.
public interface OnPageChangleListener {
    public void onPageChange(int pageNo);
}

3. Use Custom WebView in your Activity.
 MyWebView myWebView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        myWebView = (MyWebView) findViewById(R.id.myWebView);
        myWebView.getSettings().setUseWideViewPort(true);
        myWebView.getSettings().setSupportZoom(true);
        myWebView.getSettings().setBuiltInZoomControls(true);
        myWebView.setStartPageIndex(2);
        myWebView.setLastPageIndex(4);
        myWebView.setOnPageChangeListener(new OnPageChangleListener() {
            @Override
            public void onPageChange(int pageNo) {
                System.out.println(String.valueOf(pageNo));
                myWebView.loadUrl("file:///android_asset/" + pageNo + ".html");
            }
        });

        myWebView.loadUrl("file:///android_asset/" + myWebView.getStartPageIndex() + ".html");

}
4.main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    <com.example.Demo.MyWebView
        android:id="@+id/myWebView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>
Haresh Chhelana
  • 24,720
  • 5
  • 57
  • 67
  • Thanks Haresh, I have inserted your code but this results in the same error. Could it possible be that the path to MyWebView should be adjusted considering that in my layout the MyWebView is not at the highest level (right inside the linearlayout at the top level) but down one level inside a relativelayout. Something like com.example.test.RelativeLayout.MyWebView? – Mr. Jigs Jan 23 '14 at 10:01
  • you have to create Custom WebView class not as Activity inner class,So you have declare as inner class in your MainActivity ? then create separate class for Custom WebView. – Haresh Chhelana Jan 23 '14 at 10:50
  • Thank you for the example code and the much improved page change mechanism. Unfortunately you were not first with the actual solution that the class was hidden by theMainActivity. – Mr. Jigs Jan 23 '14 at 11:57