Thursday, May 18, 2017

Android RecycleView with OnClickListener

May 18, 2017

Android RecyclerView is more than flexible more than android  ListView. It is a container for rendering larger data set of views that can be recycled and scrolled very efficiently. RecyclerView is like traditional ListView, but with more flexibility to customizes and optimized to work with larger datasets.
Example of Android RecyclerView
recyclerView list main
recyclerView list
First, add the following android support library dependency to project build.graddle file.
dependencies {
    compile 'com.android.support:recyclerview-v7:25.0.1'
    compile 'com.android.support:cardview-v7:25.0.1'
} 

First, dependency for RecyclerView and Second is for CardView. We use cardView in Recyclerview row item layout file. now use below code to your layout file
<android.support.v7.widget.RecyclerView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:id="@+id/main_recyView"/>

Now go to your java class file and use below code.

RecyclerView recyclerView = (RecyclerView) findViewById(R.id.main_recyView);

LinearLayoutManager linearLayoutManager = new 
LinearLayoutManager(this,LinearLayoutManager.VERTICAL,false);

//setting layout manager
recyclerView.setLayoutManager(linearLayoutManager);
recyclerView.setNestedScrollingEnabled(false);

Here I use LinearLayoutManager and vertically scroll options. you can use another layout manager. Now create an Adapter of android RecyclerView. we also need ViewHolder Class. you can create this ViewHolder class in a separate class or in the child class of Adapter class. I create ViewHolder class in the Adapter class. in adapter class, we need two variables
  1. ArrayList
  2. Context
we also need android Recyclerview row item layout file. code is
<android.support.v7.widget.CardView
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:elevation="10dp"
        android:padding="10dp">

        <TextView
            android:id="@+id/main_card_tv"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:padding="10dp"
            android:text="@string/app_name"
            android:textSize="20sp"/>

    </android.support.v7.widget.CardView>
we also need Item type class. My class name is SubjectList.java you can change your choice. SubjectList.java code is
public class SubjectList {

        private String subName;

        public SubjectList(String subName) {
            this.subName = subName;
        }

        public String getSubName() {
            return subName;
        }
    }

Now adapter class
public class MainAdapter extends    RecyclerView.Adapter<MainAdapter.MainViewHolder> {


        //Array list
        private ArrayList<SubjectList> objects;
        //context
        private Context context;

        //view holder class
        class MainViewHolder extends RecyclerView.ViewHolder {

            TextView textView;

            private MainViewHolder(View itemView) {
                super(itemView);
                textView = (TextView) itemView.findViewById(R.id.main_card_tv);
            }
        }

        //constructor
        public MainAdapter(ArrayList<SubjectList> objects, Context context) {
            this.objects = objects;
            this.context = context;
        }

        @Override
        public MainViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

            View view = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.main_card_view,parent,false);
            return new MainViewHolder(view);
        }

    @Override
    public void onBindViewHolder(final MainViewHolder holder, int position) {

        final SubjectList list = objects.get(position);

        holder.textView.setText(list.getSubName());

        holder.textView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                context.startActivity(new Intent(context, LocationActivity.class));
                
            }
        });
    }

    @Override
    public int getItemCount() {
        return objects.size();
    }

}

RecyclerView OnclickListener

we add a listener in onBindViewHolder method. the code here-
@Override
        public void onBindViewHolder(final MainViewHolder holder, int position) {

            final SubjectList list = objects.get(position);
            
            holder.textView.setText(list.getSubName());

            holder.textView.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    context.startActivity(new Intent(context, LocationActivity.class));
                
            }
        });
            holder.textView.setOnLongClickListener(new View.OnLongClickListener() {
                @Override
                public boolean onLongClick(View v) {
                    return false;
            }
        });
    }
Note: If you have multiple views in Recyclerview row item layout file you can use Card view to setOnClickListener instead of Textview.

Code analysis

ViewHolder Class-
  • we make ViewHolder class extend of RecyclerView.ViewHolder
  • we have on TextView and we cast it.
that’s all of ViewHolder Class. Adapter class-
  • we initialize our two variables through constructor
  • in onCreateViewHolder methods we create a new view type that inflates a layout file through LayoutInflater and returns new ViewHolder class with a parameter with that’s view.
  • we create new SubjectList and initialize it through the position of the ArrayList item.
  • add set Text to View by getting getter method of SubjectList.
  • now setOnClickListener to the view
  • in final we just return the size of ArrayList in getItemCount() method.

Please check next Part. Next Part cover MainActivity code Revise of all code and final screenshot. Click here.

Read More

Android Floating Action Button with animation part-2

May 18, 2017

Welcome to the part two of our today's android project.
In the previous part, we create animation XML and drawable. Now we add fab code in the layout. (if you miss part one click here)

In my case my layout is activity_main.xml before doing this we need two colors in colors.xml.
Let's add this
<color name="fab1">#e2e21d</color>
<color name="fab2">#47e92e</color>
Now add three fab button. I share this code one by one.
<android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="150dp"
        android:layout_marginEnd="16dp"
        android:layout_gravity="bottom|end"
        android:elevation="6dp"
        android:src="@drawable/ic_person_outline_black_24dp"
        app:fabSize="normal"
        android:visibility="gone"
        android:id="@+id/fab_people"
        app:backgroundTint="@color/fab2"
        app:pressedTranslationZ="12dp"/>
next one
<android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="80dp"
        android:layout_marginEnd="16dp"
        android:layout_gravity="bottom|end"
        android:elevation="6dp"
        android:src="@drawable/ic_school_black_24dp"
        app:fabSize="normal"
        android:visibility="gone"
        android:id="@+id/fab_school"
        app:backgroundTint="@color/fab1"
        app:pressedTranslationZ="12dp"/>
and the last one
<android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="@dimen/fab_margin"
        android:layout_gravity="bottom|end"
        android:elevation="6dp"
        android:src="@drawable/ic_share_black_24dp"
        app:fabSize="normal"
        android:id="@+id/main_fab"
        app:pressedTranslationZ="12dp"/>

Note: if you have any dought you can check full activity.xml code on GitHub.

Now time for java code.
In my case java file is MainActivty.java Add those variables-
FloatingActionButton main,people,school;
Animation fabOpen,fabClose,fabRotate,fabRotateAntiClockWise;

//fab is open or close
boolean isOpen = false;
Now assign all fab button with findViewById()
main = (FloatingActionButton) findViewById(R.id.main_fab);
people = (FloatingActionButton) findViewById(R.id.fab_people);
school = (FloatingActionButton) findViewById(R.id.fab_school);
Now time for load animation-
fabOpen = AnimationUtils.loadAnimation(this,R.anim.fab_open);
fabClose = AnimationUtils.loadAnimation(this,R.anim.fab_close);
fabRotate = AnimationUtils.loadAnimation(this,R.anim.rotate_clockwise);
fabRotateAntiClockWise = AnimationUtils.loadAnimation(this,R.anim.rotate_anit_clockwise);

If the user clicks the main fab button then we will show others button. That's is the logic. ok add main fab clickListener and use below code to show others button. After the code, I discuss code logic again Ok enough talking. Let's start-

main.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Log.e("Click", "click");

                if (isOpen){
                    people.setAnimation(fabClose);
                    school.setAnimation(fabClose);
                    main.setAnimation(fabRotateAntiClockWise);
                    people.setClickable(false);
                    school.setClickable(false);
                    people.setVisibility(View.GONE);
                    school.setVisibility(View.GONE);
                    isOpen = false;

                } else {
                    people.setVisibility(View.VISIBLE);
                    school.setVisibility(View.VISIBLE);
                    people.setAnimation(fabOpen);
                    school.setAnimation(fabOpen);
                    main.setAnimation(fabRotate);
                    people.setClickable(true);
                    school.setClickable(true);
                    people.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(MainActivity.this, "Welcome to people", 
                                      Toast.LENGTH_SHORT).show();
                        }
                    });

                    school.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            Toast.makeText(MainActivity.this, "Welcome to school", 
                                                      Toast.LENGTH_SHORT).show();
                        }
                    });

                    isOpen = true;
                }
            }
        });

Note: youcan recheck MainActivity.java on GitHub 

Code analysis-
1.In layout file when we created out floating action button we set those button's visibility gone excepts main fab button. we check boolean state first, isopen is true or false

2. If the answer is true that means fab is open now. So we set here close fab functionality.
2.1. set close animation on two fabs that are you want's to close.
2.2. set those fab clickable false.
2.3 set anti clock rotate animation on mainFab.
2.4 now time to invisible that's fab.
2.5 at last assign isopen to false.

3.If the answer is false that means fab is close. So we set here close fab functionality.
3.1. now time to invisible others fab.
3.1. set open animation on two fabs that are not shown.
3.2. set those fab clickable true.
3.3 set clock rotate animation on mainFab.
3.4 set click listener on those fab
3.5 at last assign isopen to true.

Wow. now we fab three fabs in our layout but only one is showing at first. After clicking main fab other's button is open with animation. And those button is now working. And again click the main fab button, others two buttons is gone. So welcome to you all. you successfully created this project.

you can find the full project on Github. Fab

Thanks for reading this post and hope this code is working and now you can use fab with animation on your own project.

Happy coding.

Read More

Android Floating Action Button with animation

May 18, 2017

In this android project, we create 3 floating action button. The main fab button is only showing when activity is launch. other's two are invisible. After clicking the main fab button it will show the other's fab button. Those buttons are now visible and clickable. after clicking again main fab button is rotate 45 degrees and close others fab button with animation. That's our main goal today.

Let's start to making our today's android app
First, add those dependencies to your build.gradle file
dependencies {
   
    compile 'com.android.support:appcompat-v7:25.2.0'
    compile 'com.android.support:design:25.2.0'
    
}

Now we create 4 animations XML file in res > anim folder.

1.fab_open.XML
2.fab_close.xml
3. rotate_clockwise.XML
4.rotate_anti_clockwise.xml

first two are using on closing and opening fab and last 2 are using to rotate the main fab.

Let's create those file in res > anim folder

Note: we should follow code comment. That will help us to understand code easily.

1.fab_open.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">
    <!-- android:fillAfter="true" is ensure thata animation transformation occur
     only after finish animation -->

    <!-- we change animation from 0 to 80 percent -->
    <!-- pivot x or y means it's is the center point of animation -->
    <scale
        android:fromXScale="0.0"
        android:fromYScale="0.0"
        android:toXScale=".8"
        android:toYScale=".8"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration = "300"
        android:interpolator = "@android:anim/linear_interpolator"/>

    <!-- now change the animation of the opacity of the object -->
    <!-- now we change alpha 0 to 1 that's means object's disappears -->
    <!-- accelerate_interpolator means that's animation start's slowly -->
    <alpha
        android:fromAlpha="0"
        android:toAlpha="1"
        android:duration = "300"
        android:interpolator = "@android:anim/accelerate_interpolator"/>


</set>
2.fab_close.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">
    <!-- android:fillAfter="true" is ensure thata animation transformation occur
     only after finish animation -->

    <!-- same as fab_open.xml but inverse order -->
    
    <!-- we change animation from 80 to 0 percent -->
    <!-- pivot x or y means it's is the center point of animation -->
    <scale
        android:fromXScale=".8"
        android:fromYScale=".8"
        android:toXScale="0.0"
        android:toYScale="0.0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration = "300"
        android:interpolator = "@android:anim/linear_interpolator"/>

    <!-- now change the animation of the opacity of the object -->
    <!-- now we change alpha 1 to 0 that's means object's disappears -->
    <!-- accelerate_interpolator means that's animation start's slowly -->
    <alpha
        android:fromAlpha="1"
        android:toAlpha="0"
        android:duration = "300"
        android:interpolator = "@android:anim/accelerate_interpolator"/>

</set>
3.rotate_clockwise.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:fillAfter="true">

    <!-- it rotate to 0 to 45 degree -->

    <rotate
        android:fromDegrees="0"
        android:toDegrees="45"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration = "300"
        android:interpolator = "@android:anim/linear_interpolator"/>


</set>
34 rotate_anti_clockwise.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
     android:fillAfter="true">

    <!-- same as clockwise.xml but inverse order -->
    <!-- in this animation we rotate start 45 to 0  -->
    <rotate
        android:fromDegrees="45"
        android:toDegrees="0"
        android:pivotX="50%"
        android:pivotY="50%"
        android:duration = "300"
        android:interpolator = "@android:anim/linear_interpolator"/>
</set>

Now add some drawable to on our android project. I am currently use vector drawable here. I also share my code here. Note you can use image or others vector drawable as you.(it also reduces android app size)

1.ic_person_outline_black_24dp.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FF000000"
        android:pathData="M12,5.9c1.16,0 2.1,0.94 2.1,
        2.1s-0.94,2.1 -2.1,2.1S9.9,9.16 9.9,8s0.94,-2.1 2.1,
        -2.1m0,9c2.97,0 6.1,1.46 6.1,2.1v1.1L5.9,18.1L5.9,
        17c0,-0.64 3.13,-2.1 6.1,-2.1M12,4C9.79,4 8,5.79 8,
        8s1.79,4 4,4 4,-1.79 4,-4 -1.79,-4 -4,-4zM12,13c-2.67,
        0 -8,1.34 -8,4v3h16v-3c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

2.ic_school_black_24dp.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FF000000"
        android:pathData="M5,13.18v4L12,21l7,-3.82v-4L12,17l-7,-3.82zM12,3L1,9l11,6 9,-4.91V17h2V9L12,3z"/>
</vector>

3.ic_share_black_24dp.xml
<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="24.0"
        android:viewportHeight="24.0">
    <path
        android:fillColor="#FF000000"
        android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,
        0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,
        -0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,
        0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,
        3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,
        9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,
        -0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,
        2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,
        -2.92 -2.92,-2.92z"/>
</vector>


Ok, that's looking great.
we have done a lot. In the next part, we have created layout and java code. Click here for next part.

Read More

Monday, May 15, 2017

Android Material Date picker Dialog

May 15, 2017

Welcome to this post.

In this post, we are going to create a material date picker.

Date picker Dialog helps you to pick the date for your application.
If you have an option for user pick their date then you can use it. This popup in your layout. SO it's won't take place on your layout. In this post, we learn about how we can use Date picker Dialog and pick our date.

Ok, let's started.
First, you need to create a class name here DatePickerFragment and extend to DialogFragment and implement DatePickerDialog.OnDateSetListener

Let me show-
public class DatePickerFragment extends DialogFragment implements
  DatePickerDialog.OnDateSetListener {

}

now override two methods named onCreateDialog and onDateSet. in onCreateDialog, we add a calendar and get current date from our calendar and return those values-

@Override
  public Dialog onCreateDialog(Bundle savedInstanceState) {

  Calendar c = Calendar.getInstance();

  int startYear = c.get(Calendar.YEAR);
  startMonth = c.get(Calendar.MONTH);
  int startDay = c.get(Calendar.DAY_OF_MONTH);

  return new DatePickerDialog(getActivity(),this,startYear,startMonth,startDay);
  }

Note: in this methods, you can set you desire date if you want to show to your user. For this, you can first set date on the calendar the before getting data.

A quick look-
SimpleDateFormat format = new SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH);
  try {
  String dateStr = "1/5/2017";
  Date date = format.parse(dateStr);
  c.setTime(date);
  } catch (ParseException e) {
  e.printStackTrace();
  }

Note: here I formatted a string into date and set it to the calendar. But you can add directly like this way-

Calendar calendar =Calendar.getInstance();
        
calendar.set(Calendar.YEAR, 2017);
calendar.set(Calendar.MONTH, 2);
calendar.set(Calendar.DAY_OF_MONTH, 17);

when user set the date then onDateSet will be executed. the code is your wish. you get all in an integer. here I save it on shared preference.

@Override
  public void onDateSet(DatePicker view, int year, int month, int dayOfMonth) {

  String dateStr = dayOfMonth+"/"+month+"/"+year;
  SharedPreferences preferences = getActivity().getSharedPreferences("TimeDate", Context.MODE_PRIVATE);
  
  SharedPreferences.Editor editor = preferences.edit();
  editor.putString("Date",dateStr);
  editor.apply();

  }

Ok. we created our DatepickerDialog.java class. Now we use it on on button listener.

dateTvLabel.setOnClickListener(new View.OnClickListener() {
  @Override
  public void onClick(View v) {
  DatePickerFragment datePickerFragment = new DatePickerFragment();
  datePickerFragment.show(getFragmentManager(), "Date Picker");
  }
  });

and That's it. Now you can use this Date Picker Dialog and customize your project.

datePicker


 Happy coding.

Read More

Android Material Time Picker Dialog

May 15, 2017

Time picker Dialog helps you to pick the time for your application. If you have an option for user pick their time then you can use it. This popup in your layout. SO it's won't take place on your layout. In this post, we learn about how we can use time picker Dialog and pick our time. First, you need to create a class name here TimePickerFragment and extend to DialogFragment and implement TimePickerDialog.OnTimeSetListener ok, Let's start -

public class TimePickerFragment extends DialogFragment implements
  TimePickerDialog.OnTimeSetListener {

}

now override two methods named onCreateDialog and onTimeSet. in onCreateDialog, we add a calendar and get the current time from our calendar and return those values-

@Override
  public Dialog onCreateDialog(Bundle savedInstanceState) {

  //Use the current time as the default values for the time picker
  final Calendar c = Calendar.getInstance();

  int hour = c.get(Calendar.HOUR_OF_DAY);
  int minute = c.get(Calendar.MINUTE);

  //Create and return a new instance of TimePickerDialog
  return new TimePickerDialog(getActivity(), this, hour, minute,
  DateFormat.is24HourFormat(getActivity()));
  }

Note if you want to set a specific time then set on it calendar first and get date same as we do on DatePickerDiolog Ok, let's show again-

SimpleDateFormat format = new SimpleDateFormat("hh:mm a", Locale.ENGLISH);

String timeStr = "10:12 PM"

try {
Date time = format.parse(timeStr);
c.setTime(time);
} catch (ParseException e) {
e.printStackTrace();
}

Note: here I formatted a string into date and set it to the calendar. But you can add directly like this way-

Calendar calendar =Calendar.getInstance();
  
calendar.set(Calendar.HOUR_OF_DAY, 22);
calendar.set(Calendar.MINUTE, 22);

when user set the date then onDateSet will be executed. code is your wish. you get all in an integer. here I save it on shared preference.

@Override
  public void onTimeSet(TimePicker view, int hourOfDay, int minute) {
  String time=hourOfDay+":"+minute;
  SharedPreferences preferences = getActivity().getSharedPreferences("TimeDate", 
                                           Context.MODE_PRIVATE);
  SharedPreferences.Editor editor = preferences.edit();
  editor.putString("Time",time);
  editor.apply();
  }

That's it. we finished up TimePiclerDialog Class. But one this if you want to 12 our clock that's show AM or PM. Then you should modify this code. Because here hourOfDay is shown 24 hours format. Ok now modify the code. If our hourOfDay is greater than 11 then it's must be PM. so we add pm on the string. and subtract from 12 then we get again 12 hours format. Let's move on code-

//Get the AM or PM for current time
        String aMpM = "AM";
        if (hourOfDay > 11) {
            aMpM = "PM";
        }

        //Make the 24 hour time format to 12 hour time format
        int currentHour;
        if (hourOfDay > 11) {
            currentHour = hourOfDay - 12;
        } else {
            currentHour = hourOfDay;
        }

        String time = String.valueOf(currentHour)
                + ":" + String.valueOf(minute) + " " + aMpM;

Not enough for understanding then full methods-

@Override
    public void onTimeSet(TimePicker view, int hourOfDay, int minute) {

        //Get the AM or PM for current time
        String aMpM = "AM";
        if (hourOfDay > 11) {
            aMpM = "PM";
        }

        //Make the 24 hour time format to 12 hour time format
        int currentHour;
        if (hourOfDay > 11) {
            currentHour = hourOfDay - 12;
        } else {
            currentHour = hourOfDay;
        }

        String time = String.valueOf(currentHour)
                + ":" + String.valueOf(minute) + " " + aMpM;

        Log.e("TIME is set", time);
        SharedPreferences preferences = getActivity().getSharedPreferences("TimeDate", 
                                                 Context.MODE_PRIVATE);
        SharedPreferences.Editor editor = preferences.edit();
        editor.putString("Time",time);
        editor.apply();
    }

Ok, that's great. Now we use it on on button listener or Click listener on any view.

//set time
        timeTvLabel.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                TimePickerFragment pickerDialog = new TimePickerFragment();
          
                pickerDialog.show(getFragmentManager(), "Time Pick");
            }
        });

That's it. We finish our today coding. Hope it's working.

time picker


 Happy coding.

Read More

Android App Settings with Preference Fragment Compat

May 15, 2017

In this post, we will make Android app settings with new Style.
We use PreferenceFragmentCompat.

Why Preference fragment compact? 
Because by using this we can show toolbar on settings activity easily.
Before starting to take a look at documentation click here.

So we need a separate fragment class. Settings is an activity just like others but we implement fragment here.
 Ok, that's our today goal.
Let's start.
Create an Activity name Settings Activity -

public class SettingsActivity extends AppCompatActivity {

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

  if (getSupportActionBar() != null) {
  getSupportActionBar().setDisplayHomeAsUpEnabled(true);
     }

  }

Now set it on Manifest.XML

<activity
  android:name=".settings.SettingActivity"
  android:label="@string/action_settings" />

Note: don't set-


android:parentActivityName=".MainActivity"

if you set this, after pressing the back arrow button on the toolbar it's launch MainActivity again. Now add dependencies to your build.gradle file

compile 'com.android.support:preference-v7:25.3.1'

After that Create a Fragment Class Name SettingFragment.java and extend it to PreferenceFragmentCompat and implements. SharedPreferences.OnSharedPreferenceChangeListener Let me Show-

public class SettingsFragment extends PreferenceFragmentCompat implements
  SharedPreferences.OnSharedPreferenceChangeListener{

  @Override
  public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
  
  }

  @Override
  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

  }

Now add a method on this class name setPreferenceSummery. If we use ListPreference then we set to list selected value. for doing this, add this code-

private void setPreferenceSummery(Preference preference,Object value){

  String stringValue = value.toString();

  if (preference instanceof ListPreference){
  // For list preferences, look up the correct display value in
  // the preference's 'entries' list (since they have separate labels/values).
  ListPreference listPreference = (ListPreference) preference;
  int prefIndex = listPreference.findIndexOfValue(stringValue);
  //same code in one line
  //int prefIndex = ((ListPreference) preference).findIndexOfValue(value);

  //prefIndex must be is equal or garter than zero because
  //array count as 0 to ....
  if (prefIndex >= 0){
  listPreference.setSummary(listPreference.getEntries()[prefIndex]);
  }
  } else {
  // For other preferences, set the summary to the value's simple string representation.
  preference.setSummary(stringValue);
     }
 }

Note: For understanding code, you see comment on the code.

Now time the fulfill the methods onCreatePreferences.
In this methods, we add our XML file for settings option. But we don't create yet. So it's show error status. But don't worry we will add this later. Code-

@Override
  public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
  // Add 'general' preferences, defined in the XML file
  addPreferencesFromResource(R.xml.pref_general);

  SharedPreferences sharedPreferences = getPreferenceScreen().getSharedPreferences();

  PreferenceScreen preferenceScreen = getPreferenceScreen();

  int count = preferenceScreen.getPreferenceCount();

  for (int i = 0; i < count ; i++) {
  Preference p = preferenceScreen.getPreference(i);
  if (!(p instanceof CheckBoxPreference)) {
  String value = sharedPreferences.getString(p.getKey(), "");
  setPreferenceSummery(p, value);
       }
     }
  }

Now time to work with onSharedPreferenceChanged-

@Override
  public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {

  Preference preference = findPreference(key);

  if (preference != null) {

  if (!(preference instanceof CheckBoxPreference)) {
  String value = sharedPreferences.getString(preference.getKey(), "");
  setPreferenceSummery(preference, value);
        }
     }
  }


Optional code: 
if you want to use the content provider to access database then you set a notification for change value-
Activity activity = getActivity();
activity.getContentResolver().notifyChange(CONTENT_URI, null);
After doing that we should register and unregister the shared preference listener with activity life cycle.

Let's do this-
//register and unregister on lifecycle
  @Override
  public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  getPreferenceScreen().getSharedPreferences()
  .registerOnSharedPreferenceChangeListener(this);
  }

  @Override
  public void onDestroy() {
  super.onDestroy();
  getPreferenceScreen().getSharedPreferences()
  .unregisterOnSharedPreferenceChangeListener(this);
  }


ok. our fragment is ready to use.(don't worry about the error, we will fix this letter, for now just ignore it.)
Now we add the toolbar back arrow code.
so that it's come back the previous activity. For more details use code comment-

@Override
    public boolean onOptionsItemSelected(MenuItem item) {

        /*
         * Normally, calling setDisplayHomeAsUpEnabled(true) 
         * (we do so in onCreate here) as well as
         * declaring the parent activity in the 
         * AndroidManifest is all that is required to get the
         * up button working properly. However, in this case, 
         * we want to navigate to the previous
         * screen the user came from when the up 
         * button was clicked, rather than a single
         * designated Activity in the Manifest.
         *
         * We use the up button's ID (android.R.id.home) 
         * to listen for when the up button is
         * clicked and then call onBackPressed 
         * to navigate to the previous Activity when this happens.
         */

        int id = item.getItemId();

        if (id == android.R.id.home){
            NavUtils.navigateUpFromSameTask(this);
        }

        return super.onOptionsItemSelected(item);
    }

Now in this part, we create XML code.

Are you tired of seeing the error? 
Now time to fix it. we create an XML file name pref_general.xml.
Let's add-
In our settings screen, we just add two preference,

  • List Preference,
  •  Checkbox preference. 

our list preference for text size. so we need to create two arrays on arrays.XML one is for label and others is for value. but we need to add string first (I provide all string for both preferences).

Strings-
<!-- for settings -->
  <!-- ***************START************* -->
  <!-- text size -->
  <string name="sTextSmallLabel">Small</string>
  <string name="sTextMediumLabel">Medium</string>
  <string name="sTextModerateLabel">Moderate</string>
  <string name="sTextLargeLabel">Large</string>
  <string name="sTextExtraLargeLabel">Extra Large</string>

  <!-- text size value-->
  <string name="sTextSmallValue">15</string>
  <string name="sTextMediumValue">17</string>
  <string name="sTextModerateValue">20</string>
  <string name="sTextLargeValue">23</string>
  <string name="sTextExtraLargeValue">26</string>

  <string name="textSizeKey" translatable="false">textSize</string>
  <string name="textSizeLabel">Text Size</string>

  <string name="switchKey">SwitchKey</string>
  <string name="switchLabel">Night Mode</string>
  <string name="switchON">Night Mode ON</string>
  <string name="switchOFF">Night Mode OFF</string>

  <!-- ***************FINISH************* -->

Now add arrays-

<resources>

  <string-array name="textSizeLabel">
  <item>@string/sTextSmallLabel</item>
  <item>@string/sTextMediumLabel</item>
  <item>@string/sTextModerateLabel</item>
  <item>@string/sTextLargeLabel</item>
  <item>@string/sTextExtraLargeLabel</item>
  </string-array>

  <string-array name="textSizeValue">
  <item>@string/sTextSmallValue</item>
  <item>@string/sTextMediumValue</item>
  <item>@string/sTextModerateValue</item>
  <item>@string/sTextLargeValue</item>
  <item>@string/sTextExtraLargeValue</item>
  </string-array>


</resources>

Note my full arrays.xml. Ok, that's enough waiting now add pref_general.xml


<PreferenceScreen
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="match_parent">

  <ListPreference
  android:defaultValue="@string/sTextModerateValue"
  android:entries="@array/textSizeLabel"
  android:entryValues="@array/textSizeValue"
  android:key="@string/textSizeKey"
  android:title="@string/textSizeLabel"/>

  <CheckBoxPreference
  android:defaultValue="false"
  android:key="@string/switchKey"
  android:summaryOff="@string/switchOFF"
  android:summaryOn="@string/switchON"
  android:title="@string/switchLabel"/>

</PreferenceScreen>

Just one more work to do left to complete Settings-
we need to update activity_settings. we need to set a fragment to on this XML file. Let's add this and this fragment will show our new settings in the settings.

<fragment
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/weather_settings_fragment"
    android:name="packageName.settings.SettingFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

Ok, that's . we finish our settings.

oh! I just forget to change the theme of styles.XML. Let's add on your main app theme.

<!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
  <!-- must add this line or app will crash -->
  <item name="preferenceTheme">@style/PreferenceThemeOverlay</item>
  </style>

Note: if you don't add this line your app will crash. Be careful. Now you launch this SettingsActivity.java class with intent from your desired class.

See-
settings

It is single preference screen app. But If you want to add multiple screens, follow this post- Android Settings Series

That's all today.
Hope you can use this option for your app.

Happy coding

Read More