Build An Anagram Finder Android App

176 Views

In this tutorial explains you’ll learn how to create a simple but great application to find the anagrams of a sequence of typed letters.

PLEASE NOTE: This tutorial has been written using Android Studio 3.5.x and Java

What are we going to build?

First of all, what is an Anagram? The answer comes from Wikipedia:

An anagram is a word or phrase formed by rearranging the letters of a different word or phrase, typically using all the original letters exactly once.

Wikipedia

So, our Anagram Finder app will ask us to enter some characters and click a Check button that will start the anagram search for these letters.
The application will rely on a dictionary of words included in the project when searching for anagrams.
Once the search is complete, the app will either display the anagrams found or a message that will inform you that no anagrams can be found for the letters you entered.

The Android project

Let’s start by creating a new project. Open Android Studio and click + Start a new Android Studio project.

Select the Empty Activity and click the Next button.

Type a name for your project – I’ve set Anagrams for the sake of this tutorial.

When you set an Android Studio’s project name, it’s always good to leave no spaces between words.

Type the package name you want for your application, select the location of the files and click the Finish button.

When Android Studio will be done on creating your project, expand the res/layout folder, in order to access the activity_main.xml file.

The App design

The layout of the activity_main.xml file (inside the res/layout folder) is pretty simple, it’s just an EditText, a Button and a TextView. In order for you to build it, open the activity_main.xml in the Text tab:

Replace the existing code with the following one:

<?xml version="1.0" encoding="utf-8"?>
<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"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:focusable="true"
    android:focusableInTouchMode="true"
    tools:context=".MainActivity">

    <EditText
        android:id="@+id/inputTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginStart="10dp"
        android:layout_marginTop="20dp"
        android:layout_marginEnd="10dp"
        android:backgroundTint="#252525"
        android:hint="Type some character..."
        android:textColor="#252525"
        android:textSize="14sp" />

    <TextView
        android:id="@+id/resultsTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_below="@+id/inputTxt"
        android:layout_marginStart="10dp"
        android:layout_marginTop="10dp"
        android:layout_marginEnd="120dp"
        android:textColor="#252525"
        android:textSize="12sp" />

    <Button
        android:id="@+id/checkButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/resultsTxt"
        android:layout_alignEnd="@+id/inputTxt"
        android:layout_gravity="center_horizontal"
        android:text="Check"
        android:textAllCaps="false" />

</RelativeLayout>

Coding the application

The first thing to do is to download a file called words from here. This file contains about 10,000 most frequently used words in the English language and it’ll be used by the app to search for anagrams.

Once you’ve downloaded the words file on your Desktop, enter the app/src/main directory from your project folder (it should be Anagrams, as the name you gave to the app), and create a new folder called assets.

Copy the words file into that assets folder, and get back yo your Android Studio project, you should see your new folder and its file in panel on the left side. Double-slick on the words file to see it.

Now expand the Gradle Scripts section and open the build.gradle (Module:app) file. We have to add a couple of lines inside the dependencies code in order to implement the Butter Knife library. This will make the retrieval of the views defined within the XML file easier.

// Butter Knife
 implementation 'com.jakewharton:butterknife:10.2.0'
 annotationProcessor 'com.jakewharton:butterknife-compiler:10.2.0'

We have to add one mode little code inside the Android brackets, so the application will be able to use Java 8 Lambdas and make Butter Knife work properly:

compileOptions {
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
 }

Here’s how your build.gradle file should look like:

It’s time to create a new Java Class and call it Anagram, which will help us handle all functions to make our app work. Right-click over the first folder with your package name inside the java directory, and select New -> Java Class.

In the popup window that will show up, type Anagram in the Name field and hit the OK button:

Here’s the code that you have to paste into your brand new Anagram.java file:

import android.content.Context;
import android.util.Log;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

class Anagram {

   // List of words loaded for searching anagrams
   private static final List<String>WORDS = new ArrayList<>();

   // Boolean indicating if words are loaded or no
   private static boolean LOADED = false;

   static boolean isLoaded() {
      return LOADED;
   }

   // Load the 'words' file from assets
   static void loadWords(Context context) {

      try (BufferedReader buf = new BufferedReader(new InputStreamReader(context.getAssets().open("words")))) {

         String line;

         // Read file line by line to store words
         while ((line = buf.readLine()) != null) {
            // Set words uppercase
            WORDS.add(line.toUpperCase());
         }
         LOADED = true;
      } catch (IOException e) { Log.i("log-", "Error: " + e); }

   }

   // Compare two strings and return true if they have same letters
   private static boolean sameLetters(String a, String b) {
      if (a == null)
         return b == null;
      if (b == null)
         return false;

      char[] left = a.toCharArray();
      char[] right = b.toCharArray();

      // Sort caracters of each String
      Arrays.sort(left);
      Arrays.sort(right);

      // Compare both sorted arrays
      return Arrays.equals(left, right);
   }

   // Return all anagrams for entered letters
   static List < String > listWords(String letters) {
      List < String > list = new ArrayList < > ();

      for (String word: WORDS) {
         if (sameLetters(word, letters)) { list.add(word); }
      }

      return list;
   }
}

You may check the comments to understand what this class does. Basically, The loadWords function will read the content of the dict file line-by-line and place them in the memory of your device.
The sameLetters Boolean method will compare two strings and verify that they are anagrams.

Let’s switch to the MainActivity.java file and get ready to make our app alive. Place this code right below the package name of your java file:

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.annotation.SuppressLint;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;

import java.util.List;

import butterknife.ButterKnife;

public class MainActivity extends AppCompatActivity {

   EditText inputTxt;
   Button checkButton;
   TextView resultsTxt;
   Dialog waitDialog;

   Context ctx = this;



   //-----------------------------------------------
   // MARK - ON CREATE
   //-----------------------------------------------
   @Override
   protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);


      //-----------------------------------------------
      // MARK - INITIALIZE VIEWS
      //-----------------------------------------------
      inputTxt = findViewById(R.id.inputTxt);
      resultsTxt = findViewById(R.id.resultsTxt);
      checkButton = findViewById(R.id.checkButton);


      // Init ButterKnife
      ButterKnife.bind(this);

      // Disable the checkButton because words are not loaded from assets
      checkButton.setEnabled(Anagram.isLoaded());


      // Call function that loads words from assets
      loadWords();



      //-----------------------------------------------
      // MARK - CHECK BUTTON
      //-----------------------------------------------
      checkButton.setOnClickListener(view -> {
         String text = inputTxt.getText().toString().toUpperCase();

         if (!text.matches("")) {
            final String text2 = text.trim();

            if (!"".equals(text2)) {
               showLoadingAlert();

               new Thread(() -> {
                  final List < String > words = Anagram.listWords(text); // we search anagrams for entered letters in separate thread

                  runOnUiThread(() -> {
                     hideLoadingAlert();

                     // Display the results
                     displayResult(words);
                  });
               }).start();

            }// ./ If
         }// ./ If
      });


   }// ./ onCreate()



   //-----------------------------------------------
   // MARK - LOAD WORDS
   //-----------------------------------------------
   private void loadWords() {
      new Thread(() -> {
         Anagram.loadWords(ctx);

         runOnUiThread(() -> {
            checkButton.setEnabled(Anagram.isLoaded());
         });
      }).start();
   }

   //-----------------------------------------------
   // MARK - SHOW/HIDE LOADING ALERT
   //-----------------------------------------------
   private void showLoadingAlert() { waitDialog = new AlertDialog.Builder(this).setMessage("Loading...").create(); }
   private void hideLoadingAlert() { waitDialog.dismiss(); }


   //-----------------------------------------------
   // MARK - DISPLAY RESULTS
   //-----------------------------------------------
   @SuppressLint("SetTextI18n")
   private void displayResult(List < String > words) {
      if (words.isEmpty()) { resultsTxt.setText("NO RESULT");
      } else {
         StringBuilder sb = new StringBuilder();
         for (String word: words) { sb.append(word).append("\n"); }
         resultsTxt.setText(sb);
      }
   }

}// ./ end

You may check the comments to learn how this code works, or just get excited and hit the green run button in Android Studio to test your new app on your device.

If you’ve done everything correctly, you may type “blowing” and click the Check button, you’ll get something like this:

Try some more words to discover their anagrams, you can now challenge your friends on scramble games!

Conclusion

That’s all for this tutorial, you have learned how to create a cool app to scramble some letters into anagrams in Android.

Hope you enjoyed this article, feel free to post comments about it. You can also download the full Android Studio project of this article, just click the link below:

Download the Android Studio project

Buy me a coffee - XScoder - thanks for your support
Your support will be highly appreciated 😉