How to detect whether a user is typing or using the keyboard in your Android App?

In this video it shows how one can detect whether the user is using the keyboard for typing within an EditText widget. It uses addTextChangedListener and setOnFocusChangeListener listeners to detect the action of the user.

Once the action is detected, that is the user is typing, the respective status is updated in a TextView widget in the layout.

This concept is widely used in all the chat messenger Apps these days to show that a particular user is using the keyboard (typing). For not typing (Typing Stopped), it uses the setOnFocusChangeListener listener which updates the status to ‘Not Typing’ when the user moves away (changes focuses away from the EditText) to some other widget in the App’s layout.

I hope you like this video. For any questions, suggestions or appreciation please contact us at: https://programmerworld.co/contact/ or email at: programmerworld1990@gmail.com

Source Code:

package com.programmerworld.keyboardusage;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.text.Editable;
import android.text.TextWatcher;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

private TextView textViewStatus;
private EditText editTextKeyboardTesting;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

textViewStatus = findViewById(R.id.textViewStatus);
editTextKeyboardTesting = findViewById(R.id.editTextTextMultiLine);

editTextKeyboardTesting.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}

@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}

@Override
public void afterTextChanged(Editable s) {
textViewStatus.setText("User is typing ...");
}
});

editTextKeyboardTesting.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (!hasFocus){
textViewStatus.setText("User STOPPED");
}
}
});
}
}

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">

<TextView
android:id="@+id/textViewStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/keyboard_is_not_used"
android:textSize="24sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.331" />

<EditText
android:id="@+id/editTextTextMultiLine"
android:layout_width="247dp"
android:layout_height="124dp"
android:layout_marginStart="90dp"
android:layout_marginTop="45dp"
android:ems="10"
android:gravity="start|top"
android:hint="@string/type_here"
android:inputType="textMultiLine"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:autofillHints="" />

<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="167dp"
android:layout_marginTop="41dp"
android:text="@string/done"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textViewStatus" />

</androidx.constraintlayout.widget.ConstraintLayout>

<resources>
<string name="app_name">Keyboard usage</string>
<string name="keyboard_is_not_used">Keyboard is not Used ...</string>
<string name="type_here">Type here ...</string>
<string name="done">Done</string>
</resources>

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.programmerworld.keyboardusage">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>

</manifest>

apply plugin: 'com.android.application'

android {
compileSdkVersion 29
buildToolsVersion "29.0.3"

defaultConfig {
applicationId "com.programmerworld.keyboardusage"
minSdkVersion 26
targetSdkVersion 29
versionCode 1
versionName "1.0"

testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}

buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}

dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.1"

// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}

allprojects {
repositories {
google()
jcenter()
}
}

task clean(type: Delete) {
delete rootProject.buildDir
}

Leave a Reply

%d bloggers like this: