├── .gitignore ├── app ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ ├── values │ │ │ │ ├── strings.xml │ │ │ │ ├── colors.xml │ │ │ │ └── styles.xml │ │ │ ├── mipmap-hdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-mdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-xxxhdpi │ │ │ │ ├── ic_launcher.png │ │ │ │ └── ic_launcher_round.png │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ ├── ic_launcher.xml │ │ │ │ └── ic_launcher_round.xml │ │ │ ├── drawable-v24 │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── layout │ │ │ │ └── activity_main.xml │ │ │ └── drawable │ │ │ │ └── ic_launcher_background.xml │ │ ├── java │ │ │ └── com │ │ │ │ └── umut │ │ │ │ └── soysal │ │ │ │ └── example │ │ │ │ └── MainActivity.kt │ │ └── AndroidManifest.xml │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── umut │ │ │ └── soysal │ │ │ └── example │ │ │ └── ExampleUnitTest.kt │ └── androidTest │ │ └── java │ │ └── com │ │ └── umut │ │ └── soysal │ │ └── example │ │ └── ExampleInstrumentedTest.kt ├── proguard-rules.pro └── build.gradle ├── currencyedittext ├── .gitignore ├── src │ ├── main │ │ ├── res │ │ │ └── values │ │ │ │ ├── strings.xml │ │ │ │ └── attrs.xml │ │ ├── AndroidManifest.xml │ │ └── java │ │ │ └── com │ │ │ └── umut │ │ │ └── soysal │ │ │ └── lib │ │ │ ├── CurrencyTextFormatter.java │ │ │ ├── CurrencyEditText.java │ │ │ └── CurrencyTextWatcher.java │ ├── test │ │ └── java │ │ │ └── com │ │ │ └── umut │ │ │ └── soysal │ │ │ └── lib │ │ │ └── ExampleUnitTest.java │ └── androidTest │ │ └── java │ │ └── com │ │ └── umut │ │ └── soysal │ │ └── lib │ │ └── ExampleInstrumentedTest.java ├── proguard-rules.pro └── build.gradle ├── settings.gradle ├── gif └── appSs.gif ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .idea ├── markdown-navigator │ └── profiles_settings.xml ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── vcs.xml ├── runConfigurations.xml ├── gradle.xml └── misc.xml ├── gradle.properties ├── README.md ├── gradlew.bat └── gradlew /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /currencyedittext/.gitignore: -------------------------------------------------------------------------------- 1 | /build 2 | -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | include ':app', ':currencyedittext' 2 | -------------------------------------------------------------------------------- /gif/appSs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/gif/appSs.gif -------------------------------------------------------------------------------- /app/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | example 3 | 4 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /currencyedittext/src/main/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | CurrencyEdittext 3 | 4 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /.idea/markdown-navigator/profiles_settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/umutsoysl/CurrencyEdittext/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /currencyedittext/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 3 | -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /app/src/main/res/values/colors.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | #008577 4 | #00574B 5 | #D81B60 6 | 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Tue Feb 26 19:57:10 EAT 2019 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.1-all.zip 7 | -------------------------------------------------------------------------------- /currencyedittext/src/main/res/values/attrs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /app/src/main/res/values/styles.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /app/src/test/java/com/umut/soysal/example/ExampleUnitTest.kt: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.example 2 | 3 | import org.junit.Test 4 | 5 | import org.junit.Assert.* 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * See [testing documentation](http://d.android.com/tools/testing). 11 | */ 12 | class ExampleUnitTest { 13 | @Test 14 | fun addition_isCorrect() { 15 | assertEquals(4, 2 + 2) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /currencyedittext/src/test/java/com/umut/soysal/lib/ExampleUnitTest.java: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.lib; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | /** 8 | * Example local unit test, which will execute on the development machine (host). 9 | * 10 | * @see Testing documentation 11 | */ 12 | public class ExampleUnitTest { 13 | @Test 14 | public void addition_isCorrect() { 15 | assertEquals(4, 2 + 2); 16 | } 17 | } -------------------------------------------------------------------------------- /app/src/main/java/com/umut/soysal/example/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.example 2 | 3 | import android.support.v7.app.AppCompatActivity 4 | import android.os.Bundle 5 | import kotlinx.android.synthetic.main.activity_main.* 6 | import java.util.* 7 | 8 | class MainActivity : AppCompatActivity() { 9 | 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | setContentView(R.layout.activity_main) 13 | 14 | ///set locale 15 | currencyEn.locale = Locale.US 16 | 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.idea/runConfigurations.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 12 | -------------------------------------------------------------------------------- /.idea/gradle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 18 | 19 | -------------------------------------------------------------------------------- /app/src/androidTest/java/com/umut/soysal/example/ExampleInstrumentedTest.kt: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.example 2 | 3 | import android.support.test.InstrumentationRegistry 4 | import android.support.test.runner.AndroidJUnit4 5 | 6 | import org.junit.Test 7 | import org.junit.runner.RunWith 8 | 9 | import org.junit.Assert.* 10 | 11 | /** 12 | * Instrumented test, which will execute on an Android device. 13 | * 14 | * See [testing documentation](http://d.android.com/tools/testing). 15 | */ 16 | @RunWith(AndroidJUnit4::class) 17 | class ExampleInstrumentedTest { 18 | @Test 19 | fun useAppContext() { 20 | // Context of the app under test. 21 | val appContext = InstrumentationRegistry.getTargetContext() 22 | assertEquals("com.umut.soysal.example", appContext.packageName) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /app/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /app/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /currencyedittext/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | # Add project specific ProGuard rules here. 2 | # You can control the set of applied configuration files using the 3 | # proguardFiles setting in build.gradle. 4 | # 5 | # For more details, see 6 | # http://developer.android.com/guide/developing/tools/proguard.html 7 | 8 | # If your project uses WebView with JS, uncomment the following 9 | # and specify the fully qualified class name to the JavaScript interface 10 | # class: 11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview { 12 | # public *; 13 | #} 14 | 15 | # Uncomment this to preserve the line number information for 16 | # debugging stack traces. 17 | #-keepattributes SourceFile,LineNumberTable 18 | 19 | # If you keep the line number information, uncomment this to 20 | # hide the original source file name. 21 | #-renamesourcefileattribute SourceFile 22 | -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | # Project-wide Gradle settings. 2 | # IDE (e.g. Android Studio) users: 3 | # Gradle settings configured through the IDE *will override* 4 | # any settings specified in this file. 5 | # For more details on how to configure your build environment visit 6 | # http://www.gradle.org/docs/current/userguide/build_environment.html 7 | # Specifies the JVM arguments used for the daemon process. 8 | # The setting is particularly useful for tweaking memory settings. 9 | org.gradle.jvmargs=-Xmx1536m 10 | # When configured, Gradle will run in incubating parallel mode. 11 | # This option should only be used with decoupled projects. More details, visit 12 | # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects 13 | # org.gradle.parallel=true 14 | # Kotlin code style for this project: "official" or "obsolete": 15 | kotlin.code.style=official 16 | -------------------------------------------------------------------------------- /currencyedittext/src/androidTest/java/com/umut/soysal/lib/ExampleInstrumentedTest.java: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.lib; 2 | 3 | import android.content.Context; 4 | import android.support.test.InstrumentationRegistry; 5 | import android.support.test.runner.AndroidJUnit4; 6 | 7 | import org.junit.Test; 8 | import org.junit.runner.RunWith; 9 | 10 | import static org.junit.Assert.*; 11 | 12 | /** 13 | * Instrumented test, which will execute on an Android device. 14 | * 15 | * @see Testing documentation 16 | */ 17 | @RunWith(AndroidJUnit4.class) 18 | public class ExampleInstrumentedTest { 19 | @Test 20 | public void useAppContext() { 21 | // Context of the app under test. 22 | Context appContext = InstrumentationRegistry.getTargetContext(); 23 | 24 | assertEquals("com.umut.soysal.currencyedittext.test", appContext.getPackageName()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /currencyedittext/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.library' 2 | 3 | android { 4 | compileSdkVersion 28 5 | 6 | 7 | 8 | defaultConfig { 9 | minSdkVersion 15 10 | targetSdkVersion 28 11 | versionCode 1 12 | versionName "1.0" 13 | 14 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 15 | 16 | } 17 | 18 | buildTypes { 19 | release { 20 | minifyEnabled false 21 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 22 | } 23 | } 24 | 25 | } 26 | 27 | dependencies { 28 | implementation fileTree(dir: 'libs', include: ['*.jar']) 29 | 30 | implementation 'com.android.support:appcompat-v7:28.0.0' 31 | testImplementation 'junit:junit:4.12' 32 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 33 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 34 | } 35 | -------------------------------------------------------------------------------- /app/build.gradle: -------------------------------------------------------------------------------- 1 | apply plugin: 'com.android.application' 2 | 3 | apply plugin: 'kotlin-android' 4 | 5 | apply plugin: 'kotlin-android-extensions' 6 | 7 | android { 8 | compileSdkVersion 28 9 | defaultConfig { 10 | applicationId "com.umut.soysal.example" 11 | minSdkVersion 15 12 | targetSdkVersion 28 13 | versionCode 1 14 | versionName "1.0" 15 | testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" 16 | } 17 | buildTypes { 18 | release { 19 | minifyEnabled false 20 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' 21 | } 22 | } 23 | } 24 | 25 | dependencies { 26 | implementation fileTree(include: ['*.jar'], dir: 'libs') 27 | implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" 28 | implementation 'com.android.support:appcompat-v7:28.0.0' 29 | implementation 'com.android.support.constraint:constraint-layout:1.1.3' 30 | testImplementation 'junit:junit:4.12' 31 | androidTestImplementation 'com.android.support.test:runner:1.0.2' 32 | androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' 33 | implementation project(':currencyedittext') 34 | } 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CurrencyEdittext 2 | Android edittext currency mask library. 3 | 4 | By inserting additional properties into the [BlacKCaT27](https://github.com/BlacKCaT27/CurrencyEditText) library, the cursor remains fixed, and the cursor will no longer return to the beginning. The cursor will continue to stay where it is until you change it. 5 | 6 | The cursor will move to decimal part when you click to comma. 7 | 8 | # Gif 9 | 10 | 11 | 12 | # Setup 13 | 14 | * **Grade** 15 | Add it as a dependency to your `build.gradle` 16 | 17 | ```gradle 18 | 19 | allprojects { 20 | repositories { 21 | google() 22 | jcenter() 23 | maven { url 'https://jitpack.io' } 24 | } 25 | } 26 | ``` 27 | 28 | ```gradle 29 | 30 | dependencies { 31 | implementation 'com.github.umutsoysl:CurrencyEdittext:1.0.1' 32 | } 33 | 34 | ``` 35 | # Using 36 | 37 | * **You can use the library by adding to the XML side of your project.** 38 | 39 | ```xml 40 | 41 | 46 | 47 | ``` 48 | 49 | 50 | * **You can choose any locale.** 51 | 52 | ```kotlin 53 | /* 54 | set currency usd 55 | */ 56 | currencyEn.locale = Locale.US 57 | 58 | ``` 59 | License 60 | -------- 61 | 62 | 63 | Copyright 2019 Umut Soysal. 64 | 65 | Licensed under the Apache License, Version 2.0 (the "License"); 66 | you may not use this file except in compliance with the License. 67 | You may obtain a copy of the License at 68 | 69 | http://www.apache.org/licenses/LICENSE-2.0 70 | 71 | Unless required by applicable law or agreed to in writing, software 72 | distributed under the License is distributed on an "AS IS" BASIS, 73 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 74 | See the License for the specific language governing permissions and 75 | limitations under the License. 76 | -------------------------------------------------------------------------------- /app/src/main/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 12 | 13 | 19 | 22 | 25 | 26 | 27 | 28 | 34 | 35 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 18 | 19 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 34 | 35 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem 4 | @rem Gradle startup script for Windows 5 | @rem 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | set DIRNAME=%~dp0 12 | if "%DIRNAME%" == "" set DIRNAME=. 13 | set APP_BASE_NAME=%~n0 14 | set APP_HOME=%DIRNAME% 15 | 16 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 17 | set DEFAULT_JVM_OPTS= 18 | 19 | @rem Find java.exe 20 | if defined JAVA_HOME goto findJavaFromJavaHome 21 | 22 | set JAVA_EXE=java.exe 23 | %JAVA_EXE% -version >NUL 2>&1 24 | if "%ERRORLEVEL%" == "0" goto init 25 | 26 | echo. 27 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 28 | echo. 29 | echo Please set the JAVA_HOME variable in your environment to match the 30 | echo location of your Java installation. 31 | 32 | goto fail 33 | 34 | :findJavaFromJavaHome 35 | set JAVA_HOME=%JAVA_HOME:"=% 36 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 37 | 38 | if exist "%JAVA_EXE%" goto init 39 | 40 | echo. 41 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 42 | echo. 43 | echo Please set the JAVA_HOME variable in your environment to match the 44 | echo location of your Java installation. 45 | 46 | goto fail 47 | 48 | :init 49 | @rem Get command-line arguments, handling Windows variants 50 | 51 | if not "%OS%" == "Windows_NT" goto win9xME_args 52 | 53 | :win9xME_args 54 | @rem Slurp the command line arguments. 55 | set CMD_LINE_ARGS= 56 | set _SKIP=2 57 | 58 | :win9xME_args_slurp 59 | if "x%~1" == "x" goto execute 60 | 61 | set CMD_LINE_ARGS=%* 62 | 63 | :execute 64 | @rem Setup the command line 65 | 66 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 67 | 68 | @rem Execute Gradle 69 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% 70 | 71 | :end 72 | @rem End local scope for the variables with windows NT shell 73 | if "%ERRORLEVEL%"=="0" goto mainEnd 74 | 75 | :fail 76 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 77 | rem the _cmd.exe /c_ return code! 78 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 79 | exit /b 1 80 | 81 | :mainEnd 82 | if "%OS%"=="Windows_NT" endlocal 83 | 84 | :omega 85 | -------------------------------------------------------------------------------- /app/src/main/res/layout/activity_main.xml: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 20 | 21 | 33 | 34 | 45 | 46 | 59 | 60 | -------------------------------------------------------------------------------- /currencyedittext/src/main/java/com/umut/soysal/lib/CurrencyTextFormatter.java: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.lib; 2 | 3 | 4 | import android.util.Log; 5 | 6 | import java.text.DecimalFormat; 7 | import java.util.Currency; 8 | import java.util.Locale; 9 | 10 | public final class CurrencyTextFormatter { 11 | 12 | private CurrencyTextFormatter(){} 13 | 14 | public static String formatText(String val, Locale locale){ 15 | return formatText(val, locale, Locale.US, null); 16 | } 17 | 18 | public static String formatText(String val, Locale locale, Locale defaultLocale){ 19 | return formatText(val, locale, defaultLocale, null); 20 | } 21 | 22 | public static String formatText(String val, Locale locale, Locale defaultLocale, Integer decimalDigits){ 23 | 24 | if(val.equals("-")) return val; 25 | 26 | int currencyDecimalDigits; 27 | if (decimalDigits != null){ 28 | currencyDecimalDigits = decimalDigits; 29 | } 30 | else { 31 | Currency currency = Currency.getInstance(locale); 32 | try { 33 | currencyDecimalDigits = currency.getDefaultFractionDigits(); 34 | } catch (Exception e) { 35 | Log.e("CurrencyTextFormatter", "Illegal argument detected for currency: " + currency + ", using currency from defaultLocale: " + defaultLocale); 36 | currencyDecimalDigits = Currency.getInstance(defaultLocale).getDefaultFractionDigits(); 37 | } 38 | } 39 | 40 | DecimalFormat currencyFormatter; 41 | try { 42 | currencyFormatter = (DecimalFormat) DecimalFormat.getCurrencyInstance(locale); 43 | } catch (Exception e) { 44 | try { 45 | Log.e("CurrencyTextFormatter", "Error detected for locale: " + locale + ", falling back to default value: " + defaultLocale); 46 | currencyFormatter = (DecimalFormat) DecimalFormat.getCurrencyInstance(defaultLocale); 47 | } 48 | catch(Exception e1){ 49 | Log.e("CurrencyTextFormatter", "Error detected for defaultLocale: " + defaultLocale + ", falling back to USD."); 50 | currencyFormatter = (DecimalFormat) DecimalFormat.getCurrencyInstance(Locale.US); 51 | } 52 | } 53 | 54 | boolean isNegative = false; 55 | if (val.contains("-")){ 56 | isNegative = true; 57 | } 58 | 59 | val = val.replaceAll("[^\\d]", ""); 60 | 61 | if(!val.equals("")) { 62 | 63 | if (val.length() <= currencyDecimalDigits){ 64 | String formatString = "%" + currencyDecimalDigits + "s"; 65 | val = String.format(formatString, val).replace(' ', '0'); 66 | } 67 | 68 | String preparedVal = new StringBuilder(val).insert(val.length() - currencyDecimalDigits, '.').toString(); 69 | 70 | //Convert the string into a double, which will be passed into the currency formatter 71 | double newTextValue = Double.valueOf(preparedVal); 72 | 73 | newTextValue *= isNegative ? -1 : 1; 74 | 75 | currencyFormatter.setMinimumFractionDigits(currencyDecimalDigits); 76 | val = currencyFormatter.format(newTextValue); 77 | } 78 | else { 79 | throw new IllegalArgumentException("Invalid amount of digits found (either zero or too many) in argument val"); 80 | } 81 | return val; 82 | } 83 | 84 | } -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 36 | 37 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 78 | -------------------------------------------------------------------------------- /app/src/main/res/drawable/ic_launcher_background.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 | 26 | 28 | 30 | 32 | 34 | 36 | 38 | 40 | 42 | 44 | 46 | 48 | 50 | 52 | 54 | 56 | 58 | 60 | 62 | 64 | 66 | 68 | 70 | 72 | 74 | 75 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | 3 | ############################################################################## 4 | ## 5 | ## Gradle start up script for UN*X 6 | ## 7 | ############################################################################## 8 | 9 | # Attempt to set APP_HOME 10 | # Resolve links: $0 may be a link 11 | PRG="$0" 12 | # Need this for relative symlinks. 13 | while [ -h "$PRG" ] ; do 14 | ls=`ls -ld "$PRG"` 15 | link=`expr "$ls" : '.*-> \(.*\)$'` 16 | if expr "$link" : '/.*' > /dev/null; then 17 | PRG="$link" 18 | else 19 | PRG=`dirname "$PRG"`"/$link" 20 | fi 21 | done 22 | SAVED="`pwd`" 23 | cd "`dirname \"$PRG\"`/" >/dev/null 24 | APP_HOME="`pwd -P`" 25 | cd "$SAVED" >/dev/null 26 | 27 | APP_NAME="Gradle" 28 | APP_BASE_NAME=`basename "$0"` 29 | 30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 31 | DEFAULT_JVM_OPTS="" 32 | 33 | # Use the maximum available, or set MAX_FD != -1 to use that value. 34 | MAX_FD="maximum" 35 | 36 | warn () { 37 | echo "$*" 38 | } 39 | 40 | die () { 41 | echo 42 | echo "$*" 43 | echo 44 | exit 1 45 | } 46 | 47 | # OS specific support (must be 'true' or 'false'). 48 | cygwin=false 49 | msys=false 50 | darwin=false 51 | nonstop=false 52 | case "`uname`" in 53 | CYGWIN* ) 54 | cygwin=true 55 | ;; 56 | Darwin* ) 57 | darwin=true 58 | ;; 59 | MINGW* ) 60 | msys=true 61 | ;; 62 | NONSTOP* ) 63 | nonstop=true 64 | ;; 65 | esac 66 | 67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar 68 | 69 | # Determine the Java command to use to start the JVM. 70 | if [ -n "$JAVA_HOME" ] ; then 71 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 72 | # IBM's JDK on AIX uses strange locations for the executables 73 | JAVACMD="$JAVA_HOME/jre/sh/java" 74 | else 75 | JAVACMD="$JAVA_HOME/bin/java" 76 | fi 77 | if [ ! -x "$JAVACMD" ] ; then 78 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 79 | 80 | Please set the JAVA_HOME variable in your environment to match the 81 | location of your Java installation." 82 | fi 83 | else 84 | JAVACMD="java" 85 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 86 | 87 | Please set the JAVA_HOME variable in your environment to match the 88 | location of your Java installation." 89 | fi 90 | 91 | # Increase the maximum file descriptors if we can. 92 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then 93 | MAX_FD_LIMIT=`ulimit -H -n` 94 | if [ $? -eq 0 ] ; then 95 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 96 | MAX_FD="$MAX_FD_LIMIT" 97 | fi 98 | ulimit -n $MAX_FD 99 | if [ $? -ne 0 ] ; then 100 | warn "Could not set maximum file descriptor limit: $MAX_FD" 101 | fi 102 | else 103 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" 104 | fi 105 | fi 106 | 107 | # For Darwin, add options to specify how the application appears in the dock 108 | if $darwin; then 109 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" 110 | fi 111 | 112 | # For Cygwin, switch paths to Windows format before running java 113 | if $cygwin ; then 114 | APP_HOME=`cygpath --path --mixed "$APP_HOME"` 115 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 116 | JAVACMD=`cygpath --unix "$JAVACMD"` 117 | 118 | # We build the pattern for arguments to be converted via cygpath 119 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 120 | SEP="" 121 | for dir in $ROOTDIRSRAW ; do 122 | ROOTDIRS="$ROOTDIRS$SEP$dir" 123 | SEP="|" 124 | done 125 | OURCYGPATTERN="(^($ROOTDIRS))" 126 | # Add a user-defined pattern to the cygpath arguments 127 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 128 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 129 | fi 130 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 131 | i=0 132 | for arg in "$@" ; do 133 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 134 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 135 | 136 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 137 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 138 | else 139 | eval `echo args$i`="\"$arg\"" 140 | fi 141 | i=$((i+1)) 142 | done 143 | case $i in 144 | (0) set -- ;; 145 | (1) set -- "$args0" ;; 146 | (2) set -- "$args0" "$args1" ;; 147 | (3) set -- "$args0" "$args1" "$args2" ;; 148 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 149 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 150 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 151 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 152 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 153 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 154 | esac 155 | fi 156 | 157 | # Escape application args 158 | save () { 159 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done 160 | echo " " 161 | } 162 | APP_ARGS=$(save "$@") 163 | 164 | # Collect all arguments for the java command, following the shell quoting and substitution rules 165 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" 166 | 167 | # by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong 168 | if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then 169 | cd "$(dirname "$0")" 170 | fi 171 | 172 | exec "$JAVACMD" "$@" 173 | -------------------------------------------------------------------------------- /currencyedittext/src/main/java/com/umut/soysal/lib/CurrencyEditText.java: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.lib; 2 | 3 | 4 | import android.annotation.SuppressLint; 5 | import android.content.Context; 6 | import android.content.res.TypedArray; 7 | import android.text.Editable; 8 | import android.text.InputFilter; 9 | import android.text.InputType; 10 | import android.text.TextWatcher; 11 | import android.util.AttributeSet; 12 | import android.util.Log; 13 | import android.view.Gravity; 14 | import android.view.KeyEvent; 15 | import android.view.View; 16 | import android.widget.EditText; 17 | 18 | import java.util.Currency; 19 | import java.util.Locale; 20 | 21 | @SuppressLint("AppCompatCustomView") 22 | @SuppressWarnings("unused") 23 | public class CurrencyEditText extends EditText 24 | { 25 | private Locale currencyLocale; 26 | 27 | private Locale defaultLocale = Locale.US; 28 | 29 | private boolean allowNegativeValues = false; 30 | 31 | private long rawValue = 0L; 32 | 33 | private CurrencyTextWatcher textWatcher; 34 | private String hintCache = null; 35 | public static int cursor=0; 36 | private int decimalDigits = 0; 37 | private int mValueInLowestDenom = 0; 38 | 39 | 40 | public CurrencyEditText(Context context, AttributeSet attrs) 41 | { 42 | super(context, attrs); 43 | init(); 44 | processAttributes(context, attrs); 45 | } 46 | 47 | 48 | 49 | public void setAllowNegativeValues(boolean negativeValuesAllowed) 50 | { 51 | allowNegativeValues = negativeValuesAllowed; 52 | } 53 | 54 | 55 | public boolean areNegativeValuesAllowed() 56 | { 57 | return allowNegativeValues; 58 | } 59 | 60 | 61 | public long getRawValue() 62 | { 63 | return rawValue; 64 | } 65 | 66 | public void setValue(long value) 67 | { 68 | String formattedText = format(value); 69 | setText(formattedText); 70 | } 71 | 72 | 73 | public Locale getLocale() 74 | { 75 | return currencyLocale; 76 | } 77 | 78 | 79 | public void setLocale(Locale locale) 80 | { 81 | currencyLocale = locale; 82 | refreshView(); 83 | } 84 | 85 | 86 | public String getHintString() 87 | { 88 | CharSequence result = super.getHint(); 89 | if (result == null) return null; 90 | return super.getHint().toString(); 91 | } 92 | 93 | 94 | public int getDecimalDigits() 95 | { 96 | return decimalDigits; 97 | } 98 | 99 | 100 | public void setDecimalDigits(int digits) 101 | { 102 | if (digits < 0 || digits > 27) 103 | { 104 | throw new IllegalArgumentException("Decimal Digit value must be between 0 and 27"); 105 | } 106 | decimalDigits = digits; 107 | 108 | refreshView(); 109 | } 110 | 111 | 112 | public void configureViewForLocale(Locale locale) 113 | { 114 | this.currencyLocale = locale; 115 | Currency currentCurrency = getCurrencyForLocale(locale); 116 | decimalDigits = currentCurrency.getDefaultFractionDigits(); 117 | refreshView(); 118 | } 119 | 120 | 121 | public void setDefaultLocale(Locale locale) 122 | { 123 | this.defaultLocale = locale; 124 | } 125 | 126 | 127 | public Locale getDefaultLocale() 128 | { 129 | return defaultLocale; 130 | } 131 | 132 | 133 | public String formatCurrency(String val) 134 | { 135 | return format(val); 136 | } 137 | 138 | 139 | public String formatCurrency(long rawVal) 140 | { 141 | return format(rawVal); 142 | } 143 | 144 | 145 | private void refreshView() 146 | { 147 | setText(format(getRawValue())); 148 | updateHint(); 149 | } 150 | 151 | private String format(long val) 152 | { 153 | return CurrencyTextFormatter.formatText(String.valueOf(val), currencyLocale, defaultLocale, decimalDigits); 154 | } 155 | 156 | private String format(String val) 157 | { 158 | return CurrencyTextFormatter.formatText(val, currencyLocale, defaultLocale, decimalDigits); 159 | } 160 | 161 | private void init() 162 | { 163 | 164 | this.setOnKeyListener(new OnKeyListener() 165 | { 166 | public boolean onKey(View v, int keyCode, KeyEvent event) 167 | { 168 | if (keyCode == KeyEvent.KEYCODE_COMMA) 169 | { 170 | 171 | } 172 | else if (keyCode == KeyEvent.KEYCODE_NUMPAD_DOT) 173 | { 174 | 175 | } 176 | return false; 177 | } 178 | }); 179 | 180 | 181 | this.setGravity(Gravity.RIGHT); 182 | this.setInputType(InputType.TYPE_CLASS_TEXT); 183 | InputFilter[] filters = new InputFilter[1]; 184 | filters[0] = new InputFilter.LengthFilter(20); 185 | this.setFilters(filters); 186 | 187 | this.addTextChangedListener(new TextWatcher() 188 | { 189 | @Override 190 | public void beforeTextChanged(CharSequence s, int start, int count, int after) 191 | { 192 | changeDecimalKeyboard(); 193 | } 194 | 195 | @Override 196 | public void onTextChanged(CharSequence s, int start, int before, int count) 197 | { 198 | 199 | } 200 | 201 | @Override 202 | public void afterTextChanged(Editable s) 203 | { 204 | 205 | } 206 | }); 207 | 208 | 209 | currencyLocale = retrieveLocale(); 210 | Currency currentCurrency = getCurrencyForLocale(currencyLocale); 211 | decimalDigits = currentCurrency.getDefaultFractionDigits(); 212 | initCurrencyTextWatcher(); 213 | } 214 | 215 | protected void setValueInLowestDenom(int mValueInLowestDenom) 216 | { 217 | this.mValueInLowestDenom = mValueInLowestDenom; 218 | } 219 | 220 | private void changeDecimalKeyboard() 221 | { 222 | this.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED); 223 | } 224 | 225 | private void changeSignedKeyboard() 226 | { 227 | this.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED); 228 | } 229 | 230 | private void initCurrencyTextWatcher() 231 | { 232 | 233 | if (textWatcher != null) 234 | { 235 | this.removeTextChangedListener(textWatcher); 236 | } 237 | textWatcher = new CurrencyTextWatcher(this); 238 | this.addTextChangedListener(textWatcher); 239 | } 240 | 241 | private void processAttributes(Context context, AttributeSet attrs) 242 | { 243 | TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.CurrencyEditText); 244 | this.hintCache = getHintString(); 245 | updateHint(); 246 | 247 | this.setAllowNegativeValues(array.getBoolean(R.styleable.CurrencyEditText_allow_negative_values, false)); 248 | this.setDecimalDigits(array.getInteger(R.styleable.CurrencyEditText_decimal_digits, decimalDigits)); 249 | 250 | array.recycle(); 251 | } 252 | 253 | private void updateHint() 254 | { 255 | if (hintCache == null) 256 | { 257 | setHint(getDefaultHintValue()); 258 | } 259 | } 260 | 261 | private String getDefaultHintValue() 262 | { 263 | try 264 | { 265 | return Currency.getInstance(currencyLocale).getSymbol(); 266 | } 267 | catch (Exception e) 268 | { 269 | Log.w("CurrencyEditText", String.format("An error occurred while getting currency symbol for hint using locale '%s', falling back to defaultLocale", currencyLocale)); 270 | try 271 | { 272 | return Currency.getInstance(defaultLocale).getSymbol(); 273 | } 274 | catch (Exception e1) 275 | { 276 | Log.w("CurrencyEditText", String.format("An error occurred while getting currency symbol for hint using default locale '%s', falling back to USD", defaultLocale)); 277 | return Currency.getInstance(Locale.US).getSymbol(); 278 | } 279 | 280 | } 281 | } 282 | 283 | private Locale retrieveLocale() 284 | { 285 | Locale locale; 286 | try 287 | { 288 | locale = getResources().getConfiguration().locale; 289 | } 290 | catch (Exception e) 291 | { 292 | Log.w("CurrencyEditText", String.format("An error occurred while retrieving users device locale, using fallback locale '%s'", defaultLocale), e); 293 | locale = defaultLocale; 294 | } 295 | return locale; 296 | } 297 | 298 | private Currency getCurrencyForLocale(Locale locale) 299 | { 300 | Currency currency; 301 | try 302 | { 303 | currency = Currency.getInstance(locale); 304 | } 305 | catch (Exception e) 306 | { 307 | try 308 | { 309 | Log.w("CurrencyEditText", String.format("Error occurred while retrieving currency information for locale '%s'. Trying default locale '%s'...", currencyLocale, defaultLocale)); 310 | currency = Currency.getInstance(defaultLocale); 311 | } 312 | catch (Exception e1) 313 | { 314 | Log.e("CurrencyEditText", "Both device and configured default locales failed to report currentCurrency data. Defaulting to USD."); 315 | currency = Currency.getInstance(Locale.US); 316 | } 317 | } 318 | return currency; 319 | } 320 | 321 | protected void setRawValue(long value) 322 | { 323 | rawValue = value; 324 | } 325 | } -------------------------------------------------------------------------------- /currencyedittext/src/main/java/com/umut/soysal/lib/CurrencyTextWatcher.java: -------------------------------------------------------------------------------- 1 | package com.umut.soysal.lib; 2 | 3 | import android.text.Editable; 4 | import android.text.InputType; 5 | import android.text.TextWatcher; 6 | import android.view.KeyEvent; 7 | import android.view.View; 8 | 9 | class CurrencyTextWatcher implements TextWatcher 10 | { 11 | 12 | private CurrencyEditText editText; 13 | private boolean ignoreIteration; 14 | private String lastGoodInput; 15 | protected static int cursorPosition = 0; 16 | protected static boolean okcommo = false; 17 | protected static boolean clickDot = false; 18 | protected static boolean isEmpty = false; 19 | protected static boolean clickDelete = false; 20 | protected static boolean rightPost = false; 21 | public static int currentTextsize; 22 | 23 | 24 | CurrencyTextWatcher(CurrencyEditText textBox) 25 | { 26 | editText = textBox; 27 | lastGoodInput = ""; 28 | ignoreIteration = false; 29 | 30 | 31 | editText.setOnKeyListener(new View.OnKeyListener() 32 | { 33 | public boolean onKey(View v, int keyCode, KeyEvent event) 34 | { 35 | if (keyCode == KeyEvent.KEYCODE_DEL) 36 | { 37 | clickDelete = true; 38 | } 39 | else if (keyCode == 55) 40 | { 41 | clickDelete = false; 42 | okcommo = true; 43 | clickDot = true; 44 | cursorPosition = editText.getText().length() - 2; 45 | changeSignedKeyboard(); 46 | } 47 | else if (keyCode == 56) 48 | { 49 | clickDelete = false; 50 | okcommo = true; 51 | clickDot = true; 52 | cursorPosition = editText.getText().length() - 2; 53 | changeSignedKeyboard(); 54 | }else{ 55 | clickDelete = false; 56 | } 57 | return false; 58 | } 59 | }); 60 | 61 | } 62 | 63 | @Override 64 | public void afterTextChanged(Editable editable) 65 | { 66 | //Use the ignoreIteration flag to stop our edits to the text field from triggering an endlessly recursive call to afterTextChanged 67 | if (!ignoreIteration) 68 | { 69 | ignoreIteration = true; 70 | //Start by converting the editable to something easier to work with, then remove all non-digit characters 71 | String newText = editable.toString(); 72 | String textToDisplay; 73 | if (newText.length() < 1) 74 | { 75 | lastGoodInput = ""; 76 | editText.setRawValue(0); 77 | editText.setText(""); 78 | return; 79 | } 80 | 81 | if(clickDelete && okcommo &&(editable.toString().length()-2)<=editText.getSelectionStart()){ 82 | rightPost = true; 83 | if(editText.getSelectionStart()==editable.toString().length()-1){ 84 | newText = newText.substring(0,newText.length()-1) +"0"+newText.substring(newText.length()-1,newText.length()); 85 | }else if (editText.getSelectionStart()==editable.toString().length()){ 86 | newText = newText+ "0"; 87 | } 88 | }else{ 89 | rightPost = false; 90 | } 91 | 92 | if(!clickDelete&&editText.getSelectionStart()-1>=0) { 93 | String word = newText.substring(editText.getSelectionStart()-1,editText.getSelectionStart()); 94 | if(word.contentEquals(".") || word.contentEquals(",")){ 95 | okcommo = true; 96 | clickDot = true; 97 | }else{ 98 | okcommo = false; 99 | clickDot = false; 100 | } 101 | }else{ 102 | okcommo = false; 103 | clickDot = false; 104 | } 105 | 106 | newText = (editText.areNegativeValuesAllowed()) ? newText.replaceAll("[^0-9/-]", "") : newText.replaceAll("[^0-9]", ""); 107 | if (!newText.equals("") && !newText.equals("-")) 108 | { 109 | //Store a copy of the raw input to be retrieved later by getRawValue 110 | editText.setRawValue(Long.valueOf(newText)); 111 | } 112 | 113 | //ondalik bolumdesin 114 | if(!clickDelete&&!okcommo &&(editable.toString().length()-2)<=editText.getSelectionStart()){ 115 | newText = newText.substring(0,newText.length()-1); 116 | rightPost = true; 117 | }else{ 118 | rightPost = false; 119 | } 120 | 121 | 122 | try 123 | { 124 | textToDisplay = CurrencyTextFormatter.formatText(newText, editText.getLocale(), editText.getDefaultLocale(), editText.getDecimalDigits()); 125 | 126 | textToDisplay = textToDisplay.substring(1); 127 | 128 | } 129 | catch (IllegalArgumentException exception) 130 | { 131 | textToDisplay = lastGoodInput; 132 | } 133 | 134 | editText.setText(textToDisplay); 135 | //Store the last known good input so if there are any issues with new input later, we can fall back gracefully. 136 | lastGoodInput = textToDisplay; 137 | 138 | if(!clickDelete && rightPost && cursorPosition<=(editable.toString().length()-2)){ 139 | if(cursorPosition+2<=lastGoodInput.length()) { 140 | editText.setSelection(cursorPosition + 1); 141 | }else{ 142 | editText.setSelection(lastGoodInput.length()); 143 | } 144 | rightPost = false; 145 | }else if(!clickDelete && rightPost && cursorPosition==(editable.toString().length())){ 146 | editText.setSelection(lastGoodInput.length()); 147 | rightPost = false; 148 | } 149 | else { 150 | if (isEmpty) { 151 | editText.setSelection(1); 152 | cursorPosition = (1); 153 | isEmpty = false; 154 | } else if (okcommo) { 155 | if (cursorPosition != lastGoodInput.length()) { 156 | if (clickDot) { 157 | editText.setSelection(editText.length() - 2); 158 | clickDot = false; 159 | } else { 160 | editText.setSelection(cursorPosition + 1); 161 | } 162 | } else { 163 | editText.setSelection(textToDisplay.length() - 1); 164 | } 165 | } else { 166 | okcommo = false; 167 | int diff = Math.abs(currentTextsize - lastGoodInput.length()); 168 | if (clickDelete&&!rightPost) { 169 | if (diff == 2) { 170 | if(cursorPosition == 0){ 171 | editText.setSelection(0); 172 | }else { 173 | editText.setSelection(cursorPosition - 1); 174 | } 175 | } else if (diff > 2) { 176 | editText.setSelection(0); 177 | } else { 178 | editText.setSelection(cursorPosition); 179 | } 180 | clickDelete = false; 181 | }else if(clickDelete&&rightPost){ 182 | if(cursorPosition+1<=lastGoodInput.length()) { 183 | editText.setSelection(cursorPosition - 1); 184 | }else{ 185 | editText.setSelection(lastGoodInput.length()-3); 186 | } 187 | clickDelete = false; 188 | } 189 | else { 190 | if((cursorPosition + Math.abs(currentTextsize - lastGoodInput.length()))>lastGoodInput.length()){ 191 | editText.setSelection(editText.getSelectionStart()+1); 192 | }else{ 193 | 194 | editText.setSelection(cursorPosition + Math.abs(currentTextsize - lastGoodInput.length())); 195 | } 196 | 197 | } 198 | } 199 | } 200 | 201 | } 202 | else 203 | { 204 | ignoreIteration = false; 205 | if(isEmpty&&editable.toString().isEmpty()){ 206 | String tempText=null; 207 | try 208 | { 209 | tempText = CurrencyTextFormatter.formatText("000", editText.getLocale(), editText.getDefaultLocale(), editText.getDecimalDigits()); 210 | tempText = tempText.substring(1); 211 | 212 | } 213 | catch (IllegalArgumentException exception) 214 | { 215 | tempText = ""; 216 | } 217 | editText.setText(tempText); 218 | editText.setSelection(1); 219 | cursorPosition = (1); 220 | isEmpty = false; 221 | } 222 | } 223 | } 224 | 225 | 226 | @Override 227 | public void beforeTextChanged(CharSequence s, int start, int count, int after) 228 | { 229 | if (s.length() == 0) 230 | { 231 | isEmpty = true; 232 | } 233 | if (start != 0) 234 | { 235 | currentTextsize = s.toString().length(); 236 | cursorPosition = start; 237 | if(editText.getText().length()-3>=cursorPosition&&editText.getText().length()-3>0){ 238 | okcommo=false; 239 | }else{ 240 | okcommo=true; 241 | } 242 | }else if(start==0&&!ignoreIteration){ 243 | currentTextsize = s.toString().length(); 244 | cursorPosition = start; 245 | if(editText.getText().length()-3>=cursorPosition&&editText.getText().length()-3>0){ 246 | okcommo=false; 247 | }else{ 248 | okcommo=true; 249 | } 250 | } 251 | 252 | 253 | } 254 | 255 | @Override 256 | public void onTextChanged(final CharSequence s, int start, int before, int count) 257 | { } 258 | 259 | private void changeDecimalKeyboard() 260 | { 261 | editText.setRawInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_DECIMAL | InputType.TYPE_NUMBER_FLAG_SIGNED); 262 | } 263 | 264 | private void changeSignedKeyboard() 265 | { 266 | editText.setRawInputType(InputType.TYPE_CLASS_NUMBER); 267 | } 268 | 269 | 270 | } --------------------------------------------------------------------------------