Monday, 13 March 2017

Android Custom Spinner (drop down list) example

The Android Spinner is similar to a drop-down list or AWT combo-box, used for displaying multiple items from which the user can choose one. In this example, after creating a new project with a main activity, we will do the following tasks:
  1. Create an XML layout file for a single spinner item
  2. Create a CustomAdapter which extends BaseAdapter
  3. Attach the adapter to the spinner widget
  4. Run the code


1. Android XML Layout Files


File: res/layout/custom_spinner_items.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:orientation="horizontal">

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:padding="5dp"
        android:src="@mipmap/ic_launcher"/>

    <TextView
        android:id="@+id/textView"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:padding="@dimen/activity_horizontal_margin"
        android:textColor="#000"
        android:textSize="16sp"/>
</LinearLayout>

File: res/layout/content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/rl_main"
    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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="android.google.com.uiexample.MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="5dp"
        android:text="Custom Spinner Example"
        android:textAlignment="center"
        android:textColor="?android:attr/editTextColor"
        android:textSize="24sp"
        android:textStyle="normal|bold"/>

    <Spinner
        android:id="@+id/simpleSpinner"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="60dp"
        android:backgroundTint="@android:color/holo_blue_bright"/>

    <RelativeLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/simpleSpinner"
        android:layout_marginTop="70dp"
        android:background="@android:color/holo_blue_bright"
        android:padding="10dp">

        <ImageView
            android:id="@+id/iv_flag"
            android:layout_width="50dp"
            android:layout_height="50dp"
            android:layout_alignParentStart="true"
            android:layout_alignParentTop="true"
            android:layout_marginTop="10dp"
            app:srcCompat="@mipmap/ic_launcher"/>

        <TextView
            android:id="@+id/tv_country"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true"
            android:layout_marginTop="11dp"
            android:textSize="24sp"
            android:textStyle="normal|bold"/>

        <TextView
            android:id="@+id/textViewCT"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignParentStart="true"
            android:layout_below="@+id/iv_flag"
            android:layout_marginTop="40dp"
            android:text="Current Time:"
            android:textStyle="normal|bold"/>

        <TextView
            android:id="@+id/tv_time"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_alignBottom="@+id/textViewCT"
            android:layout_marginStart="15dp"
            android:layout_toEndOf="@+id/textViewCT"
            android:textSize="30sp"/>
    </RelativeLayout>

</RelativeLayout>

2. CustomAdapter

File: CustomAdapter.java
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

class CustomAdapter extends BaseAdapter
{
  private int flags[];
  private String[] countryNames;
  private LayoutInflater inflater;

  CustomAdapter(Context applicationContext, int[] flags, String[] countryNames)
  {
    this.flags = flags;
    this.countryNames = countryNames;
    inflater = (LayoutInflater.from(applicationContext));
  }

  @Override
  public int getCount()
  {
    return flags.length;
  }

  @Override
  public Object getItem(int i)
  {
    return null;
  }

  @Override
  public long getItemId(int i)
  {
    return 0;
  }

  @Override
  public View getView(int i, View view, ViewGroup viewGroup)
  {

    view = inflater.inflate(R.layout.custom_spinner_items, viewGroup, false);
    ImageView flag_icon = (ImageView) view.findViewById(R.id.imageView);
    TextView country_name = (TextView) view.findViewById(R.id.textView);
    flag_icon.setImageResource(flags[i]);
    country_name.setText(countryNames[i]);
    return view;
  }
}
3. Attach Adapter

File: MainActivity.java
import android.os.Bundle;
import android.view.View;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.ImageView;
import android.widget.AdapterView;
import android.support.v7.app.AppCompatActivity;

import java.util.Date;
import java.util.Calendar;
import java.util.TimeZone;
import java.text.SimpleDateFormat;

public class MainActivity extends AppCompatActivity implements AdapterView.OnItemSelectedListener
{

  private ImageView imgView;
  private TextView country_name;
  private TextView country_time;

  // Text shown in spinner
  private String[] countries = {"Ireland", "France", "Greece", "India",
                        "Japan", "Australia", "America - LA", "America - NY"};

  // Images from res/drawable folder
  private int flags[] = {R.drawable.ireland, R.drawable.france, R.drawable.greece, R.drawable.india,
    R.drawable.japan, R.drawable.australia, R.drawable.america, R.drawable.america};

  // timezones for each country
  private String[] timezones = { "Europe/Dublin","Europe/Paris","Europe/Athens", "Asia/Calcutta",
                                 "Japan","Australia/Perth","US/Pacific", "US/Eastern" };

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

    this.imgView = (ImageView) findViewById(R.id.iv_flag);
    this.country_name = (TextView) findViewById(R.id.tv_country);
    this.country_time = (TextView) findViewById(R.id.tv_time);


    //Getting the instance of Spinner and applying OnItemSelectedListener on it
    Spinner spinner = (Spinner) findViewById(R.id.simpleSpinner);
    spinner.setOnItemSelectedListener(this);

    CustomAdapter customAdapter = new CustomAdapter(getApplicationContext(), flags, countries);
    spinner.setAdapter(customAdapter);
  }

  //Performing action onItemSelected
  @Override
  public void onItemSelected(AdapterView<?> arg0, View arg1, int position, long id)

  {
    Date date = Calendar.getInstance().getTime();
    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm");
    sdf.setTimeZone(TimeZone.getTimeZone(timezones[position]));
    String today = sdf.format(date);

    imgView.setImageResource(flags[position]);
    country_name.setText(countries[position]);
    country_time.setText(today);

  }

  // not needed
  @Override
  public void onNothingSelected(AdapterView<?> adapterView)
  {}
  
}
4. Result



Friday, 10 March 2017

Android Custom AlertDialog Example

The following example shows the normal inbuilt AlertDialog plus a custom AlertDialog with icon.

  1. Create a custom xml file for the dialog layout
  2. Attach the layout file
  3. Display the dialog

1. Android XML Layout Files

There are 2 XML files needed, one for the main activity, and one for the custom dialog.

File: res/layout/content_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
    android:id="@+id/rl_main"
    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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context="android.google.com.uiexample.MainActivity">


    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="11dp"
        android:text="Custom Dialog Example"
        android:textAlignment="center"
        android:textColor="?android:attr/editTextColor"
        android:textSize="24sp"
        android:textStyle="normal|bold"/>

    <Button
        android:id="@+id/buttonNormalDialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="140dp"
        android:text="Show Normal Dialog"/>

    <Button
        android:id="@+id/buttonCustomDialog"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignEnd="@+id/buttonNormalDialog"
        android:layout_below="@+id/buttonNormalDialog"
        android:layout_marginTop="40dp"
        android:text="Show Custom Dialog"/>

</RelativeLayout>
File: res/layout/custom_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="wrap_content"
              android:layout_height="wrap_content"
              android:orientation="vertical">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center_horizontal"
        android:padding="5dp"
        android:text="CUSTOM DIALOG"
        android:textColor="@color/my_color_green"
        android:textSize="18sp"
        android:textStyle="normal|bold"/>

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="64dp"
        android:background="#FFFFBB33"
        android:contentDescription="@string/app_name"
        android:scaleType="center"
        android:src="@mipmap/ic_launcher"/>

    <EditText
        android:id="@+id/editTextUsername"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="4dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginTop="16dp"
        android:hint="@string/username"
        android:inputType="textEmailAddress"/>

    <EditText
        android:id="@+id/editTextPassword"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginBottom="16dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:layout_marginTop="4dp"
        android:fontFamily="sans-serif"
        android:hint="@string/password"
        android:inputType="textPassword"/>
</LinearLayout>

2. Java Activity


File: MainActivity.java
package android.google.com.uiexample;

import android.content.DialogInterface;
import android.graphics.Color;
import android.os.Bundle;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.RelativeLayout;
import android.widget.Toast;

import java.util.Random;

public class MainActivity extends AppCompatActivity
{

  private RelativeLayout myLayout;

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

    getWidgets();
  }

  private void getWidgets()
  {

    Button btnNormalDialog = (Button) findViewById(R.id.buttonNormalDialog);
    Button btnCustomDialog = (Button) findViewById(R.id.buttonCustomDialog);

    myLayout = (RelativeLayout) findViewById(R.id.rl_main);

    /*
      OnClickListener : shows normal dialog
     */
    btnNormalDialog.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(View view)
      {
        showNormalDialog();
      }
    });

    /*
      OnClickListener : shows custom dialog
     */
    btnCustomDialog.setOnClickListener(new View.OnClickListener()
    {
      @Override
      public void onClick(View view)
      {
        showCustomDialog();
      }
    });

  }

  /*
      In-built dialog: no XML Layout
  */
  private void showNormalDialog()
  {
    AlertDialog.Builder builder = new AlertDialog.Builder(this);

    //Setting message manually and performing action on button click
    builder.setMessage("Do you want to change background color ?")
      .setCancelable(false)
      .setPositiveButton("Yes", new DialogInterface.OnClickListener()
      {
        public void onClick(DialogInterface dialog, int id)
        {
          setActivityBackgroundColor();
        }
      })
      .setNegativeButton("No", new DialogInterface.OnClickListener()
      {
        public void onClick(DialogInterface dialog, int id)
        {
          //  Action for 'NO' Button
          dialog.cancel();
        }
      });

    //Creating dialog box
    AlertDialog alert = builder.create();
    //Setting the title manually
    alert.setTitle("Normal Dialog Example");
    alert.show();
  }

  /*
      Custom dialog: uses XML Layout custom_dialog.xml
  */
  private void showCustomDialog()
  {

    AlertDialog.Builder builder = new AlertDialog.Builder(this);

    // Get the layout inflater
    LayoutInflater inflater = this.getLayoutInflater();

    // Inflate and set the layout for the dialog
    // Pass null as the parent view because its going in the dialog layout
    final View myLayout = inflater.inflate(R.layout.custom_dialog, null);

    builder.setView(myLayout)
      // Add action buttons
      .setPositiveButton("Sign in", new DialogInterface.OnClickListener()
      {
        @Override
        public void onClick(DialogInterface dialog, int id)
        {
          // Get EditText widgets
          EditText inputName = (EditText) myLayout.findViewById(R.id.editTextUsername);
          EditText inputPassword = (EditText) myLayout.findViewById(R.id.editTextPassword);

          // Get EditText input values - no validation
          String name = inputName.getText().toString();
          String password = inputPassword.getText().toString();

          // call toast method
          signInToast(name, password);
        }
      })
      .setNegativeButton("Cancel", new DialogInterface.OnClickListener()
      {
        public void onClick(DialogInterface dialog, int id)
        {
          dialog.dismiss();
        }
      });
    builder.show();
  }

  public void signInToast(String name, String password)
  {
    Toast.makeText(this, "Name:  " + name +
      "\n\nPassword:  " + password, Toast.LENGTH_SHORT).show();
  }

  /*
      Changes the current Activity background to a random color
  */
  public void setActivityBackgroundColor()
  {
    Random rand = new Random();
    myLayout.setBackgroundColor(Color.argb(255, rand.nextInt(256), rand.nextInt(256), rand.nextInt(256)));
  }

}

3. Dialog Display