Android RecyclerView TabLayout In Java

Android Lollipop highly focused on rich user experience which is called as Material Design , And this version features a new widget called RecyclerView . RecyclerView is an extremely powerful and flexible way to show a list, grid, or any view of a large set of data that can be recycled and scrolled very efficiently. One advantage over ListView or GridView is the built in support for animations as items are added, removed, or repositioned .



Build Gradle


Add the following lines to the dependencies section in your project's build.grade file.

file : build.gradle
dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile 'com.android.support:design:23.0.1'
    compile 'com.android.support:recyclerview-v7:23.0.1'
}

I this tutorial we will create RecyclerView in one of Tabs of TabLayout , Creating TabLayout is outside the scope of this tutorial ,In the previous tutorial I have covered how to Create TabLayout you can refer for it .

XML Layout


Create  XML layout file in res/layout and name it tab_one_fragment.xml and Add RecyclerView inside RelativeLayout.

file : tab_one_fragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/fragment_bg">

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recyclerview"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

</RelativeLayout>


Create  XML Layout file in res/layout and name it list_row.xml , This Layout defines the layout for Items of RecyclerView . Here In this example we have a TextView inside LinearLayout .

file : list_row.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:padding="16dp"
    android:layout_width="match_parent"
    android:layout_height="56dp">

    <TextView
        android:id="@+id/list_item"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>

</LinearLayout>

RecyclerView Adapter


Create a Adapter That RecyclerView Can Use .

  • Create A Class RVAdapter and this class Must Extend RecyclerView.Adapter. This adapter follows the view holder design pattern, which means that you have to define a custom class that extends RecyclerView.ViewHolder (This pattern minimizes the number of calls to the costly findViewById method.) .
  • So Create a  ItemViewHolder Inside the  RVAdapter and  this class Must Extend  RecyclerView.ViewHolder .
  • we already defined the XML layout list_row.xml , We are going to reuse that layout now. Inside the constructor of our custom ViewHolder, initialize the views that belong to the items of our RecyclerView. 
  • Next, add a constructor to the custom adapter so that it has a handle to the data that the RecyclerView displays , As our data is in the form of a List<String> . 
RecyclerView.Adapter has three abstract methods that we must override .
  1. getItemCount() :  This method return the number of items present in the data
  2. onCreateViewHolder() : Inside this method we specify the layout that each item of the RecyclerView should use. This is done by inflating the layout using LayoutInflater, passing the output to the constructor of the custom ViewHolder.
  3. onBindViewHolder() : This Method This method is very similar to the getView method of a ListView's adapter. In our example, here's where you have to set the String values to TextView. 
file : RVAdapter.java
package com.tutorialsbuzz.recyclerview.TabFragments;

import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.tutorialsbuzz.recyclerview.R;
import java.util.List;

public class RVAdapter extends RecyclerView.Adapter<RVAdapter.ItemViewHolder> {

    private List<String> mItems;
 
    public RVAdapter(List<String> mItems) {
        this.mItems = mItems;
    }

    public class ItemViewHolder extends RecyclerView.ViewHolder {

        private TextView mTextView;

        public ItemViewHolder(View itemView) {
            super(itemView);
            mTextView = (TextView) itemView.findViewById(R.id.list_item);
        }
    }

    @Override
    public void onBindViewHolder(ItemViewHolder itemViewHolder, int i) {
        itemViewHolder.mTextView.setText(mItems.get(i));
    }

    @Override
    public ItemViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
        View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_row, viewGroup, false);
        ItemViewHolder itemViewHolder = new ItemViewHolder(view);
        return itemViewHolder;
    }

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

Fragment


1.  Create a TabOneFragment which extends Fragment .
2.  Inside the onCreateView method get the reference to recyclerview and set the LayoutLayout .

Setting LayoutManager .
Unlike a ListView, a RecyclerView needs a LayoutManager to manage the positioning of its items
you could simply use one of the predefined LayoutManager subclasses:

  • LinearLayoutManager.
  • GridLayoutManager.
  • StaggeredGridLayoutManager.

In this tutorial, I am going to use a LinearLayoutManager. This LayoutManager subclass by default, make your RecyclerView look like a ListView.

3. Inside the OnActivityCreate method call to setAdpter on recyclerview reference and pass the object of the Custom Adapter.

file : TabOneFragment.java
package com.tutorialsbuzz.recyclerview.TabFragments;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.tutorialsbuzz.recyclerview.R;
import java.util.ArrayList;

public class TabOneFragment extends Fragment {

    private RecyclerView recyclerview;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.tab_one_fragment, container, false);

        recyclerview = (RecyclerView) view.findViewById(R.id.recyclerview);
        LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
        recyclerview.setLayoutManager(layoutManager);

        return view;
    }

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);

        ArrayList<String> items = new ArrayList<String>();
        for (int i = 0; i < 50; i++) {
            items.add("TextView_" + i);
        }

        RVAdapter adapter = new RVAdapter(items);
        recyclerview.setAdapter(adapter);

    }

}


Scrolling Behaviour


As I already mentioned at the beginning of the tutorial that I am Adding RecyclerView to one of Tabs of TabLayout , Creating Tablayout is out of the scope of this tutorial , you can find tutorial for it at Android TabLayout .

The Complete XML Layout of the Activity which contains Coordinate layout as parent view and inside we have AppBarLayout and ViewPager.

<android.support.design.widget.CoordinatorLayout     xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|enterAlways" />

        <android.support.design.widget.TabLayout
            android:id="@+id/tablayout"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:tabGravity="fill"
            app:tabMode="fixed" />

    </android.support.design.widget.AppBarLayout>

    <android.support.v4.view.ViewPager
        android:id="@+id/viewpager"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</android.support.design.widget.CoordinatorLayout>

  • In the above XML Layout we have Toolbar and TabLayout inside AppBarLayout 
  • The AppBarLayout allows the Toolbar and other views (such as tabs provided by TabLayout) to react to scroll events in a sibling view marked with a ScrollingViewBehaviour .
  • In the Above XML file ViewPager is a sibling view to appbar and to register the scroll behaviour  the ViewPager is marked with a  @string/appbar_scrolling_view_behavior .
  • When the user scrolls through the RecyclerView, the AppBarLayout responds by using its children’s scroll flags to control how they enter (scroll on screen) and exit (scroll off screen).

Flags include : 
  1. scroll: this flag should be set for all views that want to scroll off the screen - for views that do not use this flag, they’ll remain pinned to the top of the screen.
  2. enterAlways: this flag ensures that any downward scroll will cause this view to become visible, enabling the ‘quick return’ pattern .
  3. enterAlwaysCollapsed: When your view has declared a minHeight and you use this flag, your View will only enter at its minimum height (i.e., ‘collapsed’), only re-expanding to its full height when the scrolling view has reached it’s top.
  4. exitUntilCollapsed: this flag causes the view to scroll off until it is ‘collapsed’ (its minHeight) before exiting .
Note : all views using the scroll flag must be declared before views that do not use the flag.This ensures that all views exit from the top, leaving the fixed elements behind.

In our app we use the scroll and enterAlways flags on the Toolbar which will result in the Toolbar scrolling off screen when scrolling upwards and come back on screen on the downward scroll. Notice the use of app:layout_behavior="@string/appbar_scrolling_view_behavior" on the ViewPager. The support library contains a special string resource @string/appbar_scrolling_view_behavior that maps to AppBarLayout. ScrollingViewBehavior, which is used to notify the AppBarLayout when scroll events occur on a particular view.  The behavior must be established on the view that triggers the event. 



Read More »

Android MultiChoice AlertDialog

Alert dialog is a subclass of dialog class ,In MultiChoice AlertDialog the content area of dialog contains list of items allowing users to select one or more options from a set .

  1. MultiChoice AlertDialog contains list of item with Text and Checkbox .
  2. To specify the items for the list, call setMultiChoiceItems  by passing an array of String for text to display and  array of boolean values to display checked and unchecked status for respective items.

Optionally you can set title ,icon ,message for the alertDialog .

XML Layout


Create XML Layout activity_main.xml , this will be set as content view for launcher Activity (MainActivity.kt) .

file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        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:orientation="vertical"
        android:padding="30dp"
        tools:context=".MainActivity">

    <androidx.appcompat.widget.AppCompatButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="show MultiChoice Dialog"
            android:textSize="20sp"
            android:textAllCaps="false"
            android:onClick="multiChoiceDialog"/>
    
</LinearLayout>

 Activity

  1. Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
  2. Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml).
file : MainActivity.kt
package com.tutorialsbuzz.multichoicealertdialog

import android.content.DialogInterface
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AlertDialog

class MainActivity : AppCompatActivity() {

    val multiChoiceList = linkedMapOf<String, Boolean>(
        "English" to false,
        "Hindi" to false,
        "French" to false,
        "Spanish" to false,
        "Portuguese" to false,
        "German" to false,
        "Italian" to false,
        "Korean" to false,
        "Japanese" to false,
        "Chinese" to false
    )

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun multiChoiceDialog(view: View) {

        val builder = AlertDialog.Builder(this)
        builder.setTitle("Select Languages")

        builder.setMultiChoiceItems(multiChoiceList.keys.toTypedArray(),
            multiChoiceList.values.toBooleanArray(), { dialogInterface, which, isChecked ->

                multiChoiceList.set(multiChoiceList.keys.toTypedArray().get(which), isChecked)

                val status = if (isChecked) {
                    " :is checked"
                } else {
                    " :is un-checked"
                }

                Toast.makeText(
                    this@MainActivity,
                    "item: " + multiChoiceList.keys.toTypedArray().get(which) + status, Toast.LENGTH_SHORT
                ).show()

            })

        builder.setPositiveButton("ok", DialogInterface.OnClickListener { dialog, id ->
            Log.d("Selected Items", multiChoiceList.toString())
            dialog.dismiss()
        })
        builder.setNegativeButton("cancel", { dialog, id ->
            dialog.dismiss()
        })

        val alertDialog = builder.create()
        alertDialog.show()
    }

}



Read More »

Android SingleChoice AlertDialog

Alert dialog is a subclass of dialog class ,In SingleChoice AlertDialog the content area of dialog contains list of items allowing users to select one option from a set .


SingleChoice AlertDialog has two kind of layout .

Text
  • List of Item Containing only Text , to have this kind of layout call  .
  • To specify the items for the list, call setItems()  by passing an array , Alernatively you can pass list adapter  , the resource id of an array (eg R.array.foo) , Cursor

Text With RadioButton
  • List of Item Containing Text and RadioButon , to have this kind of layout call setSingleChoiceItems().
  • To specify the items for the list, call setSingleChoiceItems()  by passing an array , Alernatively you can pass list adapter  , the resource id of an array (eg R.array.foo) , Cursor

Optionally you can set title ,icon ,message for the alertDialog .

1. XML Layout


file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        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:orientation="vertical"
        android:padding="30dp"
        tools:context=".MainActivity">


    <androidx.appcompat.widget.AppCompatButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="show Single Item Dialog"
            android:textSize="20sp"
            android:onClick="singleChoiceItem"
            android:textAllCaps="false"/>


    <androidx.appcompat.widget.AppCompatButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="show Single Choice Dialog"
            android:textSize="20sp"
            android:onClick="singleChoiceDialog"
            android:textAllCaps="false"/>

</LinearLayout>

1. Activity


file : MainActivity.kt
package com.tutorialsbuzz.singlechoicealertdialog

import android.content.DialogInterface
import android.os.Bundle
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }


    fun singleChoiceItem(view: View) {
        val singleChoiceList = arrayOf("google", "yahoo", "bing", "yandex", "baidu", "duckduckgo")
        val builder = AlertDialog.Builder(this)
        builder.setTitle("Select Search Engine")

        builder.setItems(singleChoiceList, { dialogInterface, which ->
            Toast.makeText(this@MainActivity, singleChoiceList[which], Toast.LENGTH_SHORT).show()
        })

        // builder.create().show();
        val alertDialog = builder.create()
        alertDialog.show()
    }

    fun singleChoiceDialog(view: View) {

        val singleChoiceList = arrayOf("google", "yahoo", "bing", "yandex", "baidu", "duckduckgo")
        val builder = AlertDialog.Builder(this)

        builder.setTitle("Select Search Engine")

        builder.setSingleChoiceItems(singleChoiceList, -1,
            { dialogInterface, which ->
                Toast.makeText(this@MainActivity, singleChoiceList[which], Toast.LENGTH_SHORT).show()
            }
        )

        builder.setPositiveButton("ok", DialogInterface.OnClickListener { dialog, id ->
            dialog.dismiss()
        })
        builder.setNegativeButton("cancel", { dialog, id ->
            dialog.dismiss()
        })

        // builder.create().show();
        val alertDialog = builder.create()
        alertDialog.show()
    }

}

Read More »

Android AlertDialog Styling .

Alert dialog is a subclass of dialog that can show a title, up to three buttons, a list of selectable items, or a custom layout.

In the previous tutorial we have seen basic example of Android AlertDialog , In this tutorial we will see styling of AlertDialog .


 AlertDialog.Builder class has single and double paramterized constructor .

 1.  AlertDialog.Builder(Context context)
 2.  AlertDialog.Builder(Context context, @StyleRes int themeResId) : The themeResId is used to set the theme of the Dialog .

1. Light Theme


Pass the Theme_AppCompat_Light_Dialog_Alert Theme to AlertDialog.Builder constructor .

val builder: AlertDialog.Builder =
   AlertDialog.Builder(this@MainActivity, R.style.Theme_AppCompat_Light_Dialog_Alert)


2. Dark Theme


Pass the R.style.Theme_AppCompat_Dialog_Alert Theme to AlertDialog.Builder constructor .

val builder: AlertDialog.Builder =
   AlertDialog.Builder(this@MainActivity, R.style.Theme_AppCompat_Dialog_Alert)



3. Custom Theme


<style name="CustomAlertDialog" parent="Theme.AppCompat.Dialog.Alert">
<item name="android:background">#FFEB3B</item>
<item name="android:textColor">#9C27B0</item>
<item name="android:textColorPrimary">#E91E63</item>
</style>

Pass the above defined style to AlertDialog.Builder constructor .

val builder: AlertDialog.Builder =
AlertDialog.Builder(this@MainActivity, R.style.CustomAlertDialog)


Read More »

Android Kotlin AlertDialog

Alert dialog is a subclass of dialog that can show a title, up to three buttons, a list of selectable items, or a custom layout.

Lets See example .

AlertDialog.Builder


AlertDialog.Builder class has some of the important method/fun for building AlertDialog .
Dialog has three part Title,Content Area,Action

1. Icon :
 setIcon() is used to set the icon of dialog , it takes resource id of the drawable as parameter .

2. Title : 
 setTitle() is used to set the title of dialog , it takes string as parameter .

3. Message :
 setMessage is used to set the message of dialog , it takes string as parameter .

4. Adding Buttons : 
  • Positive Button : You should use this to accept and continue with the action (the "OK" action). call setPositiveButton to add positive button .
  • Negative Button : You should use this to cancel the action. call setNegative to add Negative button .
  • Neutral Button : You should use this when the user may not want to proceed with the action . call setNetural to add Netural button .
Above the three method takes two parameter .
1. String : The text to display in the positive button .
2. DialogInterface.OnClickListener: For Listening click event .

Show Dialog
Calling show() on alertDialog object will show alertDialog .

Dismiss Dialog
 On DialogInterface calling dismiss() , will dismiss the dialog.

XML Layout


Create XML Layout activity_main.xml , this will be set as content view for launcher Activity (MainActivity.kt) .

file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        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:orientation="vertical"
        android:padding="30dp"
        tools:context=".MainActivity">

    <androidx.appcompat.widget.AppCompatButton
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="show AlertDialog"
            android:textSize="20sp"
            android:textAllCaps="false"
            android:onClick="showAlertDialog"/>
    
</LinearLayout>

Activity


  1. Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
  2. Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml).
file : MainActivity.kt
package com.tutorialsbuzz.alertdialogsample

import android.content.DialogInterface
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun showAlertDialog(view: View): Unit {

        val builder: AlertDialog.Builder = AlertDialog.Builder(this@MainActivity)

        builder.setTitle("Title")
        builder.setMessage("Message")
        builder.setIcon(R.mipmap.ic_launcher)

        builder.setPositiveButton("ok", DialogInterface.OnClickListener { dialog, id ->
            dialog.dismiss()
        })
        builder.setNegativeButton("cancel", { dialog, id ->
            dialog.dismiss()
        })

        builder.setNeutralButton("Can't Say", { dialog, i ->
            dialog.dismiss()
        })

        val alertDialog: AlertDialog = builder.create()
        alertDialog.show()

    }
    
}



Read More »

Android WebView Kotlin

Android WebView allow you to display web content as part of your activity layout, WebView class is an extension of Android's View class , you can used it to Create web based application or just show/embed a web page in your app .

Lets See Example .

Project Detail
Project Name AndroidWebView
Package com.tutorialsbuzz.androidwebview
Min Sdk Version 22
Target Sdk Version 28
Compile Sdk Version 28
Theme Theme.AppCompat.Light.DarkActionBar


Android Manifest


 Add Internet Permission to manifest file .

file : AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
          package="com.tutorialsbuzz.androidwebview">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
    </application>

</manifest>


XML Layout 

  1. Create XML Layout activity_main.xml , this will be set as content view for launcher Activity (MainActivity.kt) .
  2. Add Seekbar widget (used for adjusting textsize of the webview) .
  3. Add two Buttons (used for Back , Forward Navigation For Webview) .
  4. Add WebView to xml layout .
file : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity"
        android:orientation="vertical">
    
    <include layout="@layout/navigator"/>

    <WebView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:id="@+id/webView"/>

</LinearLayout>

WebView Loading WebContent


1. Loading From Asset.
webView.loadUrl("file:///android_asset/index.html")

2. Loading HTML Markup.
val htmlMarkup: String = "<html>\n" +
  "<body style=\"background-color: #FF9800; font-size: 16pt; color: #ffffff;\">\n" +
  "<div>\n" +
  "    welcome to \"www.tutorialsbuzz.com\"\n" +
  "    <br/>\n" +
  "    Reendering from Markup Code \n" +
  "</div>\n" +
  "</body>\n" +
  "</html>"
webView.loadData(htmlMarkup, "text/html", "UTF-8")

3. Loading content from hosted online.
webView.loadUrl("https://www.google.com")

WebView Settings


Applying WebView Settings .
Enabling JavaScript and ZoomControl
val webViewSettings = webView.settings
webViewSettings.javaScriptEnabled = true
webViewSettings.builtInZoomControls = true

WebViewClient callback


webViewClient has below callback

onPageStarted Notifies the page start event
onPageFinished Notifies the page end event
shouldOverrideUrlLoading 1. Give the host application a chance to take control
when a URL is about to be loaded in the current WebView
If a WebViewClient is not provided, by default
WebView will ask Activity Manager to choose the
proper handler for the URL .

2. Returning true causes the current WebView to
abort or stop loading the URL .

3. Returning false causes the current WebView to
continue loading the URL as usual

WebChromeClient


webChromeClient has below callback

onProgressChanged Tell the host application the current progress of loading a page.
onReceivedIcon Notify the host application of a new favicon for the current page.
onReceivedTitle Notify the host application of a change in the document or webpage title.

WebView Navigation


1. Back Navigation  

 canGoBack() : Gets whether this WebView has a back history item.
 goBack(): Goes back in the history of this WebView.

2. Forward Navigation

 canGoForward(): Gets whether this WebView has a forward history item.
 goForward() : Goes forward in the history of this WebView.

3. Handling WebView On Device BackPress.

Inside onBackPressed callback of activity check whether webview has back history , if yes call goBack on webvie else call  super.onBackPressed() .

override fun onBackPressed() {
 if (webView.canGoBack()) {
  webView.goBack()
 } else {
  super.onBackPressed()
 }
}

Activity

  1. Create a koltin class MainActivity.kt and extend it to AppCompatActivity class .
  2. Override onCreate function and set the content of this MainActivity with above defined xml layout (activity_main.xml).
  3. Using webView reference apply webview settings and load url .
file : MainActivity.kt
package com.tutorialsbuzz.androidwebview

import android.graphics.Bitmap
import android.os.Bundle
import android.util.Log
import android.webkit.WebChromeClient
import android.webkit.WebResourceRequest
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.appcompat.app.AppCompatActivity
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.android.synthetic.main.navigator.*

class MainActivity : AppCompatActivity() {

    val TAG: String = MainActivity::class.java.simpleName

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        webView.loadUrl("https://www.google.com");

        val webViewSettings = webView.settings

        webViewSettings.javaScriptEnabled = true
        webViewSettings.builtInZoomControls = true
        
        webView.webViewClient = object : WebViewClient() {
            override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
                super.onPageStarted(view, url, favicon)
                Log.d(TAG, "onPageStarted")
            }

            override fun onPageFinished(view: WebView?, url: String?) {
                super.onPageFinished(view, url)
                Log.d(TAG, "onPageFinished")
            }

            override fun shouldOverrideUrlLoading(view: WebView?, request: WebResourceRequest?): Boolean {
                return false
            }
        };

        webView.webChromeClient = object : WebChromeClient() {

            override fun onProgressChanged(view: WebView?, newProgress: Int) {
                super.onProgressChanged(view, newProgress)
                Log.d(TAG, "onProgressChanged Progress $newProgress")
            }
        }

        navBack.setOnClickListener({ v ->
            if (webView.canGoBack())
                webView.goBack()
        })

        navFwd.setOnClickListener({ v ->
            if (webView.canGoForward())
                webView.goForward()
        })
    }

    override fun onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack()
        } else {
            super.onBackPressed()
        }
    }
}


Read More »

Android Styling SeekBar Thumb and Progress Track

 A SeekBar is an extension of ProgressBar that adds a draggable thumb. The user can touch the thumb and drag left or right to set the current progress level or use the arrow keys .

In the previous tutorial we have seen basic example of Android SeekBar , In this tutorial we will see how to style it's thumb and progress track .



1 SeekBar Thumb


To Change SeekBar Thumb we use android:thumb attribute or property of seekbar widget , the below drawable is set to this attribute.  android:thumb="@drawable/seekbar_thumb"

1.a  Shape Thumb:

<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="@color/colorAccent">
    <item>
        <shape android:shape="oval">
            <solid android:color="@color/colorAccent"/>
            <size android:width="30dp" android:height="30dp"/>
        </shape>
    </item>
</ripple>

1.b Drawable Thumb: 

The flower01 is png image kept inside res/drawable .

<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
        android:color="?android:colorControlHighlight">
    <item android:drawable="@drawable/flower01">
    </item>
</ripple>

2. SeekBar Progress Track


To Change SeekBar Progress we use ndroid:progressDrawable attribute or property of seekbar widget , the below drawable is set to this attribute. android:progressDrawable="@drawable/seekbar_progress_style" .

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">

    <item android:id="@android:id/background"
          android:drawable="@drawable/seekbar_track">
    </item>

    <item android:id="@android:id/progress">
        <clip android:drawable="@drawable/seekbar_progress"/>
    </item>
</layer-list>

In the above xml

Track: item with id @android:id/background will set to seekbar track .

Progress : item with id android:id="@android:id/progress" will set to progress .

Track
file: seekbar_track.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <corners android:radius="5dp"/>
            <gradient
                    android:angle="270"
                    android:centerColor="#11000000"
                    android:centerY="0.2"
                    android:endColor="#11000000"
                    android:startColor="#33000000"
                    android:type="linear"/>
        </shape>
    </item>
</layer-list>

Progress
file: seekbar_progress.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:id="@+id/progressshape">
        <clip>
            <shape android:shape="rectangle">
                <size android:height="5dp"/>
                <corners android:radius="5dp"/>
                <solid android:color="#3db5ea"/>
            </shape>
        </clip>
    </item>
</layer-list>

Applying Above Defined Style to Seekbar

<androidx.appcompat.widget.AppCompatSeekBar
		android:layout_marginTop="50dp"
		android:layout_width="match_parent"
		android:layout_height="wrap_content"
		android:id="@+id/seekbar01"
		android:maxHeight="8dp"
		android:progressDrawable="@drawable/seekbar_progress_style"
		android:thumb="@drawable/seekbar_thumb_shape"
		android:thumbOffset="0dp"/>




Read More »