1

How can I fit a double into a text edit object? I want include as many digits as possible on the screen without excluding scientific notation, and rounding. For example:

1000900E13 -->  10009E13
1000090E13 -->  10001E13
1000009E13 -->  1E13

I realize if I could count the the number of characters that could fit into a text edit, I could solve this problem, but character width is variable.

edit: ok, I've implemented the logic now, but I'm getting the following error when I hit the equals symbol on the interface:

fatal signal 6 (SIGBART) at 0x000001b0 (code=0)
//This error happens when I call the function, and it not a bug inside the function   itself

This is the button "=" for my calculator

 equal.setOnClickListener(new View.OnClickListener() { 
    @Override
    public void onClick(View v) {
        // TODO Auto-generated method stub

        double result;
        result = evaluateString.evaluate(string);
        string = formatDouble.fmt(result); //omits redundant zeros and decimal point

        Typeface tface = disp.getTypeface();
        float fsize = disp.getTextSize();
        float field_width = disp.getWidth();

        //this function is the problem
        String show = fillScreen.getLength(fsize, tface, field_width, string); 

        disp.setText(show);
    }
});

And this is the implementation to fill the double into the Text Edit.

public class fillScreen {

    //find proper length
    public static String getLength(float fsize, Typeface tface, float field_width, String string) {
        int len = 1;
        Paint paint = new Paint();
        Rect rect = new Rect();

        MainActivity.disp.setText("error");

        while (true) {
            paint.setTypeface(tface);
            paint.setTextSize(fsize);
            paint.getTextBounds(string, 0, string.length(), rect);
            if (rect.width() > field_width)
                break;
            len++;
        }

        len = len - 1;

        String numbersigns="0.";
        for (int i =0; i<len;i++){
            numbersigns=numbersigns+"#";
        }

        numbersigns=numbersigns+"E0";
        NumberFormat formatter = new DecimalFormat(numbersigns);
        return (formatter.format(Double.parseDouble(string))); 
    } 
}

Stack trace after dividing 6 by 6 and pressing uequals

07-12 17:12:42.432: I/System.out(6500): string is   :      6/6
07-12 17:12:42.436: I/System.out(6500): strings is  :      6/6
07-12 17:12:42.436: I/System.out(6500): strings RVP :      66/
07-12 17:12:45.519: D/AudioHardware(154): AudioHardware pcm playback is going to standby.
07-12 17:12:45.519: V/AudioHardware(154): closeMixer_l() mMixerOpenCnt: 1
07-12 17:12:45.519: D/AudioHardware(154): closePcmOut_l() mPcmOpenCnt: 1
07-12 17:12:47.309: D/lights(432): set_light_buttons: color=0xff000000, tlc=0.
07-12 17:13:12.310: I/PowerManagerService(432): Going to sleep due to screen timeout...
07-12 17:13:13.064: D/dalvikvm(432): GC_FOR_ALLOC freed 2400K, 30% free 12448K/17712K, paused 126ms, total 131ms
07-12 17:13:13.067: D/SurfaceFlinger(149): Screen released, type=0 flinger=0x2a007478
07-12 17:13:13.174: I/WindowManager(432): Screenshot Window{4230d070 u0 com.example.test/com.example.test.MainActivity} was all black! mSurfaceLayer=21040 minLayer=21040 maxLayer=21040
07-12 17:13:13.240: D/AccelerometerListener(744): enable(false)
07-12 17:13:13.677: W/ActivityManager(432): Activity pause timeout for ActivityRecord{420b2be8 u0 com.example.test/.MainActivity}
07-12 17:13:18.144: W/ActivityManager(432): Sleep timeout!  Sleeping now.
07-12 17:13:18.507: D/dalvikvm(432): GC_FOR_ALLOC freed 1165K, 25% free 13326K/17712K, paused 152ms, total 153ms
07-12 17:13:18.507: I/ActivityManager(432): Start proc com.cyanogenmod.lockclock for broadcast com.cyanogenmod.lockclock/.ClockWidgetProvider: pid=6753 uid=10029 gids={50029, 3003}
07-12 17:13:18.627: I/ActivityManager(432): Start proc com.andrew.apollo for broadcast com.andrew.apollo/.appwidgets.AppWidgetSmall: pid=6767 uid=10000 gids={50000, 1015, 3003, 1028}
07-12 17:13:18.901: I/ActivityManager(432): No longer want net.cactii.flash2 (pid 6395): empty #17
07-12 17:13:18.937: I/ActivityManager(432): Start proc com.google.android.gsf.login for service com.google.android.gsf.login/com.google.android.gsf.loginservice.GoogleLoginService: pid=6781 uid=10052 gids={50052, 3003, 1007, 1028, 1015, 1006, 3002, 3001, 2001, 3006}
07-12 17:13:18.947: V/KeyguardHostView(432): hide transport, gen:3
07-12 17:13:18.947: V/KeyguardHostView(432): music state changed: 0
07-12 17:13:19.117: D/PhoneStatusBar(583): disable: < EXPAND* icons alerts TICKER* system_info back home RECENT* clock search >
07-12 17:13:19.167: V/TAG(432): bug 7643792: fitSystemWindows([0,38][0,0])
07-12 17:13:19.214: D/PhoneStatusBar(583): disable: < EXPAND icons alerts TICKER system_info BACK* HOME* RECENT CLOCK* search >
07-12 17:13:19.377: I/ActivityManager(432): No longer want com.android.defcontainer (pid 6462): empty #17
07-12 17:13:19.674: I/ActivityManager(432): No longer want com.android.keychain (pid 6549): empty #17
07-12 17:13:23.678: W/ActivityManager(432): Activity stop timeout for ActivityRecord{420b2be8 u0 com.example.test/.MainActivity}
the_prole
  • 8,275
  • 16
  • 78
  • 163

1 Answers1

1

If the font is proportional (variable char length) you would need to do iterations:

1. Start with length 1
2. Calculate the width using Paint object and setTypeFace, setTextSize methods
3. Increase length, check if it still fits, if not the result is (length -1)

Here how your code can look like. You'll just need to write your own method that returns a number with a given length as a string (see getNumberAsString below):

    public int getLength(int fsize, Typeface tface, int field_width) {
        int len = 1;
        Paint paint = new Paint();
        Rect rect = new Rect();

        while (true) {

            paint.setTypeface(tface);
            paint.setTextSize(fsize);
            String text = getNumberAsString(len);
            paint.getTextBounds(text, 0, text.length(), rect);
            if (rect.width() > field_width)
                break;
            len++;
        }
        return len - 1;
    } 

In your current implementation 'while' loop will never end, because you don't change the size of 'string'. To fix the problem, you need to add the following function:

    public String getNumberAsString(int len, String string) {
        String numbersigns="0.";
        for (int i =0; i<len;i++){
            numbersigns=numbersigns+"#";
        }

        numbersigns=numbersigns+"E0";
        NumberFormat formatter = new DecimalFormat(numbersigns);
        return (formatter.format(Double.parseDouble(string))); 
    }

and then use it in your 'while' loop as follows:

cur_str = getNumberAsString(len, string);
paint.getTextBounds(cur_str, 0, cur_str.length(), rect);

I've also found a very good explanation why setText('Error') called before 'while' loop didn't work. A detailed description is provided in the post below. setText invalidates the view. As a result, the view will be eventually re-drawn, but not before your current method is completed. Since your method with 'while' loop never ends, the view will never be re-drawn. Android TextView.setText() invoked & returned before Thread.sleep() blocks until sleep() returns. Why?

Community
  • 1
  • 1
Oleg Gryb
  • 5,122
  • 1
  • 28
  • 40
  • 1
    Thanks, what value do I use for field_width if my text view fills parent? And if default font is Droid Sans what value do I use for tface? – the_prole Jul 11 '14 at 10:21
  • 1
    getWidth will return the width of your view: http://developer.android.com/reference/android/view/View.html#getWidth%28%29 – Oleg Gryb Jul 11 '14 at 16:37
  • 1
    ... and you can use getTypeface: http://developer.android.com/reference/android/widget/TextView.html#getTypeface – Oleg Gryb Jul 11 '14 at 16:40
  • 1
    Thanks @Oleg Gryb, but now I'm getting a cryptic error I can't understand. I've posted the error and the code above. – the_prole Jul 12 '14 at 13:56