0% found this document useful (0 votes)
136 views1 page

How To Create Android Translation App

How to Create Android Translation App From Scratch with Yandex Translation API

Uploaded by

FITSUM Biruk
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
136 views1 page

How To Create Android Translation App

How to Create Android Translation App From Scratch with Yandex Translation API

Uploaded by

FITSUM Biruk
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Help us test our new app update Live on Play Store

Забудь про баны по IP


Больше не придется перебирать и тестировать прокси-сервисы. С ASTROPROXY
остаются навсегда

Astroproxy ПОДАТЬ ЗАЯВКУ


Share 0

Like 0
NG APACHE
NOW TRENDING:
PDFBOX IN ANDROID HOW TO CREATE AND ADD CONTENT TO PDF FILE WITH APACHE PDFBOX IN ANDROID HOW TO READ PDF FILE WITH APACHE PDFBOX IN AN
Tweet

Save

ANDROID CREATE APP FROM SCRATCH TUTORIALS  CODE SNIPPETS  TEMPLATES HOT LIBRARIES  BUY CODE

 Home  Create App From Scratch 


Search the site 
How to Create Android Translation App From Scratch with Yandex Translation API

HOW TO CREATE ANDROID TRANSLATION


APP FROM SCRATCH WITH YANDEX
TRANSLATION API
In this episode on how to create android
translation app from scratch with
Yandex translation API, we are going to
explore what it takes to build an android
translation app.

There are many android translation apps


out there. I know you must have used
one.

But imagine if you were tasked to create


your own translation app, how would
you go about it?

If you are not sure of how to build a


translation app or you want to build your own translation app and publish it in Google Play
Store following this tutorial will provide a valuable insight and knowledge on how you can
achieve it.

We are going to use Yandex Translation API for translating user entered words.

There are many companies that offer translation service and their prices vary. But the three
most popular translation services are Google Cloud Vision Translation, Microsoft Cloud
BUY SOURCE CODES FOR $10
Translation and Yandex.
$10.00 – Buy Now
You can read more about different companies that offer translation services with a simple
google search.
You can contact us for any of these source code

WHY DID WE CHOOSE YANDEX TRANSLATION API? Android Translation App

Android Dictionary App


All the translation service companies I checked, Yandex has the highest free-quote per day
or month. Besides that, their API documentation is simple and easier to use. Android Invoice and Estimation App

Android Drawing App


In the course of writing this tutorial, I have tested Microsoft and Google translation APIs but
Android Note App
we will focus on Yandex. If you need support for any other services you can contact us.
Android Note with Room Database

ANDROID PROGRAMMING TOPICS WE WILL COVER HERE Android Youtube Player App

Android Currency Converter


1. How to use Retrofit for Android Network calls
Android Weather App
2. How to use Retrofit logger to log your request and response object
3. How to use android RecyclerView with Pattern pattern Android Voice Recorder App
4. How to delete RecyclerView item Android Music Player App
5. How to use android Room, LiveData and ViewModel
Android Dentist Booking App
6. How to use Android text-to-speech
7. How to use android voice recognition Android Scientific Calculator App

8. How to share content in android Android Pill Reminder App


9. How to populate spinner widget with remote data source
Android Quote App
10. Clean UI
Android Restaurant Table Booking App

TRANSLATION APP FEATURES Android Ecommerce App

Android Quiz with SQLite Database


1. Intro page Android Quiz with Web Admin
2. List of saved translations
Android Online Survey App
3. Delete saved translation
4. About us information Android Food ordering App
5. Translate text in up to 90 different languages Android Car Rental App
6. Copy text
Android Delivery App
7. Delete text
8. Enter text with voice Android Multi Restaurant Booking App

9. Convert text to speech Android PDF Reader App


10. Paste text Android Taxi Booking App
11. Share translated text
Android Screen Recorder App
12. Save Translated text
13. Clean design Android Chat App
14. Well commented code
15. Switch languages
RECENT BLOG POST
Hello World Program in C++ with
HAND SKETCH OF OUR ANDROID TRANSLATION APP Code::Blocks
How to remove pages from PDF Document
in android with Apache PDFBox
How to convert Image to PDF File Using
Apache PDFBox in Android
How to create and add content to PDF File
with Apache PDFBox in Android
How to read PDF File with Apache PDFBox in
Android
How to create Android PDF Viewer
Application
How to change Android Navigation Drawer
Background color in Kotlin
How to create Android Component
Navigation in Kotlin
How to combine Navigation Drawer and
Bottom Navigation in the same Activity in
Kotlin
ANDROID TRANSLATION APP SCREENSHOTS How to navigate to a new Activity in Android
Component Navigation in Kotlin

ANDROID TRANSLATOR APP VIDEO DEMO

How to Create Android Translator App from Scratch

1. CREATE A NEW ANDROID PROJECT


Open Android Studio
Go to file menu
Select  new
Enter project name
Enter activity name
Keep other default settings
Click on finish button to create a new android project

2. ADD LIBRARY DEPENDENCIES IN BUILD.GRADLE FILE


For the dependencies, we will use several android third party libraries to make our work
much easier and saves time.

The dependency section of build.gradle is well commented. The comments give us an idea
of what each or group of libraries do.

Open build.gradle file and paste the content below.

1. dependencies {
2. implementation fileTree(dir: 'libs', include: ['*.jar'])
3. implementation 'androidx.appcompat:appcompat:1.0.2'
4. implementation 'androidx.constraintlayout:constraintlayout:2.0.0-
alpha2'
5. implementation 'com.google.android.material:material:1.1.0-alpha01'
6.
7. //Recycler view
8. implementation 'androidx.recyclerview:recyclerview:1.0.0'
9.
10. //Room persistence data
11. implementation "android.arch.persistence.room:rxjava2:1.1.1"
12. implementation 'androidx.room:room-common:2.1.0-alpha03'
13. implementation 'androidx.room:room-runtime:2.1.0-alpha03'
14. annotationProcessor "androidx.room:room-compiler:2.1.0-alpha03"
15. implementation 'android.arch.lifecycle:livedata:1.1.1'
16.
17. //Live Model
18. implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
19. implementation "androidx.lifecycle:lifecycle-viewmodel:2.0.0"
20. implementation "androidx.lifecycle:lifecycle-runtime:2.0.0"
21. annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.0.0"
22.
23. //Network call - Retrofit
24. implementation 'com.squareup.retrofit2:retrofit:2.4.0'
25. implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
26. implementation 'com.google.code.gson:gson:2.8.5'
27. implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
28. implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'
29. implementation "com.jakewharton.retrofit:retrofit2-rxjava2-
adapter:1.0.0"
30.
31. //logging Networking call
32. implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
33. implementation 'com.squareup.okhttp3:okhttp:3.10.0'
34.
35. //fast Adapter
36. implementation 'com.mikepenz:fastadapter:3.3.1'
37.
38. // dependency injection
39. implementation "com.google.dagger:dagger:2.16"
40. annotationProcessor "com.google.dagger:dagger-compiler:2.16"
41. annotationProcessor "com.google.dagger:dagger-android-processor:2.16"
42. implementation "com.google.dagger:dagger-android-support:2.16"
43.
44. //Reactive
45. implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
46. implementation 'io.reactivex.rxjava2:rxjava:2.2.4'
47.
48. //debug db
49. debugImplementation 'com.amitshekhar.android:debug-db:1.0.3'
50.
51. //Runtime permission
52. implementation 'com.karumi:dexter:5.0.0'
53.
54. testImplementation 'junit:junit:4.12'
55. androidTestImplementation 'androidx.test:runner:1.1.1-alpha01'
56. androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1-
alpha01'
57. }

dependencies { 
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.0.2'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alph
implementation 'com.google.android.material:material:1.1.0-alpha01'

//Recycler view
implementation 'androidx.recyclerview:recyclerview:1.0.0'

//Room persistence data


implementation "android.arch.persistence.room:rxjava2:1.1.1"
implementation 'androidx.room:room-common:2.1.0-alpha03'
implementation 'androidx.room:room-runtime:2.1.0-alpha03'
annotationProcessor "androidx.room:room-compiler:2.1.0-alpha03"
implementation 'android.arch.lifecycle:livedata:1.1.1'

//Live Model
implementation "androidx.lifecycle:lifecycle-extensions:2.0.0"
implementation "androidx.lifecycle:lifecycle-viewmodel:2.0.0"
implementation "androidx.lifecycle:lifecycle-runtime:2.0.0"
annotationProcessor "androidx.lifecycle:lifecycle-compiler:2.0.0"

//Network call - Retrofit


implementation 'com.squareup.retrofit2:retrofit:2.4.0'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
implementation 'com.google.code.gson:gson:2.8.5'
implementation 'com.squareup.retrofit2:converter-scalars:2.3.0'
implementation 'com.squareup.retrofit2:adapter-rxjava:2.4.0'
implementation "com.jakewharton.retrofit:retrofit2-rxjava2-adapter:1.

//logging Networking call


implementation 'com.squareup.okhttp3:logging-interceptor:3.10.0'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'

//fast Adapter
implementation 'com.mikepenz:fastadapter:3.3.1'

// dependency injection
implementation "com.google.dagger:dagger:2.16"
annotationProcessor "com.google.dagger:dagger-compiler:2.16"
annotationProcessor "com.google.dagger:dagger-android-processor:2.16"
implementation "com.google.dagger:dagger-android-support:2.16"

//Reactive
implementation 'io.reactivex.rxjava2:rxandroid:2.1.0'
implementation 'io.reactivex.rxjava2:rxjava:2.2.4'

//debug db
debugImplementation 'com.amitshekhar.android:debug-db:1.0.3'

//Runtime permission
implementation 'com.karumi:dexter:5.0.0'

testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1-alpha01'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1
}

3. UPDATE COLORS.XML
Open res folder > strings.xml and add the code below to it.

1. <?xml version="1.0" encoding="utf-8"?>


2. <resources>
3. <color name="colorPrimary">#4992F9</color>
4. <color name="colorPrimaryDark">#1E79F9</color>
5. <color name="colorBackground">#6fa7f6</color>
6. <color name="colorAccent">#D81B60</color>
7. <color name="colorBlack">#000000</color>
8. <color name="colorWhite">#ffffff</color>
9. <color name="colorDark">#999999</color>
10. <color name="colorDarker">#555555</color>
11. <color name="colorLine">#f1f1f1</color>
12. <color name="colorDarkHighlight">#AC8333</color>
13. <color name="colorHighlight">#F9AE1E</color>
14. </resources>

<?xml version="1.0" encoding="utf-8"?> 


<resources>
<color name="colorPrimary">#4992F9</color>
<color name="colorPrimaryDark">#1E79F9</color>
<color name="colorBackground">#6fa7f6</color>
<color name="colorAccent">#D81B60</color>
<color name="colorBlack">#000000</color>
<color name="colorWhite">#ffffff</color>
<color name="colorDark">#999999</color>
<color name="colorDarker">#555555</color>
<color name="colorLine">#f1f1f1</color>
<color name="colorDarkHighlight">#AC8333</color>
<color name="colorHighlight">#F9AE1E</color>
</resources>

4. UPDATE STYLES.XML
1. <resources>
2.
3. <!-- Base application theme. -->
4. <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
5. <!-- Customize your theme here. -->
6. <item name="colorPrimary">@color/colorPrimary</item>
7. <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
8. <item name="colorAccent">@color/colorAccent</item>
9. </style>
10.
11. <style name="AppTheme.NoActionBar">
12. <item name="windowActionBar">false</item>
13. <item name="windowNoTitle">true</item>
14. </style>
15.
16. <style name="AppTheme.AppBarOverlay"
parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
17.
18. <style name="AppTheme.PopupOverlay"
parent="ThemeOverlay.AppCompat.Light" />
19.
20. </resources>

<resources> 

<!-- Base application theme. -->


<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
</style>

<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>

<style name="AppTheme.AppBarOverlay" parent="ThemeOverlay.AppCompat.D

<style name="AppTheme.PopupOverlay" parent="ThemeOverlay.AppCompat.Li

</resources>

5. UPDATE STRINGS.XML
Open res folder > strings.xml and add the code below to it.

1. <resources>
2. <string name="app_name">Android Translation</string>
3. <string
name="title_activity_list_translation">ListTranslationActivity</string>
4. </resources>

<resources> 
<string name="app_name">Android Translation</string>
<string name="title_activity_list_translation">ListTranslationActivit
</resources>

APPLICATION PROJECT STRUCTURE


Before we go into different files we will create for this project, below is a structure I have
created.

The translator app features are separated by folders. We will also include folders/packages
for related classes.

Below is how the project is structured. The storetranslation and texttranslation house store
translated list page and the main translator page.

1. di folder is for dependency injection code


2. base folder will contain BaseViewModels and BaseActivity class
3. adapter folder will contain Adapter classes
4. repository folder will contain Data Repository classes
5. utils folder will contain utility classes

GET TRANSLATION API KEY FROM YANDEX


Before we go deeper into the code, we need to obtain a translation API key which we will
use to send translation request to Yandex server and obtain a response which will contain
our targeted language if successful or an error that will indicate that something has gone
wrong.

Go to Yandex Translation Page

Click on Get Free API Key. 

You will be prompted to sign up or login if you have not done any of them. When you final
login, you will be navigated to a page like below.

You will see your translation API key. Copy it and keep in a safe place. We will use it later in
the project.

Please not that when you are on a free quota in Yandex you don’t need to add payment to
your account. Once you add payment you will automatically lose your free quota.

WHAT HAPPENS FROM HERE?


Since this is a long tutorial, we will focus on the core feature of android translation app and
leave some other features out. Please note that the full source code is not free. If you want
to download the full source code and tutorial, see more details at the end of this page.

CREATE A NEW ACTIVITY FOR TRANSLATION


We need a new activity class and its layout file for our main translation UI.

First, create a new folder and name it texttranslation. Right click on the folder and go to
New > Activity > Empty Activity.

Name the activity file TextTranslationActivity.java.

Open the activity_text_translation.xml. In the layout file, we will add all the widgets and
ViewGroup our UI requires. Copy and paste the code below inside the layout file.

1. <?xml version="1.0" encoding="utf-8"?>


2. <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
3. xmlns:app="http://schemas.android.com/apk/res-auto"
4. xmlns:tools="http://schemas.android.com/tools"
5. android:id="@+id/layout_text_translate"
6. android:layout_width="match_parent"
7. android:layout_height="match_parent"
8. android:background="#E0E0E0"
9. tools:context=".texttranslation.TextTranslationActivity">
10.
11. <androidx.constraintlayout.widget.Guideline
12. android:id="@+id/guideline2"
13. android:layout_width="wrap_content"
14. android:layout_height="wrap_content"
15. android:orientation="horizontal"
16. app:layout_constraintGuide_percent="0.47" />
17.
18. <androidx.cardview.widget.CardView
19. android:id="@+id/cardView"
20. android:layout_width="0dp"
21. android:layout_height="0dp"
22. android:layout_marginBottom="8dp"
23. android:layout_marginEnd="16dp"
24. android:layout_marginLeft="16dp"
25. android:layout_marginRight="16dp"
26. android:layout_marginStart="16dp"
27. android:layout_marginTop="16dp"
28. app:layout_constraintBottom_toTopOf="@+id/guideline2"
29. app:layout_constraintEnd_toEndOf="parent"
30. app:layout_constraintStart_toStartOf="parent"
31. app:layout_constraintTop_toTopOf="parent">
32.
33. <androidx.constraintlayout.widget.ConstraintLayout
34. android:layout_width="match_parent"
35. android:layout_height="match_parent"
36. android:padding="5dp">
37.
38. <androidx.appcompat.widget.AppCompatEditText
39. android:id="@+id/original_text_et"
40. android:layout_width="0dp"
41. android:layout_height="0dp"
42. android:layout_marginBottom="8dp"
43. android:background="@drawable/border"
44. android:gravity="top"
45. android:hint="Touch and Start Typing..."
46. android:padding="8dp"
47. android:scrollbars="vertical"
48. android:textAppearance="@style/TextAppearance.AppCompat.Body
49. app:layout_constraintBottom_toTopOf="@+id/paste_btn"
50. app:layout_constraintEnd_toEndOf="parent"
51. app:layout_constraintStart_toStartOf="parent"
52. app:layout_constraintTop_toTopOf="parent" />
53.
54.
<com.google.android.material.floatingactionbutton.FloatingActionButton
55. android:id="@+id/paste_btn"
56. android:layout_width="wrap_content"
57. android:layout_height="wrap_content"
58. android:layout_marginBottom="8dp"
59. android:layout_marginEnd="8dp"
60. android:layout_marginLeft="8dp"
61. android:layout_marginRight="8dp"
62. android:layout_marginStart="8dp"
63. android:clickable="true"
64. app:backgroundTint="@color/colorWhite"
65. app:layout_constraintBottom_toBottomOf="parent"
66. app:layout_constraintEnd_toStartOf="@+id/guideline6"
67. app:layout_constraintStart_toStartOf="@+id/guideline4"
68. app:srcCompat="@drawable/ic_content_paste" />
69.
70.
<com.google.android.material.floatingactionbutton.FloatingActionButton
71. android:id="@+id/cancel_btn"
72. android:layout_width="wrap_content"
73. android:layout_height="wrap_content"
74. android:layout_marginBottom="8dp"
75. android:layout_marginEnd="8dp"
76. android:layout_marginLeft="8dp"
77. android:layout_marginRight="8dp"
78. android:layout_marginStart="8dp"
79. android:clickable="true"
80. app:backgroundTint="@color/colorWhite"
81. app:layout_constraintBottom_toBottomOf="parent"
82. app:layout_constraintEnd_toStartOf="@+id/guideline7"
83. app:layout_constraintHorizontal_bias="0.583"
84. app:layout_constraintStart_toStartOf="@+id/guideline6"
85. app:srcCompat="@drawable/ic_cancel" />
86.
87.
<com.google.android.material.floatingactionbutton.FloatingActionButton
88. android:id="@+id/voice_to_text_btn"
89. android:layout_width="wrap_content"
90. android:layout_height="wrap_content"
91. android:layout_marginBottom="8dp"
92. android:layout_marginEnd="8dp"
93. android:layout_marginLeft="8dp"
94. android:layout_marginRight="8dp"
95. android:layout_marginStart="8dp"
96. android:clickable="true"
97. app:backgroundTint="@color/colorWhite"
98. app:layout_constraintBottom_toBottomOf="parent"
99. app:layout_constraintEnd_toStartOf="@+id/guideline8"
100. app:layout_constraintStart_toStartOf="@+id/guideline7"
101. app:srcCompat="@drawable/ic_mic_blue_700_24dp" />
102.
103.
<com.google.android.material.floatingactionbutton.FloatingActionButton
104. android:id="@+id/read_aloud_original_btn"
105. android:layout_width="wrap_content"
106. android:layout_height="wrap_content"
107. android:layout_marginBottom="8dp"
108. android:layout_marginEnd="8dp"
109. android:layout_marginLeft="8dp"
110. android:layout_marginRight="8dp"
111. android:layout_marginStart="8dp"
112. android:clickable="true"
113. app:backgroundTint="@color/colorWhite"
114. app:layout_constraintBottom_toBottomOf="parent"
115. app:layout_constraintEnd_toStartOf="@+id/guideline5"
116. app:layout_constraintStart_toStartOf="@+id/guideline8"
117. app:srcCompat="@drawable/ic_volume_up" />
118.
119. <androidx.constraintlayout.widget.Guideline
120. android:id="@+id/guideline4"
121. android:layout_width="wrap_content"
122. android:layout_height="wrap_content"
123. android:orientation="vertical"
124. app:layout_constraintGuide_begin="16dp" />
125.
126. <androidx.constraintlayout.widget.Guideline
127. android:id="@+id/guideline5"
128. android:layout_width="wrap_content"
129. android:layout_height="wrap_content"
130. android:orientation="vertical"
131. app:layout_constraintGuide_end="16dp" />
132.
133. <androidx.constraintlayout.widget.Guideline
134. android:id="@+id/guideline6"
135. android:layout_width="wrap_content"
136. android:layout_height="wrap_content"
137. android:orientation="vertical"
138. app:layout_constraintGuide_percent="0.25" />
139.
140. <androidx.constraintlayout.widget.Guideline
141. android:id="@+id/guideline7"
142. android:layout_width="wrap_content"
143. android:layout_height="wrap_content"
144. android:orientation="vertical"
145. app:layout_constraintGuide_percent="0.5" />
146.
147. <androidx.constraintlayout.widget.Guideline
148. android:id="@+id/guideline8"
149. android:layout_width="wrap_content"
150. android:layout_height="wrap_content"
151. android:orientation="vertical"
152. app:layout_constraintGuide_percent="0.75" />
153.
154. </androidx.constraintlayout.widget.ConstraintLayout>
155. </androidx.cardview.widget.CardView>
156.
157. <androidx.cardview.widget.CardView
158. android:id="@+id/cardView2"
159. android:layout_width="0dp"
160. android:layout_height="0dp"
161. android:layout_marginBottom="8dp"
162. android:layout_marginEnd="16dp"
163. android:layout_marginLeft="16dp"
164. android:layout_marginRight="16dp"
165. android:layout_marginStart="16dp"
166. android:layout_marginTop="8dp"
167. app:layout_constraintEnd_toEndOf="parent"
168. app:layout_constraintStart_toStartOf="parent"
169. app:layout_constraintBottom_toBottomOf="parent"
170. app:layout_constraintTop_toTopOf="@+id/guideline2">
171.
172. <androidx.constraintlayout.widget.ConstraintLayout
173. android:layout_width="match_parent"
174. android:layout_height="match_parent"
175. android:padding="5dp">
176.
177. <ScrollView
178. android:layout_width="0dp"
179. android:layout_height="0dp"
180. android:layout_marginBottom="8dp"
181. android:fillViewport="true"
182.
app:layout_constraintBottom_toTopOf="@+id/copy_translation_btn"
183. app:layout_constraintEnd_toEndOf="parent"
184. app:layout_constraintStart_toStartOf="parent"
185. app:layout_constraintTop_toTopOf="parent">
186.
187.
188. <androidx.appcompat.widget.AppCompatTextView
189. android:id="@+id/translated_text_tv"
190. android:layout_width="match_parent"
191. android:layout_height="match_parent"
192. android:background="@drawable/border"
193. android:textColor="@color/colorBlack" />
194.
195. </ScrollView>
196.
197.
198.
<com.google.android.material.floatingactionbutton.FloatingActionButton
199. android:id="@+id/copy_translation_btn"
200. android:layout_width="wrap_content"
201. android:layout_height="wrap_content"
202. android:layout_marginBottom="8dp"
203. android:layout_marginEnd="8dp"
204. android:layout_marginLeft="8dp"
205. android:layout_marginRight="8dp"
206. android:layout_marginStart="8dp"
207. android:clickable="true"
208. app:backgroundTint="@color/colorWhite"
209. app:layout_constraintBottom_toBottomOf="parent"
210. app:layout_constraintEnd_toStartOf="@+id/guideline9"
211. app:layout_constraintStart_toStartOf="@+id/guideline11"
212. app:srcCompat="@drawable/ic_content_copy_blue" />
213.
214.
<com.google.android.material.floatingactionbutton.FloatingActionButton
215. android:id="@+id/share_translation_btn"
216. android:layout_width="wrap_content"
217. android:layout_height="wrap_content"
218. android:layout_marginBottom="8dp"
219. android:layout_marginEnd="8dp"
220. android:layout_marginLeft="8dp"
221. android:layout_marginRight="8dp"
222. android:layout_marginStart="8dp"
223. android:clickable="true"
224. app:backgroundTint="@color/colorWhite"
225. app:layout_constraintBottom_toBottomOf="parent"
226. app:layout_constraintEnd_toStartOf="@+id/guideline12"
227. app:layout_constraintHorizontal_bias="0.583"
228. app:layout_constraintStart_toStartOf="@+id/guideline11"
229. app:srcCompat="@drawable/ic_share_blue" />
230.
231.
<com.google.android.material.floatingactionbutton.FloatingActionButton
232. android:id="@+id/like_btn"
233. android:layout_width="wrap_content"
234. android:layout_height="wrap_content"
235. android:layout_marginBottom="8dp"
236. android:layout_marginEnd="8dp"
237. android:layout_marginLeft="8dp"
238. android:layout_marginRight="8dp"
239. android:layout_marginStart="8dp"
240. android:clickable="true"
241. app:backgroundTint="@color/colorWhite"
242. app:layout_constraintBottom_toBottomOf="parent"
243. app:layout_constraintEnd_toStartOf="@+id/guideline13"
244. app:layout_constraintStart_toStartOf="@+id/guideline12"
245. app:srcCompat="@drawable/ic_save_blue" />
246.
247.
<com.google.android.material.floatingactionbutton.FloatingActionButton
248. android:id="@+id/read_aloud_translation_btn"
249. android:layout_width="wrap_content"
250. android:layout_height="wrap_content"
251. android:layout_marginBottom="8dp"
252. android:layout_marginEnd="8dp"
253. android:layout_marginLeft="8dp"
254. android:layout_marginRight="8dp"
255. android:layout_marginStart="8dp"
256. android:clickable="true"
257. app:backgroundTint="@color/colorWhite"
258. app:layout_constraintBottom_toBottomOf="parent"
259. app:layout_constraintEnd_toStartOf="@+id/guideline10"
260. app:layout_constraintStart_toStartOf="@+id/guideline13"
261. app:srcCompat="@drawable/ic_volume_up" />
262.
263. <androidx.constraintlayout.widget.Guideline
264. android:id="@+id/guideline9"
265. android:layout_width="wrap_content"
266. android:layout_height="wrap_content"
267. android:orientation="vertical"
268. app:layout_constraintGuide_begin="16dp" />
269.
270. <androidx.constraintlayout.widget.Guideline
271. android:id="@+id/guideline10"
272. android:layout_width="wrap_content"
273. android:layout_height="wrap_content"
274. android:orientation="vertical"
275. app:layout_constraintGuide_end="16dp" />
276.
277. <androidx.constraintlayout.widget.Guideline
278. android:id="@+id/guideline11"
279. android:layout_width="wrap_content"
280. android:layout_height="wrap_content"
281. android:orientation="vertical"
282. app:layout_constraintGuide_percent="0.25" />
283.
284. <androidx.constraintlayout.widget.Guideline
285. android:id="@+id/guideline12"
286. android:layout_width="wrap_content"
287. android:layout_height="wrap_content"
288. android:orientation="vertical"
289. app:layout_constraintGuide_percent="0.5" />
290.
291. <androidx.constraintlayout.widget.Guideline
292. android:id="@+id/guideline13"
293. android:layout_width="wrap_content"
294. android:layout_height="wrap_content"
295. android:orientation="vertical"
296. app:layout_constraintGuide_percent="0.75" />
297. </androidx.constraintlayout.widget.ConstraintLayout>
298. </androidx.cardview.widget.CardView>
299.
300. <com.google.android.material.floatingactionbutton.FloatingActionButton
301. android:id="@+id/translate_text__btn"
302. android:layout_width="wrap_content"
303. android:layout_height="wrap_content"
304. android:clickable="true"
305. app:layout_constraintBottom_toTopOf="@+id/cardView2"
306. app:layout_constraintEnd_toEndOf="parent"
307. app:layout_constraintStart_toStartOf="parent"
308. app:layout_constraintTop_toBottomOf="@+id/cardView"
309. app:srcCompat="@drawable/ic_send_white" />
310.
311. </androidx.constraintlayout.widget.ConstraintLayout>

<?xml version="1.0" encoding="utf-8"?> 


<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/layout_text_translate"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#E0E0E0"
tools:context=".texttranslation.TextTranslationActivity">

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.47" />

<androidx.cardview.widget.CardView
android:id="@+id/cardView"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">

<androidx.appcompat.widget.AppCompatEditText
android:id="@+id/original_text_et"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:background="@drawable/border"
android:gravity="top"
android:hint="Touch and Start Typing..."
android:padding="8dp"
android:scrollbars="vertical"
android:textAppearance="@style/TextAppearance.AppCompat.B
app:layout_constraintBottom_toTopOf="@+id/paste_btn"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/paste_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline6"
app:layout_constraintStart_toStartOf="@+id/guideline4"
app:srcCompat="@drawable/ic_content_paste" />

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/cancel_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline7"
app:layout_constraintHorizontal_bias="0.583"
app:layout_constraintStart_toStartOf="@+id/guideline6"
app:srcCompat="@drawable/ic_cancel" />

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/voice_to_text_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline8"
app:layout_constraintStart_toStartOf="@+id/guideline7"
app:srcCompat="@drawable/ic_mic_blue_700_24dp" />

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/read_aloud_original_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline5"
app:layout_constraintStart_toStartOf="@+id/guideline8"
app:srcCompat="@drawable/ic_volume_up" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="16dp" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="16dp" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline6"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.25" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline7"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline8"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.75" />

</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

<androidx.cardview.widget.CardView
android:id="@+id/cardView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="16dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginStart="16dp"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2">

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="5dp">

<ScrollView
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:fillViewport="true"
app:layout_constraintBottom_toTopOf="@+id/copy_translatio
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">

<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/translated_text_tv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/border"
android:textColor="@color/colorBlack" />

</ScrollView>

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/copy_translation_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline9"
app:layout_constraintStart_toStartOf="@+id/guideline11"
app:srcCompat="@drawable/ic_content_copy_blue" />

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/share_translation_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline12"
app:layout_constraintHorizontal_bias="0.583"
app:layout_constraintStart_toStartOf="@+id/guideline11"
app:srcCompat="@drawable/ic_share_blue" />

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/like_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline13"
app:layout_constraintStart_toStartOf="@+id/guideline12"
app:srcCompat="@drawable/ic_save_blue" />

<com.google.android.material.floatingactionbutton.FloatingAct
android:id="@+id/read_aloud_translation_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginStart="8dp"
android:clickable="true"
app:backgroundTint="@color/colorWhite"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/guideline10"
app:layout_constraintStart_toStartOf="@+id/guideline13"
app:srcCompat="@drawable/ic_volume_up" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline9"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_begin="16dp" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline10"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_end="16dp" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.25" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline12"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />

<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.75" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>

<com.google.android.material.floatingactionbutton.FloatingActionButto
android:id="@+id/translate_text__btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
app:layout_constraintBottom_toTopOf="@+id/cardView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/cardView"
app:srcCompat="@drawable/ic_send_white" />

</androidx.constraintlayout.widget.ConstraintLayout>

The drawable icons used in some of the widgets can be obtain from the drawable folder or
you can create your own icons. If everything works well with no error, you will get a UI
similar to the image below.

Open the TextTranslationActivity class, we will get instances of the widgets we added in the
layout file. In other to avoid repetition and boilerplate code, we will use ButterKnife library
for View binding and event listeners.

Copy and paste the code below to your android app. As you can see, the code is well
commented and very explanatory.

1. package com.inducesmile.androidtranslation.texttranslation;
2.
3. import android.app.ProgressDialog;
4. import android.content.ActivityNotFoundException;
5. import android.content.Intent;
6. import android.os.Bundle;
7. import android.speech.RecognizerIntent;
8. import android.speech.tts.TextToSpeech;
9. import android.text.TextUtils;
10. import android.util.Log;
11. import android.view.Menu;
12. import android.view.MenuItem;
13. import android.view.View;
14. import android.widget.AdapterView;
15. import android.widget.ArrayAdapter;
16. import android.widget.Spinner;
17. import android.widget.Toast;
18.
19. import com.google.android.material.floatingactionbutton.FloatingActionButton
20. import com.inducesmile.androidtranslation.R;
21. import com.inducesmile.androidtranslation.repository.api.model.YandexRespons
22. import com.inducesmile.androidtranslation.repository.database.model.Translat
23. import com.inducesmile.androidtranslation.texttranslation.dialog.SaveDialog;
24. import com.inducesmile.androidtranslation.utils.CommonUtils;
25. import com.inducesmile.androidtranslation.utils.Constants;
26. import com.inducesmile.androidtranslation.utils.CopyPasteText;
27. import com.inducesmile.androidtranslation.utils.ShareUtils;
28. import com.inducesmile.androidtranslation.utils.TextToVoice;
29.
30. import java.util.ArrayList;
31. import java.util.Arrays;
32. import java.util.List;
33. import java.util.Locale;
34. import java.util.Objects;
35.
36. import javax.inject.Inject;
37.
38. import androidx.appcompat.app.AppCompatActivity;
39. import androidx.appcompat.widget.AppCompatEditText;
40. import androidx.appcompat.widget.AppCompatTextView;
41. import androidx.constraintlayout.widget.ConstraintLayout;
42. import androidx.lifecycle.Observer;
43. import dagger.android.AndroidInjection;
44.
45. public class TextTranslationActivity extends AppCompatActivity implements Vi
46.
47. private static final String TAG = TextTranslationActivity.class.getSimpl
48.
49.
50. private AppCompatEditText mOriginalText;
51. private AppCompatTextView mTranslatedText;
52.
53. private ConstraintLayout mLayout;
54.
55. private String originalText = "";
56. private String translatedText = "";
57. private String transAbbr = "en";
58. private String origAbbr = "en";
59.
60. private FloatingActionButton pasteText, deleteText, speakText, readText,
61. favoriteText, translateReadText, convertTex
62.
63. private TextToSpeech tts;
64.
65. private ProgressDialog mProgressDialog;
66.
67. private CopyPasteText copyPasteText;
68.
69. private Spinner spinner, translationSpinner;
70.
71. @Inject
72. TextTranslationViewModel textTranslationViewModel;
73.
74.
75. @Override
76. protected void onCreate(Bundle savedInstanceState) {
77. super.onCreate(savedInstanceState);
78. setContentView(R.layout.activity_text_translation);
79.
80. setTitle("");
81. AndroidInjection.inject(this);
82.
83. copyPasteText = new CopyPasteText(this);
84.
85. mOriginalText = (AppCompatEditText)findViewById(R.id.original_text_e
86. mTranslatedText = (AppCompatTextView)findViewById(R.id.translated_te
87.
88. pasteText = (FloatingActionButton)findViewById(R.id.paste_btn);
89. deleteText = (FloatingActionButton)findViewById(R.id.cancel_btn);
90. speakText = (FloatingActionButton)findViewById(R.id.voice_to_text_bt
91. readText = (FloatingActionButton)findViewById(R.id.read_aloud_origin
92.
93. copyText = (FloatingActionButton)findViewById(R.id.copy_translation_
94. shareText = (FloatingActionButton)findViewById(R.id.share_translatio
95. favoriteText = (FloatingActionButton)findViewById(R.id.like_btn);
96. translateReadText = (FloatingActionButton)findViewById(R.id.read_alo
97.
98. convertText = (FloatingActionButton)findViewById(R.id.translate_text
99.
100. pasteText.setOnClickListener(this);
101. deleteText.setOnClickListener(this);
102. speakText.setOnClickListener(this);
103. readText.setOnClickListener(this);
104.
105. copyText.setOnClickListener(this);
106. shareText.setOnClickListener(this);
107. favoriteText.setOnClickListener(this);
108. translateReadText.setOnClickListener(this);
109.
110. convertText.setOnClickListener(new View.OnClickListener() {
111. @Override
112. public void onClick(View v) {
113. String userTextInput = getOriginalText();
114. List<String> list = Arrays.asList(Constants.YANDEX_TRANSLATE
115. if(TextUtils.isEmpty(userTextInput)){
116. Toast.makeText(TextTranslationActivity.this, "Content to
empty ...", Toast.LENGTH_SHORT).show();
117. }else if(TextUtils.isEmpty(transAbbr)){
118. Toast.makeText(TextTranslationActivity.this, "Target Lan
Toast.LENGTH_SHORT).show();
119. }
120. else if(!list.contains(transAbbr)) {
121. Toast.makeText(TextTranslationActivity.this, "Target Lan
Toast.LENGTH_SHORT).show();
122. }else {
123. textTranslationViewModel.makeApiTranslationCall(userText
124. }
125. }
126. });
127.
128. watchTranslatedText();
129. }
130.
131.
132. //Watch translated text for change
133. private void watchTranslatedText(){
134. textTranslationViewModel.getYandexResponse().observe(this, new Obser
{
135. @Override
136. public void onChanged(YandexResponse yandexResponse) {
137. if (yandexResponse != null) {
138. translatedText = String.valueOf(yandexResponse.getText()
139. translatedText = translatedText.replaceAll("\\p{P}", "")
140. mTranslatedText.setText(translatedText);
141. }
142. }
143. });
144. }
145.
146. private boolean isOriginalTextExist(){
147. String textContent = Objects.requireNonNull(mOriginalText.getText())
148. return TextUtils.isEmpty(textContent);
149. }
150.
151. private boolean isTranslatedTextExist(){
152. String textContent = Objects.requireNonNull(mTranslatedText.getText(
153. return TextUtils.isEmpty(textContent);
154. }
155.
156.
157. private String getOriginalText(){
158. return Objects.requireNonNull(mOriginalText.getText()).toString();
159. }
160.
161.
162. private String getTranslatedText(){
163. return Objects.requireNonNull(mTranslatedText.getText()).toString();
164. }
165.
166.
167. @Override
168. public boolean onCreateOptionsMenu(Menu menu) {
169. getMenuInflater().inflate(R.menu.text_translate_menu, menu);
170.
171. MenuItem item = menu.findItem(R.id.original_lang_spinner);
172. populateFirstSpinner(item);
173.
174. MenuItem item2 = menu.findItem(R.id.translate_lang_spinner);
175. populateSecondSpinner(item2);
176.
177. return super.onCreateOptionsMenu(menu);
178. }
179.
180.
181. @Override
182. public boolean onOptionsItemSelected(MenuItem item) {
183. int clickItem = item.getItemId();
184. if(clickItem == R.id.switch_item){
185.
186. //Switch selected language
187. String firstText = (String)spinner.getSelectedItem();
188. String secondText = (String)translationSpinner.getSelectedItem()
189. int firstIndex = CommonUtils.getLanguageIndexPosition(firstText)
190. int secondIndex = CommonUtils.getLanguageIndexPosition(secondTex
191.
192. spinner.setSelection(secondIndex);
193. translationSpinner.setSelection(firstIndex);
194.
195. // switch language abbreviation
196. String tempAbbreviation = origAbbr;
197. transAbbr = origAbbr;
198. origAbbr = tempAbbreviation;
199.
200. //switching text content
201. mOriginalText.setText(getTranslatedText());
202. mTranslatedText.setText(getOriginalText());
203.
204.
205. }
206. return super.onOptionsItemSelected(item);
207. }
208.
209.
210.
211. //Language option for original text
212. private void populateFirstSpinner(MenuItem item){
213. spinner = (Spinner) item.getActionView();
214. ArrayAdapter<String> languageAdapter = new ArrayAdapter<String>(this
R.layout.custom_spinner_item, CommonUtils.sortedListString());
215.
216. languageAdapter.setDropDownViewResource(android.R.layout.simple_spin
217. spinner.setAdapter(languageAdapter);
218. spinner.setSelection(CommonUtils.getEnglishLanguagePosition());
219.
220. spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedList
221. @Override
222. public void onItemSelected(AdapterView<?> parent, View view, int
223. String item = parent.getItemAtPosition(position).toString();
224.
225. int index =
Arrays.asList(Constants.YANDEX_TRANSLATE_SUPPORTED_LANGUAGE).indexOf(item);
226. origAbbr = Constants.YANDEX_TRANSLATE_ABBR[index];
227. }
228.
229. @Override
230. public void onNothingSelected(AdapterView<?> adapterView) {
231.
232. }
233. });
234. }
235.
236.
237. //Language option for translation
238. private void populateSecondSpinner(MenuItem item){
239. translationSpinner = (Spinner) item.getActionView();
240. ArrayAdapter<String> translationAdapter = new ArrayAdapter<String>(t
R.layout.custom_spinner_item, CommonUtils.sortedListString());
241.
242.
translationAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dr
243. translationSpinner.setAdapter(translationAdapter);
244. translationSpinner.setSelection(CommonUtils.getEnglishLanguagePositi
245.
246. translationSpinner.setOnItemSelectedListener(new AdapterView.OnItemS
247. @Override
248. public void onItemSelected(AdapterView<?> parent, View view, int
249. String item = parent.getItemAtPosition(position).toString();
250.
251. int index =
Arrays.asList(Constants.YANDEX_TRANSLATE_SUPPORTED_LANGUAGE).indexOf(item);
252. transAbbr = Constants.YANDEX_TRANSLATE_ABBR[index];
253. }
254.
255. @Override
256. public void onNothingSelected(AdapterView<?> adapterView) {
257.
258. }
259. });
260. }
261.
262.
263. //All button options used in the translation app
264. @Override
265. public void onClick(View v) {
266. FloatingActionButton floatingActionButton = (FloatingActionButton)v;
267. int buttonId = floatingActionButton.getId();
268.
269. switch (buttonId){
270. //paste translation text
271. case R.id.paste_btn:
272. String copiedContext = copyPasteText.pasteTextContent();
273. if(TextUtils.isEmpty(copiedContext)){
274. Toast.makeText(TextTranslationActivity.this, "Paste cont
Toast.LENGTH_SHORT).show();
275. }else{
276. mOriginalText.setText(copiedContext);
277. }
278. break;
279. //Delete translation text
280. case R.id.cancel_btn:
281. mOriginalText.setText("");
282. break;
283. //context translation text to voice
284. case R.id.voice_to_text_btn:
285. askSpeechInput();
286. break;
287. //text to sppech
288. case R.id.read_aloud_original_btn:
289. if(isOriginalTextExist()){
290. Toast.makeText(TextTranslationActivity.this, "Text is em
Toast.LENGTH_SHORT).show();
291. }else{
292. TextToVoice textToVoice = new TextToVoice(TextTranslatio
293. textToVoice.turnTextToSpeech(getOriginalText());
294. }
295. break;
296. //copy translation text
297. case R.id.copy_translation_btn:
298. if(isTranslatedTextExist()){
299. Toast.makeText(TextTranslationActivity.this, "Translatio
Toast.LENGTH_SHORT).show();
300. }else{
301. copyPasteText.copyTextContent(getTranslatedText());
302. }
303. break;
304. //share translation text
305. case R.id.share_translation_btn:
306. ShareUtils.shareTranslatedText(TextTranslationActivity.this,
getTranslatedText());
307. break;
308. case R.id.like_btn:
309. //The like id was changed to save.
310. if(TextUtils.isEmpty(getOriginalText()) ||
TextUtils.isEmpty(getTranslatedText())){
311. Toast.makeText(TextTranslationActivity.this, "Translatio
Toast.LENGTH_SHORT).show();
312. }else{
313. SaveDialog deleteDialog = new SaveDialog(TextTranslation
314. TranslationObject saveObject = new TranslationObject(get
getTranslatedText());
315. deleteDialog.addNewMessage(textTranslationViewModel, sav
316. }
317.
318. break;
319. case R.id.read_aloud_translation_btn:
320. if (isTranslatedTextExist()) {
321. Toast.makeText(TextTranslationActivity.this, "Text is em
Toast.LENGTH_SHORT).show();
322. } else {
323. TextToVoice textToVoice = new TextToVoice(TextTranslatio
324. textToVoice.turnTextToSpeech(getTranslatedText());
325. }
326. break;
327. default:
328. break;
329. }
330. }
331.
332.
333. //Android speech input
334. private void askSpeechInput() {
335. Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH)
336. intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);
337. intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault()
338. intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Hi speak something")
339. try {
340. startActivityForResult(intent, Constants.REQ_CODE_SPEECH_INPUT);
341. } catch (ActivityNotFoundException a) {
342. Log.d(TAG, "Error " + a.getMessage());
343. }
344. }
345.
346.
347. @Override
348. protected void onActivityResult(int requestCode, int resultCode, Intent
349. super.onActivityResult(requestCode, resultCode, data);
350.
351. switch (requestCode) {
352. case Constants.REQ_CODE_SPEECH_INPUT: {
353. if (resultCode == RESULT_OK && null != data) {
354. ArrayList<String> result =
data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
355. mOriginalText.setText(result.get(0));
356. }
357. break;
358. }
359. }
360. }
361.
362. }

package com.inducesmile.androidtranslation.texttranslation; 

import android.app.ProgressDialog;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Bundle;
import android.speech.RecognizerIntent;
import android.speech.tts.TextToSpeech;
import android.text.TextUtils;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Spinner;
import android.widget.Toast;

import com.google.android.material.floatingactionbutton.FloatingActionBut
import com.inducesmile.androidtranslation.R;
import com.inducesmile.androidtranslation.repository.api.model.YandexResp
import com.inducesmile.androidtranslation.repository.database.model.Trans
import com.inducesmile.androidtranslation.texttranslation.dialog.SaveDial
import com.inducesmile.androidtranslation.utils.CommonUtils;
import com.inducesmile.androidtranslation.utils.Constants;
import com.inducesmile.androidtranslation.utils.CopyPasteText;
import com.inducesmile.androidtranslation.utils.ShareUtils;
import com.inducesmile.androidtranslation.utils.TextToVoice;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import java.util.Objects;

import javax.inject.Inject;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.AppCompatEditText;
import androidx.appcompat.widget.AppCompatTextView;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.lifecycle.Observer;
import dagger.android.AndroidInjection;

public class TextTranslationActivity extends AppCompatActivity implements

private static final String TAG = TextTranslationActivity.class.getSi

private AppCompatEditText mOriginalText;


private AppCompatTextView mTranslatedText;

private ConstraintLayout mLayout;

private String originalText = "";


private String translatedText = "";
private String transAbbr = "en";
private String origAbbr = "en";

private FloatingActionButton pasteText, deleteText, speakText, readTe


favoriteText, translateReadText, convert

private TextToSpeech tts;

private ProgressDialog mProgressDialog;

private CopyPasteText copyPasteText;

private Spinner spinner, translationSpinner;

@Inject
TextTranslationViewModel textTranslationViewModel;

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

setTitle("");
AndroidInjection.inject(this);

copyPasteText = new CopyPasteText(this);

mOriginalText = (AppCompatEditText)findViewById(R.id.original_tex
mTranslatedText = (AppCompatTextView)findViewById(R.id.translated

pasteText = (FloatingActionButton)findViewById(R.id.paste_btn);
deleteText = (FloatingActionButton)findViewById(R.id.cancel_btn);
speakText = (FloatingActionButton)findViewById(R.id.voice_to_text
readText = (FloatingActionButton)findViewById(R.id.read_aloud_ori

copyText = (FloatingActionButton)findViewById(R.id.copy_translati
shareText = (FloatingActionButton)findViewById(R.id.share_transla
favoriteText = (FloatingActionButton)findViewById(R.id.like_btn);
translateReadText = (FloatingActionButton)findViewById(R.id.read_

convertText = (FloatingActionButton)findViewById(R.id.translate_t

pasteText.setOnClickListener(this);
deleteText.setOnClickListener(this);
speakText.setOnClickListener(this);
readText.setOnClickListener(this);

copyText.setOnClickListener(this);
shareText.setOnClickListener(this);
favoriteText.setOnClickListener(this);
translateReadText.setOnClickListener(this);

convertText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String userTextInput = getOriginalText();
List<String> list = Arrays.asList(Constants.YANDEX_TRANSL
if(TextUtils.isEmpty(userTextInput)){
Toast.makeText(TextTranslationActivity.this, "Content
}else if(TextUtils.isEmpty(transAbbr)){
Toast.makeText(TextTranslationActivity.this, "Target
}
else if(!list.contains(transAbbr)) {
Toast.makeText(TextTranslationActivity.this, "Target
}else {
textTranslationViewModel.makeApiTranslationCall(userT
}
}
});

watchTranslatedText();
}

//Watch translated text for change


private void watchTranslatedText(){
textTranslationViewModel.getYandexResponse().observe(this, new Ob
@Override
public void onChanged(YandexResponse yandexResponse) {
if (yandexResponse != null) {
translatedText = String.valueOf(yandexResponse.getTex
translatedText = translatedText.replaceAll("\\p{P}",
mTranslatedText.setText(translatedText);
}
}
});
}

private boolean isOriginalTextExist(){


String textContent = Objects.requireNonNull(mOriginalText.getText
return TextUtils.isEmpty(textContent);
}

private boolean isTranslatedTextExist(){


String textContent = Objects.requireNonNull(mTranslatedText.getTe
return TextUtils.isEmpty(textContent);
}

private String getOriginalText(){


return Objects.requireNonNull(mOriginalText.getText()).toString()
}

private String getTranslatedText(){


return Objects.requireNonNull(mTranslatedText.getText()).toString
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.text_translate_menu, menu);

MenuItem item = menu.findItem(R.id.original_lang_spinner);


populateFirstSpinner(item);

MenuItem item2 = menu.findItem(R.id.translate_lang_spinner);


populateSecondSpinner(item2);

return super.onCreateOptionsMenu(menu);
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
int clickItem = item.getItemId();
if(clickItem == R.id.switch_item){

//Switch selected language


String firstText = (String)spinner.getSelectedItem();
String secondText = (String)translationSpinner.getSelectedIte
int firstIndex = CommonUtils.getLanguageIndexPosition(firstTe
int secondIndex = CommonUtils.getLanguageIndexPosition(second

spinner.setSelection(secondIndex);
translationSpinner.setSelection(firstIndex);

// switch language abbreviation


String tempAbbreviation = origAbbr;
transAbbr = origAbbr;
origAbbr = tempAbbreviation;

//switching text content


mOriginalText.setText(getTranslatedText());
mTranslatedText.setText(getOriginalText());

}
return super.onOptionsItemSelected(item);
}

//Language option for original text


private void populateFirstSpinner(MenuItem item){
spinner = (Spinner) item.getActionView();
ArrayAdapter<String> languageAdapter = new ArrayAdapter<String>(t

languageAdapter.setDropDownViewResource(android.R.layout.simple_s
spinner.setAdapter(languageAdapter);
spinner.setSelection(CommonUtils.getEnglishLanguagePosition());

spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedL
@Override
public void onItemSelected(AdapterView<?> parent, View view,
String item = parent.getItemAtPosition(position).toString

int index = Arrays.asList(Constants.YANDEX_TRANSLATE_SUPP


origAbbr = Constants.YANDEX_TRANSLATE_ABBR[index];
}

@Override
public void onNothingSelected(AdapterView<?> adapterView) {

}
});
}

//Language option for translation


private void populateSecondSpinner(MenuItem item){
translationSpinner = (Spinner) item.getActionView();
ArrayAdapter<String> translationAdapter = new ArrayAdapter<String

translationAdapter.setDropDownViewResource(android.R.layout.simpl
translationSpinner.setAdapter(translationAdapter);
translationSpinner.setSelection(CommonUtils.getEnglishLanguagePos

translationSpinner.setOnItemSelectedListener(new AdapterView.OnIt
@Override
public void onItemSelected(AdapterView<?> parent, View view,
String item = parent.getItemAtPosition(position).toString

int index = Arrays.asList(Constants.YANDEX_TRANSLATE_SUPP


transAbbr = Constants.YANDEX_TRANSLATE_ABBR[index];
}

@Override
public void onNothingSelected(AdapterView<?> adapterView) {

}
});
}

//All button options used in the translation app


@Override
public void onClick(View v) {
FloatingActionButton floatingActionButton = (FloatingActionButton
int buttonId = floatingActionButton.getId();

switch (buttonId){
//paste translation text
case R.id.paste_btn:
String copiedContext = copyPasteText.pasteTextContent();
if(TextUtils.isEmpty(copiedContext)){
Toast.makeText(TextTranslationActivity.this, "Paste c
}else{
mOriginalText.setText(copiedContext);
}
break;
//Delete translation text
case R.id.cancel_btn:
mOriginalText.setText("");
break;
//context translation text to voice
case R.id.voice_to_text_btn:
askSpeechInput();
break;
//text to sppech
case R.id.read_aloud_original_btn:
if(isOriginalTextExist()){
Toast.makeText(TextTranslationActivity.this, "Text is
}else{
TextToVoice textToVoice = new TextToVoice(TextTransla
textToVoice.turnTextToSpeech(getOriginalText());
}
break;
//copy translation text
case R.id.copy_translation_btn:
if(isTranslatedTextExist()){
Toast.makeText(TextTranslationActivity.this, "Transla
}else{
copyPasteText.copyTextContent(getTranslatedText());
}
break;
//share translation text
case R.id.share_translation_btn:
ShareUtils.shareTranslatedText(TextTranslationActivity.th
break;
case R.id.like_btn:
//The like id was changed to save.
if(TextUtils.isEmpty(getOriginalText()) || TextUtils.isEm
Toast.makeText(TextTranslationActivity.this, "Transla
}else{
SaveDialog deleteDialog = new SaveDialog(TextTranslat
TranslationObject saveObject = new TranslationObject(
deleteDialog.addNewMessage(textTranslationViewModel,
}

break;
case R.id.read_aloud_translation_btn:
if (isTranslatedTextExist()) {
Toast.makeText(TextTranslationActivity.this, "Text is
} else {
TextToVoice textToVoice = new TextToVoice(TextTransla
textToVoice.turnTextToSpeech(getTranslatedText());
}
break;
default:
break;
}
}

//Android speech input


private void askSpeechInput() {
Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEE
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, Recognizer
intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefaul
intent.putExtra(RecognizerIntent.EXTRA_PROMPT, "Hi speak somethin
try {
startActivityForResult(intent, Constants.REQ_CODE_SPEECH_INPU
} catch (ActivityNotFoundException a) {
Log.d(TAG, "Error " + a.getMessage());
}
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Inte
super.onActivityResult(requestCode, resultCode, data);

switch (requestCode) {
case Constants.REQ_CODE_SPEECH_INPUT: {
if (resultCode == RESULT_OK && null != data) {
ArrayList<String> result = data.getStringArrayListExt
mOriginalText.setText(result.get(0));
}
break;
}
}
}

As can be seen on the code, we have injected a View Model class

1. @Inject
2. TextTranslationViewModel textTranslationViewModel;

@Inject 
TextTranslationViewModel textTranslationViewModel;

We will need to create a this in the same folder. It will inherit from android ViewModel class

The ViewModel class is responsible for analyzing and preparing our remote data from the
currency API.

CREATE A VIEWMODEL CLASS


Create a new ViewModel class and name it TextTranslationViewModel. Open the class and
add the code below.

1. public class TextTranslationViewModel extends BaseViewModel<ITextInterface>


{
2.
3. private static final String TAG =
TextTranslationViewModel.class.getSimpleName();
4.
5. private final MutableLiveData<YandexResponse> mYandexResponse = new
MutableLiveData<>();
6.
7. private final MutableLiveData<Boolean> hasSavedText = new
MutableLiveData<>();
8.
9.
10. public TextTranslationViewModel(DataManager dataManager) {
11. super(dataManager);
12. }
13.
14.
15. public MutableLiveData<YandexResponse> getYandexResponse(){
16. return mYandexResponse;
17. }
18.
19.
20. public void makeApiTranslationCall(String original, String target){
21. setIsLoading(true);
22. Observable<YandexResponse> returnObject =
getDataManager().getTranslatedTextUsingYandexApi(ApiEndPoint.YANDEX_API_KEY,
original, target);
23.
getCompositeDisposable().add(returnObject.subscribeOn(Schedulers.io())
24. .observeOn(AndroidSchedulers.mainThread())
25. .subscribe(new Consumer<YandexResponse>() {
26. @Override
27. public void accept(YandexResponse yandexResponse) throws
Exception {
28. setIsLoading(false);
29. Log.d(TAG, "The value of the return type is " +
yandexResponse.getText());
30. mYandexResponse.setValue(yandexResponse);
31. }
32. }, throwable -> {
33. setIsLoading(false);
34. Log.d(TAG, "Error has occurred ");
35. })
36. );
37. }
38.
39.
40. public void saveTranslatedText(TranslationObject translationObject){
41. Observable<Boolean> isTextSaved =
getDataManager().addTranslationObject(translationObject);
42.
getCompositeDisposable().add(isTextSaved.subscribeOn(Schedulers.io())
43. .observeOn(AndroidSchedulers.mainThread())
44. .subscribe(new Consumer<Boolean>() {
45. @Override
46. public void accept(Boolean aBoolean) throws Exception {
47. Log.d(TAG, "New data inserted ");
48. }
49. }, throwable -> {
50. Log.d(TAG, "Error has occurred ");
51. })
52. );
53. }
54. }


public class TextTranslationViewModel extends BaseViewModel<ITextInterfac

private static final String TAG = TextTranslationViewModel.class.getS

private final MutableLiveData<YandexResponse> mYandexResponse = new M

private final MutableLiveData<Boolean> hasSavedText = new MutableLive

public TextTranslationViewModel(DataManager dataManager) {


super(dataManager);
}

public MutableLiveData<YandexResponse> getYandexResponse(){


return mYandexResponse;
}

public void makeApiTranslationCall(String original, String target){


setIsLoading(true);
Observable<YandexResponse> returnObject = getDataManager().getTra
getCompositeDisposable().add(returnObject.subscribeOn(Schedulers.
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<YandexResponse>() {
@Override
public void accept(YandexResponse yandexResponse) thr
setIsLoading(false);
Log.d(TAG, "The value of the return type is " + y
mYandexResponse.setValue(yandexResponse);
}
}, throwable -> {
setIsLoading(false);
Log.d(TAG, "Error has occurred ");
})
);
}

public void saveTranslatedText(TranslationObject translationObject){


Observable<Boolean> isTextSaved = getDataManager().addTranslation
getCompositeDisposable().add(isTextSaved.subscribeOn(Schedulers.i
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Consumer<Boolean>() {
@Override
public void accept(Boolean aBoolean) throws Exception
Log.d(TAG, "New data inserted ");
}
}, throwable -> {
Log.d(TAG, "Error has occurred ");
})
);
}
}

WHAT WE HAVE NOW


Like I said from the beginner, we will only cover the core feature of the translator app and
the code above has achieved that. If you want to download the complete source code see
the section below.

 HOW TO DOWNLOAD THE COMPLETE SOURCE CODE


You can follow this tutorial and complete the tutorial with the code snippets provided in the
tutorial.

The source code is not free to download because we spent a lot of time to create these apps from scratch
and your little support will help us to even create more apps from scratch.

 Instant Pay Download – $10.00


 Instant Pay Download – $15.00
 Instant Pay Download – $20.00
 Instant Pay Download – $50.00
 Instant Pay Download – $100.00

Buy

SOURCE CODE CUSTOMIZATION


If you like the source code and will also like to customize its look and feel or add and
remove some features, kindly contact us using the comment section below or through our
contact page.

Please note that we charge $20 per hour for customization.

SUMMARY
We have walk through the core feature of android translator app and I guess you have a
better insight on how to continue to improve your source code.

I will suggest you buy the source code to learn how other features were implemented.

If you have questions and suggestions, kindly use the comment box below to get in touch

I look forward in seeing you in our next build from scratch episode.

POSTS YOU MIGHT BE INTERESTED ON:

How to build Android How to build Android How to build Android How to Create Android
Calculator App Dictionary App from Scientific Calculator App Currency Converter Using
Scratch Apilayer from Scratch

How to build Android


Youtube Music Video App

Tags: Android translation app, build translation app, create translation ap, make
translation app

ABOUT THE AUTHOR

Inducesmile
I learn and write about Android, Swift, C, Assembly, C++, Python,
Flutter, Kotlin, React Native and Internet of Things

ADD A COMMENT

You must be logged in to post a comment.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

INDUCESMILE – ANDROID TUTORIAL, ANDROID APPS, ANDROID STUDIO, ANDROID SDK, ANDROID DEVELOPMENT COPYRIGHT © 2020.

PROGRAMMING HELP ANDROID TUTORIALS CONTACT US PRIVACY POLICY

34

You might also like