Search code examples
androidandroid-layoutandroid-studioandroid-animationtextview

How can i use HTextView scale textview effect (com.hanks.htextview.HTextView) as multiline effect?


At the moment it works with single line and when I input a text with more than one line, the application crashes.

MainActivity:

    HTextView tvQuestion_hanks = (HTextView) findViewById(R.id.tvQs_hanks);
    tvQuestion_hanks.setAnimateType(HTextViewType.SCALE);
    tvQuestion_hanks.animateText("Hello world");

Layout:

    <RelativeLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:htext="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent">


         <com.hanks.htextview.HTextView

                android:id="@+id/tvQs_hanks"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_alignParentLeft="true"
                android:layout_alignParentStart="true"
                android:layout_alignParentTop="true"
                android:layout_marginTop="16dp"
                android:textColor="#000000"
                android:textSize="17dp"
                android:text="Question"
                htext:animateType="scale"
                android:gravity="start">

         </com.hanks.htextview.HTextView>

     </RelativeLayout>

I've tried different layout codes like;

     android:lines="5"
     android:maxLines="5"
     android:nestedScrollingEnabled="true"

but it didn't work . This is my logcat just after i press the button and a multiline text is sent to HTextView (as I said the app crashes) :

            02-13 20:01:18.074 4456-4456/com.example.moham.myapplication D/AndroidRuntime: 
            Shutting down VM
            02-13 20:01:18.074 4456-4456/com.example.moham.myapplication W/dalvikvm: 
            threadid=1: thread exiting with uncaught exception (group=0x94caeb20)
            02-13 20:01:18.074 4456-4456/com.example.moham.myapplication E/AndroidRuntime: 
            FATAL EXCEPTION: main
                                                                           Process: com.example.moham.myapplication, PID: 
           4456
                                                                           java.lang.ArrayIndexOutOfBoundsException: 
           length=100; index=100
                                                                               at 
           com.hanks.htextview.animatetext.HText.prepareAnimate(HText.java:88)
                                                                               at 
           com.hanks.htextview.animatetext.HText.animateText(HText.java:74)
                                                                               at 
           com.hanks.htextview.HTextView.animateText(HTextView.java:107)
                                                                               at 
           com.example.moham.myapplication.MainActivity$1.onClick(MainActivity.java:34)
                                                                               at 
           android.view.View.performClick(View.java:4438)
                                                                               at 
           android.view.View$PerformClick.run(View.java:18422)
                                                                               at 
           android.os.Handler.handleCallback(Handler.java:733)
                                                                               at 
           android.os.Handler.dispatchMessage(Handler.java:95)
                                                                               at android.os.Looper.loop(Looper.java:136)
                                                                               at 
           android.app.ActivityThread.main(ActivityThread.java:5019)
                                                                               at java.lang.reflect.Method.invokeNative(Native 
           Method)
                                                                               at 
           java.lang.reflect.Method.invoke(Method.java:515)
                                                                               at 
           com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:779)
                                                                               at 
           com.android.internal.os.ZygoteInit.main(ZygoteInit.java:595)
                                                                               at dalvik.system.NativeStart.main(Native 
           Method)

HTextView GitHub page: https://github.com/hanks-zyh/HTextView

HTextView GitHub page2: https://github.com/yikwing/HTextView


Solution

  • I've solved this problem , not just by means of it's right way , but it finally worked . As "Re'em" noticed in the comments , this is a bug from the HTextView main library so i asked it's developers to solve it , but i was in a big hurry , so i solved it this way :

    As the HTextView is only able to handle a one-line text entry , I wrote a Function in order to measure the approximate possible amount of chars along the screen-width by :

    First ) Finding text width in pixels.

    Second ) Dividing it into text length.

        PixelPerChar = TXT_width / TXT.length();
    

    And then , in order to approximate possible amount of chars along the screen-width , i divided screen-width into PixelPerChar , so the result is an approximate number of chars that fit correctly along the screen and it won't exceed a one-line text .

        PossibleChars = lcdWidth() / PixelPerChar;
    

    The next step is to adding HtextViews to a LinearLayout one after another , Substring the text into one-line serries at the same time , and send it to each HTextView created , until the text becomes shorter than the screen-width .

    Take a look at the full function code : (Qs = Question = text :)

    private void QsPrint(String Qs){
    
        LinearLayout LinearLay1 = (LinearLayout) findViewById(R.id.LinearLay1);
        LinearLay1.removeAllViews();
    
    
        int Qswidth = QsWidth(tvQuestion_hanks , Qs);
    
        DisplayMetrics metrics = MainMenu.this.getResources().getDisplayMetrics();
        int lcdwidth = metrics.widthPixels;
        int lcdheight = metrics.heightPixels;
    
    
    
        int PIXperCHAR = Qswidth / Qs.length();
        SubStart = 0;
        SubEnd = lcdwidth / PIXperCHAR;
        sub1 = "";
    
    
        while (true)
        {
    
    
            HTextView tvQs_Hanks_multiline = new HTextView(MainMenu.this);
    
            RelativeLayout.LayoutParams params1 = new RelativeLayout
                    .LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
    
    
            tvQs_Hanks_multiline.setLayoutParams(params1);
            tvQs_Hanks_multiline.setTextSize(TypedValue.COMPLEX_UNIT_DIP, PixelToDp((int)(tvQuestion_hanks.getTextSize())));
            tvQs_Hanks_multiline.setAnimateType(HTextViewType.SCALE);
            LinearLay1.addView(tvQs_Hanks_multiline);
    
            sub1 = "";
            if(Qswidth >= lcdwidth) {
                    try {
                        sub1 = Qs.substring(SubStart, SubEnd);
                    } catch (Exception e) {
                        QsPrintSubString(Qs);
                    }
    
    
                while (QsWidth(tvQs_Hanks_multiline , sub1) >= lcdwidth){
                    SubEnd --;
                    sub1 = Qs.substring(SubStart, SubEnd);
                }
    
                SubEnd -=4; // For spacing before/after the TXT
                sub1 = Qs.substring(SubStart, SubEnd);
                tvQs_Hanks_multiline.animateText("   "+sub1+"");
            }
            else if(Qswidth < lcdwidth){
                sub1 = Qs;
                tvQs_Hanks_multiline.animateText("   " + sub1 + "");
                break;
            }
    
    
    
    
            if(Qswidth >= lcdwidth) {
    
                Qs = Qs.substring(SubEnd, Qs.length());
                Qswidth = QsWidth(tvQs_Hanks_multiline , Qs);
                PIXperCHAR = Qswidth / Qs.length();
                SubStart = 0;
                if(Qswidth >= lcdwidth) {
                    SubEnd = lcdwidth / PIXperCHAR;
                }
            }
    
    
    
        }
    
    }
    

    I used this function to calculate the text width in pixels :

    private int QsWidth(TextView tv , String Question){
    
        String Qs = Question;
        Rect bound = new Rect();
        Paint textPaint = tv.getPaint();
        textPaint.getTextBounds(Qs, 0, Qs.length(), bound);
        int QsWidth = bound.width();
    
        return QsWidth;
    }
    

    Pixel to dp convertor function :

    public static int PixelToDp(int px)
    {
        return (int) (px / Resources.getSystem().getDisplayMetrics().density);
    }
    

    And finally , i used this function because some times the text length is a special amount of chars that the "QsPrint" function can not Substring it correctly and crashes :( , so i used this function .

    It works so simple , it continuously reduces the SubEnd and tests the Substring again.

    the function will keep running until it doesn't crash any more :)

    private void QsPrintSubString(String Qs){
    
        SubEnd--;
        try {
            sub1 = Qs.substring(SubStart, SubEnd);
        }catch (Exception e){
            QsPrintSubString(Qs);
        }
    }
    

    XML layout:

    ( tvQs_hanks you see below is almost useless , it's just needed in "QsWidth()" function in order to calculate the text width before we create any HTextView in our LinearLayout )

    <RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:htext="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    
    
    
    
                <LinearLayout
                    android:id="@+id/LinearLay1"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_marginTop="20dp"
                    android:orientation="vertical">
    
    
                </LinearLayout>
    
                <com.hanks.htextview.HTextView
                    android:id="@+id/tvQs_hanks"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:text="Question"
                    android:textColor="#000000"
                    android:textSize="17dp"
                    android:visibility="gone"
                    htext:animateType="scale">
    
                </com.hanks.htextview.HTextView>
    
     </RelativeLayout>