http://www.devexchanges.info/2017/02/create-lock-screen-inside-android.html
Like some application which focuses on the protection of user data, if we would like to access content, we must enter password first. This lock screen always show every time we open the app, ensure that strangers cannot access your data. Maybe in some cases to protect user information, developer can use this way.
In this post, I will make a lock activity by designing in XML. There is an another solution is using a third-party library, please read my previous post.
User must input number-password to pass this lock screen, so design a keypad for this activity like this:
Now, you must have a main activity, it's will start when launching app. It's layout depend on your work, in this simple project, it only include a
Because the lock screen always display when app launching, so in
In this activity, we must:
As you see at the output video, when user type a wrong code, the dots layout will be shake. This is xml file to make this animation:
You can make other better animation than this by research more about animation in Android!
In this project, I use ButterKnife to make
Make a lock screen inside your own application is a not hard work, you can design it better and should pay attention to developing animation and further, vibrating device when user type a wrong code! The fact that there are many third-party libraries which can help you make this layout without write XML codes yourself. Please read my previous post to learn about using one of them. Finally, you can get full project code on Github.
Like some application which focuses on the protection of user data, if we would like to access content, we must enter password first. This lock screen always show every time we open the app, ensure that strangers cannot access your data. Maybe in some cases to protect user information, developer can use this way.
In this post, I will make a lock activity by designing in XML. There is an another solution is using a third-party library, please read my previous post.
Designing layout for lock activity
activity_lock.xml
Expected output: <?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_horizontal_margin"
tools:context="info.devexchanges.lockscreen.LockActivity">
<LinearLayout
android:id="@+id/lock_keypad"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn1"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="1" />
<Button
android:id="@+id/btn2"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="2" />
<Button
android:id="@+id/btn3"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="3" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn4"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="4" />
<Button
android:id="@+id/btn5"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="5" />
<Button
android:id="@+id/btn6"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="6" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn7"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="7" />
<Button
android:id="@+id/btn8"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="8" />
<Button
android:id="@+id/btn9"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="9" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_space"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false" />
<Button
android:id="@+id/btn0"
style="@style/Borderless_Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="0" />
<ImageView
android:id="@+id/btn_clear"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:contentDescription="@null"
android:src="@android:drawable/ic_input_delete"
android:tint="@color/colorPrimary" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/dot_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_above="@id/lock_keypad"
android:layout_marginBottom="@dimen/activity_horizontal_margin"
android:gravity="center"
android:orientation="horizontal">
<ImageView
android:id="@+id/dot_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/dot_disable" />
<ImageView
android:id="@+id/dot_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/dot_disable" />
<ImageView
android:id="@+id/dot_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/dot_disable" />
<ImageView
android:id="@+id/dot_4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:contentDescription="@null"
android:src="@drawable/dot_disable" />
</LinearLayout>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@id/dot_layout"
android:layout_centerInParent="true"
android:layout_marginBottom="@dimen/activity_horizontal_margin"
android:src="@drawable/lock" />
</RelativeLayout>
Now, you must have a main activity, it's will start when launching app. It's layout depend on your work, in this simple project, it only include a
TextView
:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="info.devexchanges.lockscreen.MainActivity">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<TextView
android:id="@+id/text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="@dimen/activity_horizontal_margin"
android:text="Hello World!" />
</LinearLayout>
Main activity programmatically code
onStart()
of MainActivity
, we'll check if users haven't typed true before, starting LockActivity
immediately by Intent
! In order to detect users passed the lock screen or not, we'll use SharedPreferences
. Source code simple like this:
MainActivity.java
As you can see, we must remove password when the main activity closed (by override package info.devexchanges.lockscreen;
import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.widget.TextView;
import butterknife.BindView;
import butterknife.ButterKnife;
public class MainActivity extends AppCompatActivity {
@BindView(R.id.toolbar)
Toolbar toolbar;
@BindView(R.id.text)
TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ButterKnife.bind(this);
setSupportActionBar(toolbar);
}
@SuppressLint("SetTextI18n")
@Override
protected void onStart() {
super.onStart();
if (!isPass()) {
Intent intent = new Intent(this, LockActivity.class);
startActivity(intent);
} else {
textView.setText("The code you typed is right!");
}
}
private boolean isPass() {
SharedPreferences prefs = getSharedPreferences("PASS_CODE", MODE_PRIVATE);
return prefs.getBoolean("is_pass", false);
}
@Override
protected void onStop() {
super.onStop();
SharedPreferences.Editor editor = getSharedPreferences("PASS_CODE", MODE_PRIVATE).edit();
editor.putBoolean("is_pass", false);
editor.apply();
}
}
onStop()
to guaranteed that the lock activity always shown when app resumed! Lock activity programmatically code
- Handle click event of all buttons in the keypad (to get input code - password)
- Update dots layout when input code changed
- Check input code right or wrong. If right, return to the main activity and if wrong, show a
Toast
to warning.
LockActivity.java
This is output when app running: package info.devexchanges.lockscreen;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import java.util.List;
import butterknife.BindViews;
import butterknife.ButterKnife;
import butterknife.OnClick;
public class LockActivity extends AppCompatActivity {
@BindViews({R.id.btn0, R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5, R.id.btn6,
R.id.btn7, R.id.btn8, R.id.btn9, R.id.btn_clear})
List<View> btnNumPads;
@BindViews({R.id.dot_1, R.id.dot_2, R.id.dot_3, R.id.dot_4})
List<ImageView> dots;
private static final String TRUE_CODE = "2869";
private static final int MAX_LENGHT = 4;
private String codeString = "";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_lock);
ButterKnife.bind(this);
}
@OnClick(R.id.btn_clear)
public void onClear() {
if (codeString.length() > 0) {
//remove last character of code
codeString = removeLastChar(codeString);
//update dots layout
setDotImagesState();
}
}
@OnClick({R.id.btn0, R.id.btn1, R.id.btn2, R.id.btn3, R.id.btn4, R.id.btn5, R.id.btn6,
R.id.btn7, R.id.btn8, R.id.btn9})
public void onClick(Button button) {
getStringCode(button.getId());
if (codeString.length() == MAX_LENGHT) {
if (codeString.equals(TRUE_CODE)) {
Toast.makeText(this, "Code is right", Toast.LENGTH_SHORT).show();
setIsPass();
finish();
} else {
Toast.makeText(this, "Wrong Pass code", Toast.LENGTH_SHORT).show();
//vibrate the dots layout
shakeAnimation();
}
} else if (codeString.length() > MAX_LENGHT){
//reset the input code
codeString = "";
getStringCode(button.getId());
}
setDotImagesState();
}
private void shakeAnimation() {
Animation shake = AnimationUtils.loadAnimation(this, R.anim.vibrate_anim);
findViewById(R.id.dot_layout).startAnimation(shake);
Toast.makeText(this, "Wrong Password", Toast.LENGTH_SHORT).show();
}
private void getStringCode(int buttonId) {
switch (buttonId) {
case R.id.btn0:
codeString += "0";
break;
case R.id.btn1:
codeString += "1";
break;
case R.id.btn2:
codeString += "2";
break;
case R.id.btn3:
codeString += "3";
break;
case R.id.btn4:
codeString += "4";
break;
case R.id.btn5:
codeString += "5";
break;
case R.id.btn6:
codeString += "6";
break;
case R.id.btn7:
codeString += "7";
break;
case R.id.btn8:
codeString += "8";
break;
case R.id.btn9:
codeString += "9";
break;
default:
break;
}
}
private void setDotImagesState() {
for (int i = 0; i < codeString.length(); i++) {
dots.get(i).setImageResource(R.drawable.dot_enable);
}
if (codeString.length()<4) {
for (int j = codeString.length(); j<4; j++) {
dots.get(j).setImageResource(R.drawable.dot_disable);
}
}
}
private String removeLastChar(String s) {
if (s == null || s.length() == 0) {
return s;
}
return s.substring(0, s.length() - 1);
}
private void setIsPass() {
SharedPreferences.Editor editor = getSharedPreferences("PASS_CODE", MODE_PRIVATE).edit();
editor.putBoolean("is_pass", true);
editor.apply();
}
}
Shaking animation
res\anim\shake_anim.xml
And this is output:<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<rotate
android:duration="70"
android:fromDegrees="-5"
android:pivotX="50%"
android:pivotY="50%"
android:repeatCount="5"
android:repeatMode="reverse"
android:interpolator="@android:anim/linear_interpolator"
android:toDegrees="5" />
<translate
android:fromXDelta="-10"
android:toXDelta="10"
android:repeatCount="5"
android:repeatMode="reverse"
android:interpolator="@android:anim/linear_interpolator"
android:duration="70" />
</set>
You can make other better animation than this by research more about animation in Android!
In this project, I use ButterKnife to make
finViewbyId
work become easier! In order to use this library, please add this dependency to your app-level build.gradle: compile 'com.jakewharton:butterknife:8.5.1'
annotationProcessor 'com.jakewharton:butterknife-compiler:8.5.1'
Comments
Post a Comment