Reputation: 2128
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>
Upvotes: 0
Views: 581
Reputation: 10547
Change org.taptwo.android.widget.ViewFlow
to tabview.com.fakher.tabconfig.ViewFlow
or whatever actually is your package name in your XML
Upvotes: 0
Reputation: 1007
Have you imported the class?
package com.*your_package*;
import org.taptwo.android.widget.TitleFlowIndicator;
...
public class MainActivity extends ActionBarActivity {
// ... Main stuff here.
}
Upvotes: 0