0

When i run my project a ClassNotFoundException is genereted. the problem is that this class existes in my project this is the log:

Caused by: java.lang.RuntimeException: native typeface cannot be made at android.graphics.Typeface.(Typeface.java:190) at android.graphics.Typeface.createFromAsset(Typeface.java:164) at tabview.fakher.com.tabconfig.TitleFlowIndicator.(TitleFlowIndicator.java:110)             at java.lang.reflect.Constructor.constructNative(Native Method)             at java.lang.reflect.Constructor.newInstance(Constructor.java:417)             at android.view.LayoutInflater.createView(LayoutInflater.java:594)             at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:696)             at android.view.LayoutInflater.rInflate(LayoutInflater.java:755)             at android.view.LayoutInflater.rInflate(LayoutInflater.java:758)             at android.view.LayoutInflater.inflate(LayoutInflater.java:492)             at android.view.LayoutInflater.inflate(LayoutInflater.java:397)             at android.view.LayoutInflater.inflate(LayoutInflater.java:353)             at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(ActionBarActivityDelegateBase.java:240)             at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:102)             at tabview.fakher.com.tabconfig.MainActivity.onCreate(MainActivity.java:19)             at android.app.Activity.performCreate(Activity.java:5234)             at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087)             at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2302)             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2388)             at android.app.ActivityThread.access$900(ActivityThread.java:148)             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1319)             at android.os.Handler.dispatchMessage(Handler.java:99)             at android.os.Looper.loop(Looper.java:137)             at android.app.ActivityThread.main(ActivityThread.java:5473)             at java.lang.reflect.Method.invokeNative(Native Method)             at java.lang.reflect.Method.invoke(Method.java:525)             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:854)             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:670)             at dalvik.system.NativeStart.main(Native Method)

and this is the class TitleFlowIndicator :

public class TitleFlowIndicator extends TextView implements FlowIndicator {

    private static final float TITLE_PADDING = 10.0f;
    private static final float CLIP_PADDING = 0.0f;
    private static final int SELECTED_COLOR = 0xFFFFC445;
    private static final boolean SELECTED_BOLD = false;
    private static final int TEXT_COLOR = 0xFFAAAAAA;
    private static final int TEXT_SIZE = 15;
    private static final float FOOTER_LINE_HEIGHT = 4.0f;
    private static final int FOOTER_COLOR = 0xFFFFC445;
    private static final float FOOTER_TRIANGLE_HEIGHT = 10;
    private ViewFlow viewFlow;
    private int currentScroll = 0;
    private TitleProvider titleProvider = null;
    private int currentPosition = 0;
    private Paint paintText;
    private Paint paintSelected;
    private Path path;
    private Paint paintFooterLine;
    private Paint paintFooterTriangle;
    private float footerTriangleHeight;
    private float titlePadding;
    /**
     * Left and right side padding for not active view titles.
     */
    private float clipPadding;
    private float footerLineHeight;

    /* These are hardcoded just like in TextView */
    private static final int SANS = 1;
    private static final int SERIF = 2;
    private static final int MONOSPACE = 3;

    private Typeface typeface;

    /**
     * Default constructor
     */
    public TitleFlowIndicator(Context context) {
        super(context);
        initDraw(TEXT_COLOR, TEXT_SIZE, SELECTED_COLOR, SELECTED_BOLD, TEXT_SIZE, FOOTER_LINE_HEIGHT, FOOTER_COLOR);
    }

    /**
     * The contructor used with an inflater
     * 
     * @param context
     * @param attrs
     */
    public TitleFlowIndicator(Context context, AttributeSet attrs) {
        super(context, attrs);
        // Retrieve styles attributs

        int typefaceIndex = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "typeface", 0);
        int textStyleIndex = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "textStyle", 0);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.TitleFlowIndicator);

        String customTypeface = a.getString(R.styleable.TitleFlowIndicator_customTypeface);
        // Retrieve the colors to be used for this view and apply them.
        int footerColor = a.getColor(R.styleable.TitleFlowIndicator_footerColor, FOOTER_COLOR);
        footerLineHeight = a.getDimension(R.styleable.TitleFlowIndicator_footerLineHeight, FOOTER_LINE_HEIGHT);
        footerTriangleHeight = a.getDimension(R.styleable.TitleFlowIndicator_footerTriangleHeight, FOOTER_TRIANGLE_HEIGHT);
        int selectedColor = a.getColor(R.styleable.TitleFlowIndicator_selectedColor, SELECTED_COLOR);
        boolean selectedBold = a.getBoolean(R.styleable.TitleFlowIndicator_selectedBold, SELECTED_BOLD);
        int textColor = a.getColor(R.styleable.TitleFlowIndicator_textColor, TEXT_COLOR);
        float textSize = a.getDimension(R.styleable.TitleFlowIndicator_textSize, TEXT_SIZE);
        float selectedSize = a.getDimension(R.styleable.TitleFlowIndicator_selectedSize, textSize);
        titlePadding = a.getDimension(R.styleable.TitleFlowIndicator_titlePadding, TITLE_PADDING);
        clipPadding = a.getDimension(R.styleable.TitleFlowIndicator_clipPadding, CLIP_PADDING);
        initDraw(textColor, textSize, selectedColor, selectedBold, selectedSize, footerLineHeight, footerColor);

        if (customTypeface != null)
            typeface = Typeface.createFromAsset(context.getAssets(), customTypeface);
        else
            typeface = getTypefaceByIndex(typefaceIndex);
        typeface = Typeface.create(typeface, textStyleIndex);

    }

    /**
     * Initialize draw objects
     */
    private void initDraw(int textColor, float textSize, int selectedColor, boolean selectedBold, float selectedSize, float footerLineHeight, int footerColor) {
        paintText = new Paint();
        paintText.setColor(textColor);
        paintText.setTextSize(textSize);
        paintText.setAntiAlias(true);
        paintSelected = new Paint();
        paintSelected.setColor(selectedColor);
        paintSelected.setTextSize(selectedSize);
        paintSelected.setFakeBoldText(selectedBold);
        paintSelected.setAntiAlias(true);
        paintFooterLine = new Paint();
        paintFooterLine.setStyle(Paint.Style.FILL_AND_STROKE);
        paintFooterLine.setStrokeWidth(footerLineHeight);
        paintFooterLine.setColor(footerColor);
        paintFooterTriangle = new Paint();
        paintFooterTriangle.setStyle(Paint.Style.FILL_AND_STROKE);
        paintFooterTriangle.setColor(footerColor);
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.view.View#onDraw(android.graphics.Canvas)
     */
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        // Calculate views bounds
        ArrayList<Rect> bounds = calculateAllBounds(paintText);

        // If no value then add a fake one
        int count = (viewFlow != null && viewFlow.getAdapter() != null) ? viewFlow.getAdapter().getCount() : 1;

        // Verify if the current view must be clipped to the screen
        Rect curViewBound = bounds.get(currentPosition);
        int curViewWidth = curViewBound.right - curViewBound.left;
        if (curViewBound.left < 0) {
            // Try to clip to the screen (left side)
            clipViewOnTheLeft(curViewBound, curViewWidth);
        }
        if (curViewBound.right > getLeft() + getWidth()) {
            // Try to clip to the screen (right side)
            clipViewOnTheRight(curViewBound, curViewWidth);
        }

        // Left views starting from the current position
        if (currentPosition > 0) {
            for (int iLoop = currentPosition - 1; iLoop >= 0; iLoop--) {
                Rect bound = bounds.get(iLoop);
                int w = bound.right - bound.left;
                // Si left side is outside the screen
                if (bound.left < 0) {
                    // Try to clip to the screen (left side)
                    clipViewOnTheLeft(bound, w);
                    // Except if there's an intersection with the right view
                    if (iLoop < count - 1 && currentPosition != iLoop) {
                        Rect rightBound = bounds.get(iLoop + 1);
                        // Intersection
                        if (bound.right + TITLE_PADDING > rightBound.left) {
                            bound.left = rightBound.left - (w + (int) titlePadding);
                        }
                    }
                }
            }
        }
        // Right views starting from the current position
        if (currentPosition < count - 1) {
            for (int iLoop = currentPosition + 1; iLoop < count; iLoop++) {
                Rect bound = bounds.get(iLoop);
                int w = bound.right - bound.left;
                // If right side is outside the screen
                if (bound.right > getLeft() + getWidth()) {
                    // Try to clip to the screen (right side)
                    clipViewOnTheRight(bound, w);
                    // Except if there's an intersection with the left view
                    if (iLoop > 0 && currentPosition != iLoop) {
                        Rect leftBound = bounds.get(iLoop - 1);
                        // Intersection
                        if (bound.left - TITLE_PADDING < leftBound.right) {
                            bound.left = leftBound.right + (int) titlePadding;
                        }
                    }
                }
            }
        }

        // Now draw views
        for (int iLoop = 0; iLoop < count; iLoop++) {
            // Get the title
            String title = getTitle(iLoop);
            Rect bound = bounds.get(iLoop);
            // Only if one side is visible
            if ((bound.left > getLeft() && bound.left < getLeft() + getWidth()) || (bound.right > getLeft() && bound.right < getLeft() + getWidth())) {
                Paint paint = paintText;
                // Change the color is the title is closed to the center
                int middle = (bound.left + bound.right) / 2;
                if (Math.abs(middle - (getWidth() / 2)) < 20) {
                    paint = paintSelected;
                }
                paint.setTypeface(typeface);
                canvas.drawText(title, bound.left, bound.bottom, paint);
            }
        }

        // Draw the footer line
        path = new Path();
        int coordY = getHeight() - 1;
        coordY -= (footerLineHeight % 2 == 1) ? footerLineHeight / 2 : footerLineHeight / 2 - 1;
        path.moveTo(0, coordY);
        path.lineTo(getWidth(), coordY);
        path.close();
        canvas.drawPath(path, paintFooterLine);
        // Draw the footer triangle
        path = new Path();
        path.moveTo(getWidth() / 2, getHeight() - footerLineHeight - footerTriangleHeight);
        path.lineTo(getWidth() / 2 + footerTriangleHeight, getHeight() - footerLineHeight);
        path.lineTo(getWidth() / 2 - footerTriangleHeight, getHeight() - footerLineHeight);
        path.close();
        canvas.drawPath(path, paintFooterTriangle);

    }

    /**
     * Set bounds for the right textView including clip padding.
     * 
     * @param curViewBound
     *            current bounds.
     * @param curViewWidth
     *            width of the view.
     */
    private void clipViewOnTheRight(Rect curViewBound, int curViewWidth) {
        curViewBound.right = getLeft() + getWidth() - (int) clipPadding;
        curViewBound.left = curViewBound.right - curViewWidth;
    }

    /**
     * Set bounds for the left textView including clip padding.
     * 
     * @param curViewBound
     *            current bounds.
     * @param curViewWidth
     *            width of the view.
     */
    private void clipViewOnTheLeft(Rect curViewBound, int curViewWidth) {
        curViewBound.left = 0 + (int) clipPadding;
        curViewBound.right = curViewWidth;
    }

    /**
     * Calculate views bounds and scroll them according to the current index
     * 
     * @param paint
     * @param //currentIndex
     * @return
     */
    private ArrayList<Rect> calculateAllBounds(Paint paint) {
        ArrayList<Rect> list = new ArrayList<Rect>();
        // For each views (If no values then add a fake one)
        int count = (viewFlow != null && viewFlow.getAdapter() != null) ? viewFlow.getAdapter().getCount() : 1;
        for (int iLoop = 0; iLoop < count; iLoop++) {
            Rect bounds = calcBounds(iLoop, paint);
            int w = (bounds.right - bounds.left);
            int h = (bounds.bottom - bounds.top);
            bounds.left = (getWidth() / 2) - (w / 2) - currentScroll + (iLoop * getWidth());
            bounds.right = bounds.left + w;
            bounds.top = 0;
            bounds.bottom = h;
            list.add(bounds);
        }

        return list;
    }

    /**
     * Calculate the bounds for a view's title
     * 
     * @param index
     * @param paint
     * @return
     */
    private Rect calcBounds(int index, Paint paint) {
        // Get the title
        String title = getTitle(index);
        // Calculate the text bounds
        Rect bounds = new Rect();
        bounds.right = (int) paint.measureText(title);
        bounds.bottom = (int) (paint.descent() - paint.ascent());
        return bounds;
    }

    /**
     * Returns the title
     * 
     * @param pos
     * @return
     */
    private String getTitle(int pos) {
        // Set the default title
        String title = "title " + pos;
        // If the TitleProvider exist
        if (titleProvider != null) {
            title = titleProvider.getTitle(pos);
        }
        return title;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.taptwo.android.widget.FlowIndicator#onScrolled(int, int, int,
     * int)
     */
    @Override
    public void onScrolled(int h, int v, int oldh, int oldv) {
        currentScroll = h;
        invalidate();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.taptwo.android.widget.ViewFlow.ViewSwitchListener#onSwitched(android
     * .view.View, int)
     */
    @Override
    public void onSwitched(View view, int position) {
        currentPosition = position;
        invalidate();
    }

    /*
     * (non-Javadoc)
     * 
     * @see
     * org.taptwo.android.widget.FlowIndicator#setViewFlow(org.taptwo.android
     * .widget.ViewFlow)
     */
    @Override
    public void setViewFlow(ViewFlow view) {
        viewFlow = view;
        currentPosition = view.getSelectedItemPosition();
        invalidate();
    }

    /**
     * Set the title provider
     * 
     * @param provider
     */
    public void setTitleProvider(TitleProvider provider) {
        titleProvider = provider;
    }

    /*
     * (non-Javadoc)
     * 
     * @see android.view.View#onMeasure(int, int)
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));
    }

    /**
     * Determines the width of this view
     * 
     * @param measureSpec
     *            A measureSpec packed into an int
     * @return The width of the view, honoring constraints from measureSpec
     */
    private int measureWidth(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        if (specMode != MeasureSpec.EXACTLY) {
            throw new IllegalStateException("ViewFlow can only be used in EXACTLY mode.");
        }
        result = specSize;
        return result;
    }

    /**
     * Determines the height of this view
     * 
     * @param measureSpec
     *            A measureSpec packed into an int
     * @return The height of the view, honoring constraints from measureSpec
     */
    private int measureHeight(int measureSpec) {
        int result = 0;
        int specMode = MeasureSpec.getMode(measureSpec);
        int specSize = MeasureSpec.getSize(measureSpec);

        // We were told how big to be
        if (specMode == MeasureSpec.EXACTLY) {
            result = specSize;
        }
        // Measure the height
        else {
            // Calculate the text bounds
            Rect bounds = new Rect();
            bounds.bottom = (int) (paintText.descent() - paintText.ascent());
            result = bounds.bottom - bounds.top + (int) footerTriangleHeight + (int) footerLineHeight + 10;
            return result;
        }
        return result;
    }

    private Typeface getTypefaceByIndex(int typefaceIndex) {
        switch (typefaceIndex) {
        case SANS:
            return Typeface.SANS_SERIF;

        case SERIF:
            return Typeface.SERIF;

        case MONOSPACE:
            return Typeface.MONOSPACE;
        default:
            return Typeface.DEFAULT;
        }
    }
}

the main class :

public class MainActivity extends ActionBarActivity {

    private ViewFlow viewFlow;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setTitle(R.string.title_title);
        setContentView(R.layout.title_layout);

        viewFlow = (ViewFlow) findViewById(R.id.viewflow);
        AndroidVersionAdapter adapter = new AndroidVersionAdapter(this);
        viewFlow.setAdapter(adapter, 3);
        TitleFlowIndicator indicator = (TitleFlowIndicator) findViewById(R.id.viewflowindic);
        indicator.setTitleProvider(adapter);
        viewFlow.setFlowIndicator(indicator);
    }
}

and the layout :

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical" android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <LinearLayout android:layout_width="fill_parent"
        android:gravity="center_horizontal"
        android:id="@+id/header_layout"
        android:orientation="vertical"
        android:layout_height="wrap_content">
        <tabview.fakher.com.tabconfig.TitleFlowIndicator
            android:id="@+id/viewflowindic"
            android:layout_height="wrap_content"
            android:layout_width="fill_parent"
            app:footerLineHeight="2dp"
            app:customTypeface="fonts/Antic.ttf"
            app:footerTriangleHeight="10dp"
            app:textColor="#FFFFFFFF"
            app:selectedColor="#FFFFC445"
            app:footerColor="#FFFFC445"
            app:titlePadding="10dp"
            app:textSize="11dp"
            app:selectedSize="12dp"
            android:layout_marginTop="10dip"
            app:clipPadding="5dp">

            </tabview.fakher.com.tabconfig.TitleFlowIndicator>

    </LinearLayout>
    <org.taptwo.android.widget.ViewFlow
        android:duplicateParentState="true" android:id="@+id/viewflow"
        android:layout_width="fill_parent" android:layout_height="fill_parent"></org.taptwo.android.widget.ViewFlow>
</LinearLayout> 
Fakher
  • 2,098
  • 3
  • 29
  • 45
  • does `TitleFlowIndicator ` located in a jar file? – Rod_Algonquin Apr 28 '15 at 21:44
  • no it's under a package i think that my problem is in this line : xmlns:app="http://schemas.android.com/apk/res-auto" in the layout – Fakher Apr 28 '15 at 21:46
  • Its clearly unhappy about trying to inflate that view. This portion of the error message makes me believe that the view isn't getting packaged into your APK. Dumb question, but is it in the res/layout folder?java.lang.ClassNotFoundException: Didn't find class "org.taptwo.android.widget.TitleFlowIndicator" on path: DexPathList[[zip file "/data/app/tabview.fakher.com.tabconfig-2.apk"]. – Noah Apr 28 '15 at 21:49
  • yes of course it is under res/layout !!! but the problem is that my package name is tabview.com.fakher.tabconfig and it call org.taptwo.android.widget.TitleFlowIndicator the package from where i follow the tutorial !! note: i didn't download the project i maked it and i copied the source because it's very huge – Fakher Apr 28 '15 at 21:53
  • 1
    @Fakher : Edit your code block for `TitleFlowIndicator` to show the `package` declaration. – Squonk Apr 28 '15 at 21:56
  • @sqrfv the error is changed please take a look on the code above and the error THX – Fakher Apr 28 '15 at 22:18
  • @Rod_algonquin the error is changed please take a look on the code above and the error THX – Fakher Apr 28 '15 at 22:18
  • @Squonk the error is changed please take a look on the code above and the error THX – Fakher Apr 28 '15 at 22:18

2 Answers2

0

Have you imported the class?

package com.*your_package*;

import org.taptwo.android.widget.TitleFlowIndicator;

...
public class MainActivity extends ActionBarActivity {
    // ... Main stuff here. 
}
flagg327
  • 967
  • 1
  • 10
  • 21
  • the xml file cannot find the class not the java class !! besides that "org.taptwo.android.widget" is not my package !! it's tabview.com.fakher.tabconfig – Fakher Apr 28 '15 at 21:55
0

Change org.taptwo.android.widget.ViewFlow to tabview.com.fakher.tabconfig.ViewFlow or whatever actually is your package name in your XML

Chris Stillwell
  • 10,266
  • 10
  • 67
  • 77
  • the error is changed please take a look on the code above and the error THX – Fakher Apr 28 '15 at 22:19
  • Looks like you are trying to set a custom typeface and the typeface can't be found. See if this helps http://stackoverflow.com/a/24607372/1176870 – Chris Stillwell Apr 28 '15 at 22:39