Android tip: Scratch View in Android

    Scratch card effect is popular in shopping applications. Moreover, it can be used for proving user are not a robot in some security requirements. In Android, there is no default widget in SDK which help us to build this layout easily, developer must build it yourself. Fortunately, by search on Internet, there are a lot of external libraries that making this type of view very well. Through this post, I would like to introduce one of them, called ScratchView. Maybe it's not very popular but still quite usable!

Import library

    Like description in the library Github page, in order to use it, please add this dependency to your app/build.gradle:
compile 'com.github.cooltechworks:ScratchView:v1.0'
    It's provide us two types of scratch view:
  • ScratchImageView: A subclass of ImageView which conceals the image. Scratching over the view will reveal the hidden image.
  • ScratchTextView: A subclass of TextView which conceals the text. Scratching over the view will reveal the hidden text.

Using ScratchTextView

    Use it like a normal TextView and specially, it has setRevealListener(IRevealListener), a callback listener interface which gets called back when user reveals the text/image through onReveal() method.
    Activity layout:
activity_text.xml
<?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:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".TextViewActivity">

    <com.cooltechworks.views.ScratchTextView
        android:id="@+id/text"
        android:padding="@dimen/activity_horizontal_margin"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:text="gghghjgjgj"
        android:textSize="15sp"
        android:textStyle="bold" />
</RelativeLayout>
    And it's simple programmatically code:
TextViewActivity.java

package info.devexchanges.scratchview;

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

import com.cooltechworks.views.ScratchTextView;

public class TextViewActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_text);
        ScratchTextView scratchTextView = (ScratchTextView)findViewById(R.id.text);

        assert scratchTextView != null;
        scratchTextView.setRevealListener(new ScratchTextView.IRevealListener() {
            @Override
            public void onRevealed(ScratchTextView tv) {
                Toast.makeText(TextViewActivity.this, "Revealed!", Toast.LENGTH_SHORT).show();
            }
        });
    }
}
    Running this application, we'll have this output:

ScratchImageView

    Absolutely with above, in this activity, I use a ScratchImageView to proving user is not a robot.
    The xml layout:
activity_image.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="@dimen/activity_horizontal_margin">

    <com.cooltechworks.views.ScratchImageView
        android:id="@+id/sample_image"
        android:layout_width="150dp"
        android:layout_height="150dp"
        android:background="@android:color/white"
        android:src="@drawable/nexus_6p" />

    <RadioGroup
        android:id="@+id/group"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <RadioButton
            android:id="@+id/ip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Iphone 6s" />

        <RadioButton
            android:id="@+id/nexus"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Nexus 6P" />

        <RadioButton
            android:id="@+id/pp"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Blackberry Passport" />

        <RadioButton
            android:id="@+id/lu"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Nokia Lumia 930" />
    </RadioGroup>

    <Button
        android:id="@+id/btn_confirm"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#F88A00"
        android:text="Confirm"
        android:textColor="@android:color/white" />

</LinearLayout>
    A simple code to confirm user action:
ScratchImageActivity.java
package info.devexchanges.scratchview;

import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.RadioGroup;
import android.widget.Toast;

import com.cooltechworks.views.ScratchImageView;

public class ScratchImageActivity extends AppCompatActivity {

    private ScratchImageView scratchImageView;
    private RadioGroup radioGroup;
    private Button btnConfirm;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_image);
        btnConfirm = (Button) findViewById(R.id.btn_confirm);
        radioGroup = (RadioGroup) findViewById(R.id.group);
        scratchImageView = (ScratchImageView) findViewById(R.id.sample_image);

        //You must have this listener
        scratchImageView.setRevealListener(new ScratchImageView.IRevealListener() {
            @Override
            public void onRevealed(ScratchImageView scratchImageView) {
                Log.i("Main", "onRevealed");
            }
        });

        btnConfirm.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!scratchImageView.isRevealed()) {
                    Toast.makeText(ScratchImageActivity.this, "You mus scratch image first", Toast.LENGTH_SHORT).show();
                } else if (radioGroup.getCheckedRadioButtonId() == R.id.nexus) {
                    Toast.makeText(ScratchImageActivity.this, "Confirmed!", Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(ScratchImageActivity.this, "Failed!", Toast.LENGTH_SHORT).show();
                }
            }
        });
    }
}
    This is output:

Other libraries?

    The most popular external libraries in creating scratch view may be WSScratchView (developed by winstan520), you can take a glance, it's better than the library which using in this post. But if you would like to make a simple view to quick resolved this problem, ScratchView is still useful and can deal with all your requirements.
    Thank for reading this tip and finally, you can view my full project on @Github.

Share


Previous post
« Prev Post
Next post
Next Post »