Sunday, December 24, 2017

Android Material SearchView with Recent Search Suggestions

December 24, 2017

Welcome to this post.

In this post, I am going to cover Android Search View with Recent Search Suggestion.

In a previous post, I already cover Android Material SearchView. In that post, I use a 3rd party library. If you want to use 3rd party library to add search functionality, see this post. Android Material SearchView

But Now I don't want to use any 3rd party library.
In this post, I use:
  • Search Widget
Let's start:
create a new activity:(In my case, I named it: SearchActivity)
First jump into XML code-

Read More

Monday, September 18, 2017

Android Splash Screen right way

September 18, 2017

Welcome to this post. In this post, I am going to discuss on Android Splash Screen.

splash Screen @androidSketchPad


In this whole post, I gonna cover those topics
1. How to create android Splash Screen
2. How to override default color when app launching (windows background)

When you click app icon, the app takes some time to start. To overcome this option android by default show a color until the activity is launched. By default, it is white in color. So later in this post, I will show you how to overcome this situation and how to change this default color.

Let's start-

Create an Activity named it as your choice

creating an activity android SketchPad


now design your layout file. I just provide my XML code.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout 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:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="com.blogspot.shudiptotrafder.soilscience.SplashActivity"
    tools:showIn="@layout/activity_splash"
    android:background="?attr/colorPrimary">

    <ImageView
        android:id="@+id/splash_imageView"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        app:srcCompat="@drawable/ic_lover"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginStart="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginEnd="8dp"
        android:contentDescription="app icon"
        app:layout_constraintTop_toTopOf="parent"
        android:layout_marginTop="80dp"
        tools:ignore="HardcodedText" />

    <TextView
        android:id="@+id/splash_app"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="App Name"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginStart="8dp"
        app:layout_constraintEnd_toEndOf="parent"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="16dp"
        android:textSize="30sp"
        app:layout_constraintTop_toBottomOf="@+id/splash_imageView" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toBottomOf="@+id/splash_app"
        app:layout_constraintStart_toStartOf="parent"
        android:layout_marginStart="8dp"
        android:layout_marginEnd="8dp"
        android:layout_marginTop="16dp"
        android:id="@+id/splash_appAbout"
        android:text="This is a complete app"
        android:textSize="16sp"
        app:layout_constraintEnd_toEndOf="parent" />

</android.support.constraint.ConstraintLayout>

and ic_lover.xml it as vector drawable, code here
<vector android:height="24dp"
    android:viewportHeight="512.0"
    android:viewportWidth="512.0"
    android:width="24dp"
    xmlns:android="http://schemas.android.com/apk/res/android">
    <path
        android:fillColor="#FF6464"
        android:pathData="M0,173.5C0,96 62.9,33.1 140.4,33.1c34.4,0 65.9,12.4 90.3,32.9c14.7,12.3 36,12.3 50.7,0c24.4,-20.5 55.9,-32.9 90.3,-32.9C449.1,33.1 512,96 512,173.5v-4.1c0,136.1 -165.6,258.9 -230.4,301.8c-15.5,10.3 -35.7,10.3 -51.2,0C165.6,428.3 0,305.5 0,169.4" />
    <path
        android:fillColor="#D2555A"
        android:pathData="M0,173.5c0,-0.6 0.1,-1.2 0.1,-1.8C0.1,171 0,170.2 0,169.4V173.5z" />
    <path
        android:fillColor="#D2555A"
        android:pathData="M114.8,182.7c-0,0.6 -0.1,1.3 -0.1,1.9v-4.5C114.8,181 114.8,181.9 114.8,182.7c0.5,-66.9 29.4,-123.3 69.2,-142.5c-13.7,-4.5 -28.4,-7.1 -43.6,-7.1c-76.9,0 -139.3,61.9 -140.3,138.6c1.9,135.2 165.9,256.8 230.3,299.4c6.6,4.4 14.1,6.8 21.6,7.4C198.9,418.8 116,306 114.8,182.7z" />
    <path
        android:fillColor="#FF8B8B"
        android:pathData="M449.5,153.9m-32,0a32,32 0,1 1,64.1 0a32,32 0,1 1,-64.1 0" />
    <path
        android:fillColor="#FFC1C1"
        android:pathData="M408.4,92.8m-20,0a20,20 0,1 1,40.1 0a20,20 0,1 1,-40.1 0" />
</vector>

We finished our design option, see the preview
splash screen android SketchPad

it contains an ImageView and two TextView

now time for java coding, SplashScreen.java
public class SplashScreen extends AppCompatActivity {

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

    }

now create an instance of Thread class and in the run methods call sleep methods and pass value 1000 (1000 for 1s, the value of Mille seconds). Don't forget to put this sleep method on try-catch block. and finally, block on try-catch, create an Intent that brings us to MainActivity. At list call finish() method and this activity will be destroyed.
See the code-
Thread checkForData = new Thread(){
      @Override
      public void run() {
            super.run();
            try{
            sleep(1000);

         } catch (Exception e) {
             e.printStackTrace();
         } finally {
             startActivity(new Intent(SplashActivity.this,
                            MainActivity.class));
             finish();
         }
     }
};
start this thread by calling start method
checkForData.start();
That's it. Splash Screen is created successfully. You can run a test for see result.

oh! Your app is not working. I forget one thing that we are using vector drawable. If your app minimum API is 21 then you have no headache. but if you targeting lower API you need to use support library to support vector drawable for lower API. To do that add below line in your build.gradle file
compile 'com.android.support:support-vector-drawable:25.3.1'
Note: change the version according to you compile SDK version. See mine-
compileSdkVersion 25
buildToolsVersion "25.0.3"
One more thing to go. add below code in your activity class
static {
    AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
}
ok, run the app again.

Screen Short:
Splash Screen @android SketchPad

Note: Don't be confused I use another app splash screen. Both are used the same code.

Now come on the last topics of this post, create a new theme on style.xml and add windows background color
<style name="splashTheme" parent="AppTheme.NoActionBar">
        <item name="android:windowBackground">@color/colorPrimary</item>
</style>
use this theme on the splash screen activity. Open manifest file and override below code-
<activity
       android:name=".SplashScreen"
       android:label="@string/app_name"
       android:theme="@style/splashTheme">
         <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
          </intent-filter>
</activity>
and my color code is
<color name="colorPrimary">#3F51B5</color>
rerun your app and see the change.

See Screen Short:
Splash Screen2 @android SketchPad


A Bonus for you
I also show you how to animate this splash screen. This is the pretty basic animation example.
Let's do this
create an XML file on res -> anim folder.
splash_screen_animation.xml
<alpha
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:fromAlpha="0"
    android:toAlpha="1"
    android:duration = "1000" />
Now load this animation, see code-
Animation set = AnimationUtils.loadAnimation(this,
                R.anim.splash_screen_animation);
In the upper activity code, we don't create view variable, because we don't need that time. But now we need those views add set this animation with those views. Create view and assign it by calling findViewById()
ImageView imageView = (ImageView) findViewById(R.id.splash_imageView);
TextView app = (TextView) findViewById(R.id.splash_app);
TextView appAbout = (TextView) findViewById(R.id.splash_appAbout);
set animation with those views and also start the animation
//set animation
imageView.setAnimation(set);
app.setAnimation(set);
appAbout.setAnimation(set);

//start animation
set.start();
That's it now run the app again and see the animation on your splash screen.

Are you confused about this class SplashScreen.java code?
See all the call code below:
public class SplashScreen extends AppCompatActivity {

    static {
        AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
    }

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

        ImageView imageView = (ImageView) findViewById(R.id.splash_imageView);
        TextView app = (TextView) findViewById(R.id.splash_app);
        TextView appAbout = (TextView) findViewById(R.id.splash_appAbout);


        Animation set = AnimationUtils.loadAnimation(this,
                R.anim.splash_screen_animation);

        //set animation
        imageView.setAnimation(set);
        app.setAnimation(set);
        appAbout.setAnimation(set);

        //start animation
        set.start();

        Thread checkForData = new Thread(){
            @Override
            public void run() {
                super.run();
                try{
                    sleep(1000);

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    startActivity(new Intent(SplashActivity.this,
                            MainActivity.class));
                    finish();
               }
             }
         };
        checkForData.start();

    }
}


See full video:

Note: in this video, you can also see the app intro. Link is here: Create Android Material App Intro

That's it 
now you can create a splash screen and also override the loading screen. In this example, I use just the only color but you can also use drawable in the loading time. So it's your choice what you used un your project.

That finished this post.
Why you wasting your time, create an awesome splash screen for your existing or next project?

Thank you for reading this post.
Happy coding.

Read More

Thursday, June 15, 2017

Android Night Mode

June 15, 2017

welcome to this post.In this post we are going to learn about how to use night mode on Android app. you can turn on night mode in your app by using android support library. you can use this option in settings or in the menu item.

night_mode
Night mode


In this case, I use this on settings. In a past post, we learn how to make app settings you can take a look
Let's start-
First, add new file name colors.xml in values-night folder and some colors-
<resources>
  <color name="colorPrimary">#051358</color>
  <color name="colorPrimaryDark">#020620</color>
  <color name="colorAccent">#800931</color>
  <color name="textColorPrimary">#e2dede</color>

  <color name="colorFabPressed">#1e710b</color>
  <color name="colorFabRipple">#0b0b3d</color>
  <color name="colorFabShadow">#66030303</color>

  <color name="colorFabToday">#385437</color>
  <color name="colorFabEveryday">#54364a</color>

  <color name="colorFabLabel_txt">#f2f1f1</color>
  <color name="colorFabLabelNormal">#232520</color>
  <color name="colorFabLabelPressed">#66626660</color>
  <color name="colorFabLabelRipple">#66844182</color>

</resources>
Note: add this color but you can only just add that's the color you want to override in night mode. Take a look on my values->colors.xml file then you can take a clear look on it.
<resources>
  <color name="colorPrimary">#3F51B5</color>
  <color name="colorPrimaryDark">#303F9F</color>
  <color name="colorAccent">#FF4081</color>
  <color name="textColorPrimary">#0e0e0e</color>

  <color name="colorFabPressed">#50ea2d</color>
  <color name="colorFabRipple">#2a23e7</color>
  <color name="colorFabShadow">#66626660</color>

  <color name="colorFabToday">#5d895a</color>
  <color name="colorFabEveryday">#704862</color>

  <color name="colorFabLabel_txt">#f2f1f1</color>
  <color name="colorFabLabelNormal">#232520</color>
  <color name="colorFabLabelPressed">#66626660</color>
  <color name="colorFabLabelRipple">#66844182</color>
</resources>
Now time to change your style- your style might look like this-
<!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">@color/colorPrimary</item>
  <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  <item name="colorAccent">@color/colorAccent</item>
  
  </style>
Now change Theme.AppCompat.Light.DarkActionBar to Theme.AppCompat.DayNight.DarkActionBar. Let's do this-
<!-- Base application theme. -->
  <style name="AppTheme" parent="Theme.AppCompat.DayNight.DarkActionBar">
  <!-- Customize your theme here. -->
  <item name="colorPrimary">@color/colorPrimary</item>
  <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
  <item name="colorAccent">@color/colorAccent</item>
  
  </style>
Look like you complete 50% work Now come to the java code- I am using settings so night is enabled not that's saved in a shared preference. Shared preferences key-
<string name="switchKey">SwitchKey</string>
Now create a method that is checked is night mode is enable or not. The default value is false-
public static boolean getNightModeEnabled(Context context) {

        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);

        return preferences.getBoolean(context.getString(R.string.switchKey), false);
    }
Now Create a new Methods that's set Night mode in any activity-
Follow those steps-
1. call the newly created methods and save the return value on a boolean.
2 If the value is true the we write AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES) on the if condition.
3. If it false then we add AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)this line.

see the code-
//set night mode for app
    private void setNightMode() {

        //get from setting check bok preference is true or false
        boolean isEnabled = getNightModeEnabled(this);

        if (isEnabled) {
            AppCompatDelegate.setDefaultNightMode(
                    AppCompatDelegate.MODE_NIGHT_YES);
        } else {
            AppCompatDelegate.setDefaultNightMode(
                    AppCompatDelegate.MODE_NIGHT_NO);
        }
    }
Final Screen short

day_mode
Day Mode

night_mode
Night mode


Thank you for reading this post hope you can use this option in your app
Happy coding

Read More

Wednesday, June 14, 2017

Android Material SearchView

June 14, 2017

Welcome to this post.
Android Material Search view tutorial. In this tutorial, we going to make a project and Implement A search view on the toolbar.
For search view, I use a 3rd party library Material SearchView

Note: If you don't want to use 3rd party library see this post,  Android Material SearchView with Recent Search Suggestions

Let's start-
Before starting, see a screenshot-

material_search_view
Material Search View


we have to do with this project-
1. we set search view on the toolbar.
2. Filter RecyclerView with text input
3. voice search

some bonus- In this project,
1. use SQL database for store data2. use the content provider to access data.
3. use Loaders for load data(Curser loaders).

Let's Start- First, add this line to your build.gradle file and sync gradle.
compile 'br.com.mauker.materialsearchview:materialsearchview:1.2.2'
Now go to on your style.xml file and below style-
<style name="MaterialSearchViewStyle">
  <item name="searchBackground">@color/white_ish</item>
  <item name="searchVoiceIcon">@drawable/ic_action_voice_search</item>
  <item name="searchCloseIcon">@drawable/ic_action_navigation_close</item>
  <item name="searchBackIcon">@drawable/ic_action_navigation_arrow_back</item>
  <item name="searchSuggestionBackground">@color/search_layover_bg</item>
  <item name="searchBarHeight">?attr/actionBarSize</item>
  <item name="voiceHintPrompt">@string/hint_prompt</item>
  <item name="android:textColor">@color/black</item>
  <item name="android:textColorHint">@color/gray_50</item>
  <item name="android:hint">@string/search_hint</item>
  <item name="android:inputType">textCapWords</item>
  </style>
OK, now time to add a toolbar to the layout. In this case, I add on activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="match_parent"
  android:layout_height="?attr/actionBarSize"
  tools:context=".MainActivity"
  android:background="@color/colorPrimary"
  android:layout_marginBottom="2dp"
  android:elevation="6dp">
  <!-- don't forget to set elevation or it look like old action bar-->

  <android.support.v7.widget.Toolbar
  android:id="@+id/toolbar"
  android:layout_width="match_parent"
  android:layout_height="?attr/actionBarSize"
  android:background="?attr/colorPrimary"
  android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
  app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />

  <br.com.mauker.materialsearchview.MaterialSearchView
  android:id="@+id/search_view"
  android:layout_width="match_parent"
  android:layout_height="match_parent"
  style="@style/MaterialSearchViewStyle"/>

  </RelativeLayout>
Note: I will provide GitHub link to this project later in this post

Now add a menu button on menu.xml-
<item
  android:id="@+id/action_search"
  android:icon="@drawable/ic_search"
  android:orderInCategory="100"
  android:title="@string/abc_search_hint"
  app:showAsAction="always" />

options menu looks like:

menu
Material Search View (options menu)


Now time to write java code- In this case MainActivity.java
MaterialSearchView searchView;
and again this view on onCreate-
searchView = (MaterialSearchView) findViewById(R.id.search_view);

now set all search operation I created a private method and call it on Oncreate-
In this method, we add three listeners to the search view-
1. setOnQueryTextListener
2. setSearchViewListener
3. setOnVoiceClickedListener In listener

1. setOnQueryTextListener is fired when we type text in the search view. In this listener, we have to override two methods name-
i. onQueryTextSubmit
ii. onQueryTextChange

i. onQueryTextSubmit is called when we put the query data with submit button.
after submit-
* build a URI
* call getContentResolver and query database and save it on cursor variable.
 * if the cursor is not null and cursor data is more than 0 we have data(Call cursor.getCount())
* so we go to the details activity with intent and set this URI with intent
*close search view

ii. onQueryTextChange is called every time when you write.
So we have to set-
* we are going to update recycler view with type text
* we check the text length is greater than zero
* then we create a selection string variable for cursor query. we use SQL LIKE statement not where statement.
String selection = MainWordDBContract.Entry.COLUMN_WORD +" like ? ";
* add also selection Argument-
String[] selectionArg = new String[]{newText+"%"};
* same way to get cursor and same condition for update UI as onQueryTextSubmit

Let's see the code-
searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {
  @Override
  public boolean onQueryTextSubmit(String query) {

  Uri uri = MainWordDBContract.Entry.buildUriWithWord(query.toUpperCase());
  Cursor cursor = getContentResolver().query(uri,
  MainActivity.projection,null,null,null);

  if (cursor != null && cursor.getCount() > 0){
  Intent intent = new Intent(MainActivity.this,
  DetailsActivity.class);
  intent.setData(uri);
  startActivity(intent);
  searchView.closeSearch();
  searchView.setCloseOnTintClick(false);
  }

  if (cursor != null){
  cursor.close();
  }
  return true;
  }

  @Override
  public boolean onQueryTextChange(String newText) {

  if (newText.length() > 0){
  String selection = MainWordDBContract.Entry.COLUMN_WORD +" like ? ";
  //if you are try to search from any position of word
  //then use
  //String[] selectionArg = new String[]{"%"+newText+"%"};
  //if you try to search from start of word the use this line
  String[] selectionArg = new String[]{newText+"%"};

  Cursor cursor = getContentResolver().query(MainWordDBContract.Entry.CONTENT_URI,
  MainActivity.projection,selection,selectionArg,null);

  if (cursor != null && cursor.getCount() > 0){
  mAdapter.swapCursor(cursor);
  }

  return true;
  } else {
  return false;
  }
  }
  });
Now add the setSearchViewListener listener and there are also two methods.
* if search view is open then hide the fab
* if searchView close the show the fab again Code-
searchView.setSearchViewListener(new MaterialSearchView.SearchViewListener() {
  @Override
  public void onSearchViewOpened() {
  fab.hide();
  }

  @Override
  public void onSearchViewClosed() {
  fab.show();
  }
  });
On the last, we have added setOnVoiceClickedListener if you are using this option. for this, I write another method name askSpeechInput so let's see the code one by one- the listener-
searchView.setOnVoiceClickedListener(new MaterialSearchView.OnVoiceClickedListener() {
  @Override
  public void onVoiceClicked() {
  askSpeechInput();
  }
  });
method-
private void askSpeechInput() {
  Intent intent = new Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH);

  intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL,
  RecognizerIntent.LANGUAGE_MODEL_FREE_FORM);

  intent.putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.getDefault());
  intent.putExtra(RecognizerIntent.EXTRA_PROMPT,
  "Speak your desire word");
  try {
  startActivityForResult(intent, MaterialSearchView.REQUEST_VOICE);
  } catch (ActivityNotFoundException a) {
  a.printStackTrace();
  slet("Activity not found", a);
  Toast.makeText(this, "Sorry Speech To Text is not " +
  "supported in your device", Toast.LENGTH_SHORT).show();
  }
  }
one more method to go. we are now overriding onActivityResult for getting voice input-
@Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        if (requestCode == MaterialSearchView.REQUEST_VOICE && resultCode == RESULT_OK) {
            ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);
            if (matches != null && matches.size() > 0) {
                String searchWrd = matches.get(0);
                if (!TextUtils.isEmpty(searchWrd)) {

                    //Todo more accure on settings
                    searchView.setQuery(searchWrd, false);
                    Uri uri = MainWordDBContract.Entry.buildUriWithWord(searchWrd.toUpperCase());

                    Cursor cursor = getContentResolver().query(uri,
                            MainActivity.projection,null,null,null);

                    if (cursor != null && cursor.getCount() > 0){
                        Intent intent = new Intent(MainActivity.this, DetailsActivity.class);
                        intent.setData(uri);
                        startActivity(intent);
                        searchView.closeSearch();
                        searchView.setCloseOnTintClick(false);
                    }

                    if (cursor != null){
                        cursor.close();
                    }
                }
            }

            return;
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

voice search screen short:
voice
Material Search View (voice search)


add this line onResume method
searchView.activityResumed();
and last one-
@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        switch (item.getItemId()) {
            case R.id.action_search:
                // Open the search view on the menu item click.
                searchView.openSearch();
                return true;

            default:
                return super.onOptionsItemSelected(item);
        }
    }
Now run your app and see the material search view

It will work fine.

Note: If you don't want to use 3rd party library to add search functionality, see this post.Android Material SearchView with Recent Search Suggestions
Thank you for reading

Happy coding

Read More