Main.java Source code

Java tutorial

Introduction

Here is the source code for Main.java

Source

//package com.java2s;
/*
 * Copyright (C) 2013 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import android.graphics.Typeface;

import android.text.SpannableString;

import android.text.TextPaint;
import android.text.TextUtils;

import android.text.style.StyleSpan;

public class Main {
    private static final float MIN_TEXT_XSCALE = 0.70f;

    private static CharSequence getEllipsizedText(final CharSequence text, final int maxWidth,
            final TextPaint paint) {
        if (text == null) {
            return null;
        }
        final float scaleX = getTextScaleX(text, maxWidth, paint);
        if (scaleX >= MIN_TEXT_XSCALE) {
            paint.setTextScaleX(scaleX);
            return text;
        }

        // Note that TextUtils.ellipsize() use text-x-scale as 1.0 if ellipsize is needed. To
        // get squeezed and ellipsized text, passes enlarged width (maxWidth / MIN_TEXT_XSCALE).
        final float upscaledWidth = maxWidth / MIN_TEXT_XSCALE;
        CharSequence ellipsized = TextUtils.ellipsize(text, paint, upscaledWidth, TextUtils.TruncateAt.MIDDLE);
        // For an unknown reason, ellipsized seems to return a text that does indeed fit inside the
        // passed width according to paint.measureText, but not according to paint.getTextWidths.
        // But when rendered, the text seems to actually take up as many pixels as returned by
        // paint.getTextWidths, hence problem.
        // To save this case, we compare the measured size of the new text, and if it's too much,
        // try it again removing the difference. This may still give a text too long by one or
        // two pixels so we take an additional 2 pixels cushion and call it a day.
        // TODO: figure out why getTextWidths and measureText don't agree with each other, and
        // remove the following code.
        final float ellipsizedTextWidth = getTextWidth(ellipsized, paint);
        if (upscaledWidth <= ellipsizedTextWidth) {
            ellipsized = TextUtils.ellipsize(text, paint, upscaledWidth - (ellipsizedTextWidth - upscaledWidth) - 2,
                    TextUtils.TruncateAt.MIDDLE);
        }
        paint.setTextScaleX(MIN_TEXT_XSCALE);
        return ellipsized;
    }

    private static float getTextScaleX(final CharSequence text, final int maxWidth, final TextPaint paint) {
        paint.setTextScaleX(1.0f);
        final int width = getTextWidth(text, paint);
        if (width <= maxWidth) {
            return 1.0f;
        }
        return maxWidth / (float) width;
    }

    private static int getTextWidth(final CharSequence text, final TextPaint paint) {
        if (TextUtils.isEmpty(text)) {
            return 0;
        }
        final Typeface savedTypeface = paint.getTypeface();
        paint.setTypeface(getTextTypeface(text));
        final int len = text.length();
        final float[] widths = new float[len];
        final int count = paint.getTextWidths(text, 0, len, widths);
        int width = 0;
        for (int i = 0; i < count; i++) {
            width += Math.round(widths[i] + 0.5f);
        }
        paint.setTypeface(savedTypeface);
        return width;
    }

    private static Typeface getTextTypeface(final CharSequence text) {
        if (!(text instanceof SpannableString)) {
            return Typeface.DEFAULT;
        }

        final SpannableString ss = (SpannableString) text;
        final StyleSpan[] styles = ss.getSpans(0, text.length(), StyleSpan.class);
        if (styles.length == 0) {
            return Typeface.DEFAULT;
        }

        if (styles[0].getStyle() == Typeface.BOLD) {
            return Typeface.DEFAULT_BOLD;
        }
        // TODO: BOLD_ITALIC, ITALIC case?
        return Typeface.DEFAULT;
    }
}