Full Code of iamMehedi/PasscodeView for AI

master ef2d27200a5e cached
27 files
34.7 KB
9.0k tokens
42 symbols
1 requests
Download .txt
Repository: iamMehedi/PasscodeView
Branch: master
Commit: ef2d27200a5e
Files: 27
Total size: 34.7 KB

Directory structure:
gitextract_ztzyo5fi/

├── .gitignore
├── .idea/
│   ├── compiler.xml
│   ├── copyright/
│   │   └── profiles_settings.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── runConfigurations.xml
│   └── vcs.xml
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── mhk/
│       │               └── android/
│       │                   └── passcodeviewsample/
│       │                       └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── mhk/
│           │           └── android/
│           │               └── passcodeviewsample/
│           │                   └── SampleActivity.java
│           └── res/
│               ├── layout/
│               │   └── sample_activity.xml
│               └── values/
│                   ├── dimens.xml
│                   ├── strings.xml
│                   └── styles.xml
├── build.gradle
├── passcodeview/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── online/
│       │           └── devliving/
│       │               └── passcodeview/
│       │                   └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── online/
│           │       └── devliving/
│           │           └── passcodeview/
│           │               └── PasscodeView.java
│           └── res/
│               └── values/
│                   └── attrs.xml
└── settings.gradle

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Created by .ignore support plugin (hsz.mobi)
### Android template
# Built application files
*.apk
*.ap_

# Files for the ART/Dalvik VM
*.dex

# Java class files
*.class

# Generated files
bin/
gen/
out/

# Gradle files
.gradle/
build/

# Local configuration file (sdk path, etc)
local.properties

# Proguard folder generated by Eclipse
proguard/

# Log Files
*.log

# Android Studio Navigation editor temp files
.navigation/

# Android Studio captures folder
captures/

# Intellij
*.iml
.idea/workspace.xml
.idea/tasks.xml
.idea/gradle.xml
.idea/dictionaries
.idea/libraries

# Keystore files
*.jks

# External native build folder generated in Android Studio 2.2 and later
.externalNativeBuild

# Google Services (e.g. APIs or Firebase)
google-services.json

# Freeline
freeline.py
freeline/
freeline_project_description.json



================================================
FILE: .idea/compiler.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="CompilerConfiguration">
    <resourceExtensions />
    <wildcardResourcePatterns>
      <entry name="!?*.java" />
      <entry name="!?*.form" />
      <entry name="!?*.class" />
      <entry name="!?*.groovy" />
      <entry name="!?*.scala" />
      <entry name="!?*.flex" />
      <entry name="!?*.kt" />
      <entry name="!?*.clj" />
    </wildcardResourcePatterns>
    <annotationProcessing>
      <profile default="true" name="Default" enabled="false">
        <processorPath useClasspath="true" />
      </profile>
    </annotationProcessing>
  </component>
</project>

================================================
FILE: .idea/copyright/profiles_settings.xml
================================================
<component name="CopyrightManager">
  <settings default="" />
</component>

================================================
FILE: .idea/misc.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="EntryPointsManager">
    <entry_points version="2.0" />
  </component>
  <component name="NullableNotNullManager">
    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
    <option name="myNullables">
      <value>
        <list size="4">
          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
        </list>
      </value>
    </option>
    <option name="myNotNulls">
      <value>
        <list size="4">
          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
        </list>
      </value>
    </option>
  </component>
  <component name="ProjectLevelVcsManager" settingsEditedManually="false">
    <OptionsSetting value="true" id="Add" />
    <OptionsSetting value="true" id="Remove" />
    <OptionsSetting value="true" id="Checkout" />
    <OptionsSetting value="true" id="Update" />
    <OptionsSetting value="true" id="Status" />
    <OptionsSetting value="true" id="Edit" />
    <ConfirmationsSetting value="0" id="Add" />
    <ConfirmationsSetting value="0" id="Remove" />
  </component>
  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
    <output url="file://$PROJECT_DIR$/build/classes" />
  </component>
  <component name="ProjectType">
    <option name="id" value="Android" />
  </component>
  <component name="masterDetails">
    <states>
      <state key="ProjectJDKs.UI">
        <settings>
          <last-edited>Android API 22 Platform</last-edited>
          <splitter-proportions>
            <option name="proportions">
              <list>
                <option value="0.2" />
              </list>
            </option>
          </splitter-proportions>
        </settings>
      </state>
    </states>
  </component>
</project>

================================================
FILE: .idea/modules.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="ProjectModuleManager">
    <modules>
      <module fileurl="file://$PROJECT_DIR$/PasscodeView.iml" filepath="$PROJECT_DIR$/PasscodeView.iml" />
      <module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
      <module fileurl="file://$PROJECT_DIR$/passcodeview/passcodeview.iml" filepath="$PROJECT_DIR$/passcodeview/passcodeview.iml" />
    </modules>
  </component>
</project>

================================================
FILE: .idea/runConfigurations.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="RunConfigurationProducerService">
    <option name="ignoredProducers">
      <set>
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
        <option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
      </set>
    </option>
  </component>
</project>

================================================
FILE: .idea/vcs.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
  <component name="VcsDirectoryMappings">
    <mapping directory="$PROJECT_DIR$" vcs="Git" />
  </component>
</project>

================================================
FILE: README.md
================================================
# PasscodeView
[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LICENSE-2.0)
[ ![Download](https://api.bintray.com/packages/iammehedi/Maven/online.devliving%3Apasscodeview/images/download.svg) ](https://bintray.com/iammehedi/Maven/online.devliving%3Apasscodeview/_latestVersion)

An android widget to input passcode.

## Setup
### Maven
```xml
<dependency>
  <groupId>online.devliving</groupId>
  <artifactId>passcodeview</artifactId>
  <version>1.0.3</version>
  <type>pom</type>
</dependency>
```
### Gradle
```groovy
compile 'online.devliving:passcodeview:1.0.3'
```

## Usage
`PasscodeView` is a `ViewGroup` subclass. So it can easily be added in any xml layout file.

```xml
<online.devliving.passcodeview.PasscodeView
        android:id="@+id/passcode_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        passcodeView:numDigits="5"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        />
```

### Methods
- `requestToShowKeyboard()` - Request the PasscodeView to be focused programmatically
- `setText(CharSequence text)` - Set Passcode programmatically
- `clearText()` - Clear Passcode
- `getText()` - get entered Passcode
- `setPasscodeEntryListener(PasscodeEntryListener mPasscodeEntryListener)` - Set a listener to get notified when the Passcode has been entered

### Listener:`PasscodeEntryListener`
- `onPasscodeEntered(String passcode)` - Called when all the digits of the passcode has been entered

```java
passcodeView.setPasscodeEntryListener(new PasscodeView.PasscodeEntryListener() {
            @Override
            public void onPasscodeEntered(String passcode) {
                Toast.makeText(SampleActivity.this, "Passcode entered: " + passcode, Toast.LENGTH_SHORT).show();
            }
        });
```

### XML Attributes
- `numDigits` - Number of passcode digits
- `digitElevation` - Elevation of each digit, only applicable for OS version >= Lollipop
- `digitRadius` - radius for digit circle `16dip` by default
- `digitInnerRadius` - radius for digit inner circle `10dip` by default
- `controlColor` - color of the outer circle in normal state, by default `android:colorControlNormal`
- `controlColorActivated` - color of outer circle when focused, by default `android:colorControlHighlighted`
- `digitColorFilled` - fill color of the inner circle, by default `android:colorPrimary`
- `digitColorBorder` - border color of the inner circle, by default `android:colorPrimaryDark`

## Demo
![image](demo.gif)

## License

    Licensed under the Apache License, Version 2.0 (the "License");
    you may not use this file except in compliance with the License.
    You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

    Unless required by applicable law or agreed to in writing, software
    distributed under the License is distributed on an "AS IS" BASIS,
    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    See the License for the specific language governing permissions and
    limitations under the License.


================================================
FILE: app/.gitignore
================================================
/build


================================================
FILE: app/build.gradle
================================================
apply plugin: 'com.android.application'

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"

    defaultConfig {
        applicationId "com.mhk.android.passcodeviewsample"
        minSdkVersion 10
        targetSdkVersion 25
        versionCode 2
        versionName "1.0.1"
    }

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

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.3.1'
    compile project(':passcodeview')
}


================================================
FILE: app/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Volumes/Work/SDK/Android/Development/adt bundle/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: app/src/androidTest/java/com/mhk/android/passcodeviewsample/ApplicationTest.java
================================================
package com.mhk.android.passcodeviewsample;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
 */
public class ApplicationTest extends ApplicationTestCase<Application> {
    public ApplicationTest() {
        super(Application.class);
    }
}

================================================
FILE: app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.mhk.android.passcodeviewsample" >

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >

        <activity android:name=".SampleActivity" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>

    </application>

</manifest>


================================================
FILE: app/src/main/java/com/mhk/android/passcodeviewsample/SampleActivity.java
================================================
package com.mhk.android.passcodeviewsample;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.widget.Toast;

import online.devliving.passcodeview.PasscodeView;

/**
 * Created by Mehedi Hasan Khan on 9/6/15.
 */
public class SampleActivity extends AppCompatActivity{

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.sample_activity);

        final PasscodeView pcView = (PasscodeView) findViewById(R.id.passcode_view);

        pcView.postDelayed(new Runnable() {
            @Override
            public void run() {
                pcView.requestToShowKeyboard();
            }
        }, 400);

        pcView.setPasscodeEntryListener(new PasscodeView.PasscodeEntryListener() {
            @Override
            public void onPasscodeEntered(String passcode) {
                Toast.makeText(SampleActivity.this, "Passcode entered: " + passcode, Toast.LENGTH_SHORT).show();
            }
        });

        Log.d("SAMPLE", "Activity created");
    }
}


================================================
FILE: app/src/main/res/layout/sample_activity.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:passcodeView="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:padding="@dimen/activity_vertical_margin"
    android:background="@android:color/white">

    <online.devliving.passcodeview.PasscodeView
        android:id="@+id/passcode_view"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal"
        passcodeView:numDigits="5"
        passcodeView:digitRadius="16dp"
        passcodeView:digitInnerRadius="10dp"
        android:layout_marginTop="@dimen/activity_vertical_margin"
        />

</LinearLayout>

================================================
FILE: app/src/main/res/values/dimens.xml
================================================
<resources>
    <!-- Default screen margins, per the Android Design guidelines. -->
    <dimen name="activity_horizontal_margin">16dp</dimen>
    <dimen name="activity_vertical_margin">16dp</dimen>
</resources>


================================================
FILE: app/src/main/res/values/strings.xml
================================================
<resources>
    <string name="app_name">PasscodeView Sample</string>
</resources>


================================================
FILE: app/src/main/res/values/styles.xml
================================================
<resources>

    <!-- Base application theme. -->
    <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
        <!-- Customize your theme here. -->
        <item name="colorControlNormal">#8e8f8f</item>
        <item name="colorControlHighlight">#c6c7c7</item>
        <item name="colorAccent">#399ce4</item>
        <item name="colorPrimary">#2caae1</item>
        <item name="colorPrimaryDark">#1880ae</item>
    </style>

</resources>


================================================
FILE: build.gradle
================================================
// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'

        classpath 'com.github.dcendents:android-maven-gradle-plugin:1.4.1'
        classpath 'com.jfrog.bintray.gradle:gradle-bintray-plugin:1.1'

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

allprojects {
    repositories {
        jcenter()
    }
}

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


================================================
FILE: passcodeview/.gitignore
================================================
/build


================================================
FILE: passcodeview/build.gradle
================================================
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: "com.jfrog.bintray"

version = "1.0.3"

android {
    compileSdkVersion 25
    buildToolsVersion "25.0.3"

    defaultConfig {
        minSdkVersion 10
        targetSdkVersion 25
        versionCode 4
        versionName version
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:25.3.1'
}

def siteUrl = "https://github.com/iamMehedi/PasscodeView"
def gitUrl = "https://github.com/iamMehedi/PasscodeView.git"

group = "online.devliving"

install {
    repositories.mavenInstaller {
        // This generates POM.xml with proper parameters
        pom {
            project {
                packaging 'aar'

                // Add your description here
                name 'online.devliving:passcodeview'
                description = 'An android widget to input passcode.'
                url siteUrl

                // Set your license
                licenses {
                    license {
                        name 'The Apache Software License, Version 2.0'
                        url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
                    }
                }
                developers {
                    developer {
                        id 'im_mehedi'
                        name 'Mehedi Hasan Khan'
                        email 'mehedi.mailing@gmail.com'
                    }
                }
                scm {
                    connection gitUrl
                    developerConnection gitUrl
                    url siteUrl
                }
            }
        }
    }
}

task sourcesJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier = 'sources'
}

task javadoc(type: Javadoc) {
    source = android.sourceSets.main.java.srcDirs
    classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
    failOnError false
}

task javadocJar(type: Jar, dependsOn: javadoc) {
    classifier = 'javadoc'
    from javadoc.destinationDir
}
artifacts {
    archives javadocJar
    archives sourcesJar
}

Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

// https://github.com/bintray/gradle-bintray-plugin
bintray {
    user = properties.getProperty("bintray.user")
    key = properties.getProperty("bintray.apikey")

    configurations = ['archives']
    pkg {
        repo = "Maven"
        // it is the name that appears in bintray when logged
        name = "online.devliving:passcodeview"
        websiteUrl = siteUrl
        vcsUrl = gitUrl
        licenses = ["Apache-2.0"]
        publish = true
        version {
            gpg {
                sign = true //Determines whether to GPG sign the files. The default is false
                passphrase = properties.getProperty("bintray.gpg.password")
                //Optional. The passphrase for GPG signing'
            }
        }
    }
}

//apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'


================================================
FILE: passcodeview/proguard-rules.pro
================================================
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /Volumes/Work/SDK/Android/Development/adt bundle/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
#   http://developer.android.com/guide/developing/tools/proguard.html

# Add any project specific keep options here:

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
#   public *;
#}


================================================
FILE: passcodeview/src/androidTest/java/online/devliving/passcodeview/ApplicationTest.java
================================================
package online.devliving.passcodeview;

import android.app.Application;
import android.test.ApplicationTestCase;

/**
 * <a href="http://d.android.com/tools/testing/testing_android.html">Testing Fundamentals</a>
 */
public class ApplicationTest extends ApplicationTestCase<Application> {
    public ApplicationTest() {
        super(Application.class);
    }
}

================================================
FILE: passcodeview/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="online.devliving.passcodeview">

    <application android:allowBackup="true" >

    </application>

</manifest>


================================================
FILE: passcodeview/src/main/java/online/devliving/passcodeview/PasscodeView.java
================================================
package online.devliving.passcodeview;

import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;

/**
 * Created by Mehedi Hasan Khan (mehedi.mailing@gmail.com).
 */
public class PasscodeView extends ViewGroup{

    EditText mEditText;
    int mDigitCount;

    private int mDigitWidth;
    private int mDigitRadius;
    private int mOuterStrokeWidth;
    private int mInnerStrokeWidth;
    private int mDigitInnerRadius;
    private int mDigitSpacing;
    private int mDigitElevation;

    private int mControlColor;
    private int mHighlightedColor;
    private int mInnerColor;
    private int mInnerBorderColor;

    private OnFocusChangeListener mOnFocusChangeListener;
    private PasscodeEntryListener mPasscodeEntryListener;

    public PasscodeView(Context context) {
        this(context, null);
    }

    public PasscodeView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public PasscodeView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        // Get style information
        TypedArray array = getContext().obtainStyledAttributes(attrs, R.styleable.PasscodeView);
        mDigitCount = array.getInt(R.styleable.PasscodeView_numDigits, 4);

        // Dimensions
        DisplayMetrics metrics = getResources().getDisplayMetrics();
        mDigitRadius = array.getDimensionPixelSize(R.styleable.PasscodeView_digitRadius,
                (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, metrics));
        mOuterStrokeWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 2, metrics);
        mInnerStrokeWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 1, metrics);
        mDigitInnerRadius = array.getDimensionPixelSize(R.styleable.PasscodeView_digitInnerRadius,
                mDigitRadius - ((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6, metrics)));

        if(mDigitInnerRadius > mDigitRadius){
            mDigitInnerRadius = mDigitRadius - ((int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 6, metrics));
        }

        mDigitWidth = (mDigitRadius + mOuterStrokeWidth) * 2;

        mDigitSpacing = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 16, metrics);

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mDigitElevation = array.getDimensionPixelSize(R.styleable.PasscodeView_digitElevation, 0);
        }

        // Get theme to resolve defaults
        Resources.Theme theme = getContext().getTheme();

        mControlColor = Color.DKGRAY;
        // Text colour, default to android:colorControlNormal from theme
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            TypedValue controlColor = new TypedValue();
            theme.resolveAttribute(android.R.attr.colorControlNormal, controlColor, true);
            mControlColor = controlColor.resourceId > 0 ? getResources().getColor(controlColor.resourceId) :
                    controlColor.data;
        }
        mControlColor = array.getColor(R.styleable.PasscodeView_controlColor, mControlColor);

        // Accent colour, default to android:colorAccent from theme
        mHighlightedColor = Color.LTGRAY;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            TypedValue accentColor = new TypedValue();
            theme.resolveAttribute(R.attr.colorControlHighlight, accentColor, true);
            mHighlightedColor = accentColor.resourceId > 0 ? getResources().getColor(accentColor.resourceId) :
                    accentColor.data;
        }
        mHighlightedColor = array.getColor(R.styleable.PasscodeView_controlColorActivated, mHighlightedColor);

        //color for the inner circle
        mInnerColor = Color.CYAN;

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            TypedValue innerColor = new TypedValue();
            theme.resolveAttribute(android.R.attr.colorPrimary, innerColor, true);
            mInnerColor = innerColor.resourceId > 0 ? getResources().getColor(innerColor.resourceId) :
                    innerColor.data;
        }
        mInnerColor = array.getColor(R.styleable.PasscodeView_digitColorFilled, mInnerColor);

        //color for the inner circle border
        mInnerBorderColor = Color.GREEN;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            TypedValue innerBorderColor = new TypedValue();
            theme.resolveAttribute(android.R.attr.colorPrimaryDark, innerBorderColor, true);
            mInnerBorderColor = innerBorderColor.resourceId > 0 ? getResources().getColor(innerBorderColor.resourceId) :
                    innerBorderColor.data;
        }
        mInnerBorderColor = array.getColor(R.styleable.PasscodeView_digitColorBorder, mInnerBorderColor);

        // Recycle the typed array
        array.recycle();

        // Add child views
        setupViews();
    }

    @Override
    public boolean shouldDelayChildPressedState() {
        return false;
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        // Measure children
        for (int i = 0; i < getChildCount(); i ++) {
            getChildAt(i).measure(widthMeasureSpec, heightMeasureSpec);
        }

        // Calculate the size of the view
        int width = (mDigitWidth * mDigitCount) + (mDigitSpacing * (mDigitCount - 1));
        setMeasuredDimension(
                width + getPaddingLeft() + getPaddingRight() + (mDigitElevation * 2),
                mDigitWidth + getPaddingTop() + getPaddingBottom() + (mDigitElevation * 2));
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        // Position the child views
        for (int i = 0; i < mDigitCount; i++) {
            View child = getChildAt(i);
            int left = i * mDigitWidth + (i > 0 ? i * mDigitSpacing : 0);
            child.layout(
                    left + getPaddingLeft() + mDigitElevation,
                    getPaddingTop() + (mDigitElevation / 2),
                    left + getPaddingLeft() + mDigitElevation + mDigitWidth,
                    getPaddingTop() + (mDigitElevation / 2) + mDigitWidth);
        }

        // Add the edit text as a 1px wide view to allow it to focus
        getChildAt(mDigitCount).layout(0, 0, 1, getMeasuredHeight());
    }

    private void setupViews(){
        setWillNotDraw(false);
        // Add a digit view for each digit
        for (int i = 0; i < mDigitCount; i++) {
            DigitView digitView = new DigitView(getContext(), i);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                digitView.setElevation(mDigitElevation);
            }
            addView(digitView);
        }

        // Add an "invisible" edit text to handle input
        mEditText = new EditText(getContext());
        mEditText.setBackgroundColor(getResources().getColor(android.R.color.transparent));
        mEditText.setTextColor(getResources().getColor(android.R.color.transparent));
        mEditText.setCursorVisible(false);
        mEditText.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mDigitCount)});
        mEditText.setInputType(InputType.TYPE_CLASS_NUMBER);
        mEditText.setKeyListener(DigitsKeyListener.getInstance("1234567890"));
        mEditText.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
        mEditText.setOnFocusChangeListener(new OnFocusChangeListener() {
            @Override
            public void onFocusChange(View v, boolean hasFocus) {
                // Update the selected state of the views
                int length = mEditText.getText().length();
                updateChilViewSelectionStates(length, hasFocus);
                // Make sure the cursor is at the end
                mEditText.setSelection(length);

                // Provide focus change events to any listener
                if (mOnFocusChangeListener != null) {
                    mOnFocusChangeListener.onFocusChange(PasscodeView.this, hasFocus);
                }
            }
        });

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

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

            @Override
            public void afterTextChanged(Editable s) {
                int length = s.length();
                updateChilViewSelectionStates(length, mEditText.hasFocus());

                if (length == mDigitCount && mPasscodeEntryListener != null) {
                    mPasscodeEntryListener.onPasscodeEntered(s.toString());
                }
            }
        });
        addView(mEditText);

        invalidate();
    }

    private void updateChilViewSelectionStates(int length, boolean hasFocus){
        for (int i = 0; i < mDigitCount; i++) {
            getChildAt(i).setSelected(hasFocus && i == length);
        }
    }

    /**
     * Get the {@link Editable} from the EditText
     *
     * @return
     */
    public Editable getText() {
        return mEditText.getText();
    }

    /**
     * Set text to the EditText
     *
     * @param text
     */
    public void setText(CharSequence text) {
        if (text.length() > mDigitCount) {
            text = text.subSequence(0, mDigitCount);
        }
        mEditText.setText(text);
        invalidateChildViews();
    }

    /**
     * Clear passcode input
     */
    public void clearText() {
        mEditText.setText("");
        invalidateChildViews();
    }

    private void invalidateChildViews(){
        for(int i =0; i<mDigitCount; i++)
        {
            getChildAt(i).invalidate();
        }
    }

    public void setPasscodeEntryListener(PasscodeEntryListener mPasscodeEntryListener) {
        this.mPasscodeEntryListener = mPasscodeEntryListener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            requestToShowKeyboard();
            return true;
        }
        return super.onTouchEvent(event);
    }

    /**
     * Requests the view to be focused and the keyboard to be popped-up
     */
    public void requestToShowKeyboard(){
        // Make sure this view is focused
        mEditText.requestFocus();

        // Show keyboard
        InputMethodManager inputMethodManager = (InputMethodManager) getContext()
                .getSystemService(Context.INPUT_METHOD_SERVICE);
        inputMethodManager.showSoftInput(mEditText, 0);
    }

    @Override
    public OnFocusChangeListener getOnFocusChangeListener() {
        return mOnFocusChangeListener;
    }

    @Override
    public void setOnFocusChangeListener(OnFocusChangeListener l) {
        mOnFocusChangeListener = l;
    }

    @Override
    protected Parcelable onSaveInstanceState() {
        Parcelable parcelable = super.onSaveInstanceState();
        SavedState savedState = new SavedState(parcelable);
        savedState.editTextValue = mEditText.getText().toString();
        return savedState;
    }

    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        SavedState savedState = (SavedState) state;
        super.onRestoreInstanceState(savedState.getSuperState());
        mEditText.setText(savedState.editTextValue);
        mEditText.setSelection(savedState.editTextValue.length());
    }

    static class SavedState extends BaseSavedState {

        public static final Parcelable.Creator<SavedState> CREATOR =
                new Parcelable.Creator<SavedState>() {
                    @Override
                    public SavedState createFromParcel(Parcel in) {
                        return new SavedState(in);
                    }

                    @Override
                    public SavedState[] newArray(int size) {
                        return new SavedState[size];
                    }
                };
        String editTextValue;

        public SavedState(Parcelable superState) {
            super(superState);
        }

        private SavedState(Parcel source) {
            super(source);
            editTextValue = source.readString();
        }

        @Override
        public void writeToParcel(Parcel dest, int flags) {
            super.writeToParcel(dest, flags);
            dest.writeString(editTextValue);
        }
    }

    class DigitView extends View{

        private Paint mOuterPaint, mInnerPaint;
        private int mPosition = 0;

        public DigitView(Context context, int position)
        {
            this(context);
            mPosition = position;
        }

        public DigitView(Context context) {
            this(context, null);
        }

        public DigitView(Context context, AttributeSet attrs) {
            this(context, attrs, 0);
        }

        public DigitView(Context context, AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);

            init();
        }

        void init(){
            setWillNotDraw(false);
            if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB){
                setLayerType(LAYER_TYPE_SOFTWARE, null);
            }
            mOuterPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mOuterPaint.setAlpha(255);
            mOuterPaint.setDither(true);
            mOuterPaint.setStyle(Paint.Style.STROKE);
            mOuterPaint.setStrokeWidth(mOuterStrokeWidth);
            mOuterPaint.setStrokeCap(Paint.Cap.ROUND);
            mOuterPaint.setStrokeJoin(Paint.Join.ROUND);
            mOuterPaint.setShadowLayer(2, 0, 0, Color.parseColor("#B4999999"));

            mInnerPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mInnerPaint.setAlpha(255);
            mInnerPaint.setStyle(Paint.Style.FILL_AND_STROKE);
            mInnerPaint.setStrokeWidth(mInnerStrokeWidth);
            mInnerPaint.setStrokeCap(Paint.Cap.ROUND);
            mInnerPaint.setStrokeJoin(Paint.Join.ROUND);
            mInnerPaint.setColor(mInnerColor);

            invalidate();
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            setMeasuredDimension(mDigitWidth, mDigitWidth);
        }

        @Override
        protected void onDraw(Canvas canvas) {
            float center = getWidth()/2;

            if(isSelected())
            {
                mOuterPaint.setColor(mHighlightedColor);
            }
            else
            {
                mOuterPaint.setColor(mControlColor);
            }
            canvas.drawColor(Color.TRANSPARENT);
            canvas.drawCircle(center, center, mDigitRadius, mOuterPaint);
            if(mEditText.getText().length() > mPosition)
            {
                canvas.drawCircle(center, center, mDigitInnerRadius, mInnerPaint);
            }
        }
    }

    /**
     * Listener that gets notified when the complete passcode has been entered
     */
    public interface PasscodeEntryListener{
        /**
         * Called when all the digits of the passcode has been entered
         * @param passcode - The entered passcode
         */
        void onPasscodeEntered(String passcode);
    }
}

================================================
FILE: passcodeview/src/main/res/values/attrs.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="PasscodeView">
        <attr name="numDigits" format="integer"/>
        <attr name="digitElevation" format="dimension"/>
        <attr name="digitRadius" format="dimension"/>
        <attr name="digitInnerRadius" format="dimension"/>
        <attr name="controlColor" format="color"/>
        <attr name="controlColorActivated" format="color"/>
        <attr name="digitColorFilled" format="color"/>
        <attr name="digitColorBorder" format="color"/>
    </declare-styleable>
</resources>

================================================
FILE: settings.gradle
================================================
include ':app', ':passcodeview'
Download .txt
gitextract_ztzyo5fi/

├── .gitignore
├── .idea/
│   ├── compiler.xml
│   ├── copyright/
│   │   └── profiles_settings.xml
│   ├── misc.xml
│   ├── modules.xml
│   ├── runConfigurations.xml
│   └── vcs.xml
├── README.md
├── app/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── com/
│       │           └── mhk/
│       │               └── android/
│       │                   └── passcodeviewsample/
│       │                       └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── com/
│           │       └── mhk/
│           │           └── android/
│           │               └── passcodeviewsample/
│           │                   └── SampleActivity.java
│           └── res/
│               ├── layout/
│               │   └── sample_activity.xml
│               └── values/
│                   ├── dimens.xml
│                   ├── strings.xml
│                   └── styles.xml
├── build.gradle
├── passcodeview/
│   ├── .gitignore
│   ├── build.gradle
│   ├── proguard-rules.pro
│   └── src/
│       ├── androidTest/
│       │   └── java/
│       │       └── online/
│       │           └── devliving/
│       │               └── passcodeview/
│       │                   └── ApplicationTest.java
│       └── main/
│           ├── AndroidManifest.xml
│           ├── java/
│           │   └── online/
│           │       └── devliving/
│           │           └── passcodeview/
│           │               └── PasscodeView.java
│           └── res/
│               └── values/
│                   └── attrs.xml
└── settings.gradle
Download .txt
SYMBOL INDEX (42 symbols across 4 files)

FILE: app/src/androidTest/java/com/mhk/android/passcodeviewsample/ApplicationTest.java
  class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
    method ApplicationTest (line 10) | public ApplicationTest() {

FILE: app/src/main/java/com/mhk/android/passcodeviewsample/SampleActivity.java
  class SampleActivity (line 13) | public class SampleActivity extends AppCompatActivity{
    method onCreate (line 15) | @Override

FILE: passcodeview/src/androidTest/java/online/devliving/passcodeview/ApplicationTest.java
  class ApplicationTest (line 9) | public class ApplicationTest extends ApplicationTestCase<Application> {
    method ApplicationTest (line 10) | public ApplicationTest() {

FILE: passcodeview/src/main/java/online/devliving/passcodeview/PasscodeView.java
  class PasscodeView (line 30) | public class PasscodeView extends ViewGroup{
    method PasscodeView (line 51) | public PasscodeView(Context context) {
    method PasscodeView (line 55) | public PasscodeView(Context context, AttributeSet attrs) {
    method PasscodeView (line 59) | public PasscodeView(Context context, AttributeSet attrs, int defStyleA...
    method shouldDelayChildPressedState (line 139) | @Override
    method onMeasure (line 144) | @Override
    method onLayout (line 158) | @Override
    method setupViews (line 175) | private void setupViews(){
    method updateChilViewSelectionStates (line 235) | private void updateChilViewSelectionStates(int length, boolean hasFocus){
    method getText (line 246) | public Editable getText() {
    method setText (line 255) | public void setText(CharSequence text) {
    method clearText (line 266) | public void clearText() {
    method invalidateChildViews (line 271) | private void invalidateChildViews(){
    method setPasscodeEntryListener (line 278) | public void setPasscodeEntryListener(PasscodeEntryListener mPasscodeEn...
    method onTouchEvent (line 282) | @Override
    method requestToShowKeyboard (line 294) | public void requestToShowKeyboard(){
    method getOnFocusChangeListener (line 304) | @Override
    method setOnFocusChangeListener (line 309) | @Override
    method onSaveInstanceState (line 314) | @Override
    method onRestoreInstanceState (line 322) | @Override
    class SavedState (line 330) | static class SavedState extends BaseSavedState {
      method createFromParcel (line 334) | @Override
      method newArray (line 339) | @Override
      method SavedState (line 346) | public SavedState(Parcelable superState) {
      method SavedState (line 350) | private SavedState(Parcel source) {
      method writeToParcel (line 355) | @Override
    class DigitView (line 362) | class DigitView extends View{
      method DigitView (line 367) | public DigitView(Context context, int position)
      method DigitView (line 373) | public DigitView(Context context) {
      method DigitView (line 377) | public DigitView(Context context, AttributeSet attrs) {
      method DigitView (line 381) | public DigitView(Context context, AttributeSet attrs, int defStyleAt...
      method init (line 387) | void init(){
      method onMeasure (line 412) | @Override
      method onDraw (line 417) | @Override
    type PasscodeEntryListener (line 441) | public interface PasscodeEntryListener{
      method onPasscodeEntered (line 446) | void onPasscodeEntered(String passcode);
Condensed preview — 27 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (39K chars).
[
  {
    "path": ".gitignore",
    "chars": 829,
    "preview": "# Created by .ignore support plugin (hsz.mobi)\n### Android template\n# Built application files\n*.apk\n*.ap_\n\n# Files for t"
  },
  {
    "path": ".idea/compiler.xml",
    "chars": 656,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"CompilerConfiguration\">\n    <resourceExt"
  },
  {
    "path": ".idea/copyright/profiles_settings.xml",
    "chars": 74,
    "preview": "<component name=\"CopyrightManager\">\n  <settings default=\"\" />\n</component>"
  },
  {
    "path": ".idea/misc.xml",
    "chars": 2649,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"EntryPointsManager\">\n    <entry_points v"
  },
  {
    "path": ".idea/modules.xml",
    "chars": 494,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"ProjectModuleManager\">\n    <modules>\n   "
  },
  {
    "path": ".idea/runConfigurations.xml",
    "chars": 564,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"RunConfigurationProducerService\">\n    <o"
  },
  {
    "path": ".idea/vcs.xml",
    "chars": 180,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project version=\"4\">\n  <component name=\"VcsDirectoryMappings\">\n    <mapping dire"
  },
  {
    "path": "README.md",
    "chars": 3184,
    "preview": "# PasscodeView\n[![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://www.apache.org/licenses/LI"
  },
  {
    "path": "app/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "chars": 640,
    "preview": "apply plugin: 'com.android.application'\n\nandroid {\n    compileSdkVersion 25\n    buildToolsVersion \"25.0.3\"\n\n    defaultC"
  },
  {
    "path": "app/proguard-rules.pro",
    "chars": 683,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /V"
  },
  {
    "path": "app/src/androidTest/java/com/mhk/android/passcodeviewsample/ApplicationTest.java",
    "chars": 365,
    "preview": "package com.mhk.android.passcodeviewsample;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "chars": 644,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "app/src/main/java/com/mhk/android/passcodeviewsample/SampleActivity.java",
    "chars": 1120,
    "preview": "package com.mhk.android.passcodeviewsample;\n\nimport android.os.Bundle;\nimport android.support.v7.app.AppCompatActivity;\n"
  },
  {
    "path": "app/src/main/res/layout/sample_activity.xml",
    "chars": 837,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmln"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "chars": 211,
    "preview": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "chars": 82,
    "preview": "<resources>\n    <string name=\"app_name\">PasscodeView Sample</string>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "chars": 457,
    "preview": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.DarkActionBar"
  },
  {
    "path": "build.gradle",
    "chars": 645,
    "preview": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    r"
  },
  {
    "path": "passcodeview/.gitignore",
    "chars": 7,
    "preview": "/build\n"
  },
  {
    "path": "passcodeview/build.gradle",
    "chars": 3312,
    "preview": "apply plugin: 'com.android.library'\napply plugin: 'com.github.dcendents.android-maven'\napply plugin: \"com.jfrog.bintray\""
  },
  {
    "path": "passcodeview/proguard-rules.pro",
    "chars": 683,
    "preview": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /V"
  },
  {
    "path": "passcodeview/src/androidTest/java/online/devliving/passcodeview/ApplicationTest.java",
    "chars": 360,
    "preview": "package online.devliving.passcodeview;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n *"
  },
  {
    "path": "passcodeview/src/main/AndroidManifest.xml",
    "chars": 194,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"online.devliving.passcodeview\">\n\n    <"
  },
  {
    "path": "passcodeview/src/main/java/online/devliving/passcodeview/PasscodeView.java",
    "chars": 16072,
    "preview": "package online.devliving.passcodeview;\n\nimport android.content.Context;\nimport android.content.res.Resources;\nimport and"
  },
  {
    "path": "passcodeview/src/main/res/values/attrs.xml",
    "chars": 573,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <declare-styleable name=\"PasscodeView\">\n        <attr name=\"numDi"
  },
  {
    "path": "settings.gradle",
    "chars": 32,
    "preview": "include ':app', ':passcodeview'\n"
  }
]

About this extraction

This page contains the full source code of the iamMehedi/PasscodeView GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 27 files (34.7 KB), approximately 9.0k tokens, and a symbol index with 42 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!