Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make Loading 3 dot animation in splash screen

Hi I am trying to make my 1st android app and I made a splash screen. However, I tried to add loading please wait at the bottom with the period increment every 2 seconds. I am not sure how to make it happen because the screen crashes because of this text.

   final TextView loadingText = (TextView)findViewById(R.id.loading_text);

    Thread splashTimer = new Thread(){
        public void run(){
            try{
                int splashTime = 0;
                while(splashTime < 6000){

                    sleep(100);

                        if(splashTime < 2000){
                            loadingText.setText("Loading.");
                        }
                        else if(splashTime >= 2000 && splashTime < 4000 ){
                            loadingText.setText("Loading..");
                        }else if (splashTime >= 4000){
                            loadingText.setText("Loading...");  
                        }
                        splashTime = splashTime + 100;

                }
                Intent intent = new Intent(MainActivity.this,myMainScreen.class);
                startActivity(intent);
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            finally{
                finish();
            }
        }
    };
    splashTimer.start();    
}  

here is my logcat

06-12 01:36:33.646: D/HyLog(29533): I : /data/font/config/sfconfig.dat, No such file or directory (2)
06-12 01:36:33.646: D/HyLog(29533): I : /data/font/config/dfactpre.dat, No such file or directory (2)
06-12 01:36:33.646: D/HyLog(29533): I : /data/font/config/sfconfig.dat, No such file or directory (2)
06-12 01:36:33.986: I/Adreno-EGL(29533): <qeglDrvAPI_eglInitialize:385>: EGL 1.4 QUALCOMM build:  ()
06-12 01:36:33.986: I/Adreno-EGL(29533): OpenGL ES Shader Compiler Version: E031.24.00.02
06-12 01:36:33.986: I/Adreno-EGL(29533): Build Date: 01/20/14 Mon
06-12 01:36:33.986: I/Adreno-EGL(29533): Local Branch: PMH2-KK_3.5-RB1-AU61-554722-586267-set2
06-12 01:36:33.986: I/Adreno-EGL(29533): Remote Branch: 
06-12 01:36:33.986: I/Adreno-EGL(29533): Local Patches: 
06-12 01:36:33.986: I/Adreno-EGL(29533): Reconstruct Branch: 
06-12 01:36:34.026: D/OpenGLRenderer(29533): Enabling debug mode 0
06-12 01:36:34.096: I/ActivityManager(29533): Timeline: Activity_idle id: android.os.BinderProxy@42b1e788 time:14063098
06-12 01:36:34.336: W/dalvikvm(29533): threadid=11: thread exiting with uncaught exception (group=0x41ae6e48)
06-12 01:36:34.336: E/AndroidRuntime(29533): FATAL EXCEPTION: Thread-2388
06-12 01:36:34.336: E/AndroidRuntime(29533): Process: com.sachinda.myfirstapp, PID: 29533
06-12 01:36:34.336: E/AndroidRuntime(29533): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.view.ViewRootImpl.checkThread(ViewRootImpl.java:6347)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.view.ViewRootImpl.requestLayout(ViewRootImpl.java:871)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.view.View.requestLayout(View.java:16472)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.view.View.requestLayout(View.java:16472)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.view.View.requestLayout(View.java:16472)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.view.View.requestLayout(View.java:16472)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.widget.RelativeLayout.requestLayout(RelativeLayout.java:352)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.view.View.requestLayout(View.java:16472)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.widget.TextView.checkForRelayout(TextView.java:6817)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.widget.TextView.setText(TextView.java:3947)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.widget.TextView.setText(TextView.java:3805)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at android.widget.TextView.setText(TextView.java:3780)
06-12 01:36:34.336: E/AndroidRuntime(29533):    at com.sachinda.myfirstapp.MainActivity$1.run(MainActivity.java:45)
06-12 01:36:36.316: I/Process(29533): Sending signal. PID: 29533 SIG: 9
like image 280
Sachi Avatar asked Jun 12 '14 05:06

Sachi


4 Answers

It is crashing because you are modifying ui component on a non UI thread add method like

private void setText(final CharSequence text) {
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ((TextView) findViewById(R.id.loading_text)).setText(text);
        }
    });
}

and modify your code to use that method

while(splashTime < 6000){

     sleep(100);

     if(splashTime < 2000){
         setText("Loading.");
     }
     else if(splashTime >= 2000 && splashTime < 4000 ){
         setText("Loading..");
     }else if (splashTime >= 4000){
         setText("Loading...");
     }
          splashTime = splashTime + 100;

 }
like image 72
nizammoidu Avatar answered Nov 01 '22 11:11

nizammoidu


I have achieved Loading 3 dots using coroutines lifecycle scope and recursion. Check out the below code. isCallAttended is boolean by default is false. Then you can set it true later in logic so that you could cancel coroutine.

private fun delayCallingAnimation() {
        lifecycleScope.launch {
            if(isCallAttended) {
                this.cancel()
                return@launch
            }
            delay(1000)
            mBinding.incomingCallView.tvCalling.text = "Calling."
            delay(1000)
            mBinding.incomingCallView.tvCalling.text = "Calling.."
            delay(1000)
            mBinding.incomingCallView.tvCalling.text = "Calling..."

            delayCallingAnimation()
     }
 }
like image 26
Shafiq ur Rehman Avatar answered Nov 01 '22 12:11

Shafiq ur Rehman


What you are doing here is updating the UI elements inside a thread, which isn't allowed!

What you will have to do is use Handlers:

new Handler().post(new Runnable() {
    @Override
    public void run() {
        // Code here will run in UI thread
    }
});

This will solve the purpose.

like image 34
sidhanshu Avatar answered Nov 01 '22 11:11

sidhanshu


May be it helps anybody :) I found 2 solutions how animate dots in TextView ending ("...").

Common code

Common function for both solutions

private fun getDotAnimator(
    textView: TextView,
    dotCount: Int,
    list: List<CharSequence>
): ValueAnimator {
    val valueTo = dotCount + 1

    return ValueAnimator.ofInt(0, valueTo).apply {
        this.interpolator = LinearInterpolator()
        this.duration = textView.context.resources.getInteger(R.integer.dots_anim_time).toLong()
        this.repeatCount = ObjectAnimator.INFINITE
        this.repeatMode = ObjectAnimator.RESTART

        addUpdateListener {
            val value = it.animatedValue as? Int


            /**
             * Sometimes [ValueAnimator] give a corner value.
             */
            if (value == null || value == valueTo) return@addUpdateListener

            textView.text = list.getOrNull(value)
        }
    }
}

In XML:

<string name="dot" translatable="false">.</string>

<integer name="dots_anim_time">1200</integer>

First solution: simple adding dots to string end

fun getDotsAnimator(textView: TextView?, @StringRes stringId: Int): ValueAnimator? {
    val context = textView?.context ?: return null

    val simpleText = context.getString(stringId)
    val dotText = context.getString(R.string.dot)
    val dotCount = 3

    val textList = mutableListOf<String>()
    for (i in 0 until dotCount + 1) {
        val text = StringBuilder(simpleText).apply {
            repeat(i) { append(dotText) }
        }.toString()

        textList.add(text)
    }

    return getDotAnimator(textView, dotCount, textList)
}

But it has disadvantage. If in your XML file TextView has android:gravity="center" it will looks ugly. Because text in textList has different lenght and also has different center. Use this solution only with android:gravity="start".

Second solution: use spannable string

fun getDotsSpanAnimator(textView: TextView?, @StringRes stringId: Int): ValueAnimator? {
    val context = textView?.context ?: return null

    val simpleText = context.getString(stringId)
    val dotText = context.getString(R.string.dot)
    val dotCount = 3

    val resultText = StringBuilder(simpleText).apply {
        repeat(dotCount) { append(dotText) }
    }.toString()

    val textList = mutableListOf<SpannableString>()
    for (i in 0 until dotCount + 1) {
        val spannable = SpannableString(resultText)

        val start = resultText.length - (dotCount - i)
        val end = resultText.length
        val flag = Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
        spannable.setSpan(ForegroundColorSpan(Color.TRANSPARENT), start, end, flag)

        textList.add(spannable)
    }

    return getDotAnimator(textView, dotCount, textList)
}

This solution will work perfect with every android:gravity.

Use in code

private val dotsAnimator by lazy {
    getDotsSpanAnimator(loadingText, R.string.dialog_text_loading)
}

override fun onResume() {
    super.onResume()
    dotsAnimator?.start()
}

override fun onPause() {
    super.onPause()
    dotsAnimator?.pause()
}
like image 23
SerjantArbuz Avatar answered Nov 01 '22 13:11

SerjantArbuz