无法制作Android原生字体

时间:2015-04-28 21:38:29

标签: android android-layout

当我运行我的项目时,ClassNotFoundException已生成。问题是这个类在我的项目中存在 这是日志:

  

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

这是班级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;
        }
    }
}

主要班级:

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);
    }
}

和布局:

<?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> 

3 个答案:

答案 0 :(得分:1)

尝试将“assets /”文件夹放在“src / main”中,而不是与“src /”处于同一级别。您必须在随后的教程中找到此文件夹。

答案 1 :(得分:0)

你导入了这门课吗?

package com.*your_package*;

import org.taptwo.android.widget.TitleFlowIndicator;

...
public class MainActivity extends ActionBarActivity {
    // ... Main stuff here. 
}

答案 2 :(得分:0)

org.taptwo.android.widget.ViewFlow更改为tabview.com.fakher.tabconfig.ViewFlow或您的XML中的包名称