Thursday, February 21, 2013

Interface: Custom Toast (Part 2)

Customization interface: Toast (Part 2)
In the previous article I talked about how to change the Toast interface and regulate the time display on the screen. Today I'll show how to close Toast  by clicking.



Practice

Unfortunately, the track at the click of the Toast does not work, because it is not active for user interaction. We will resort to tricks, and instead Toast will use PopupWindow. This pop-up window you can customize as well as Toast, but unlike him, PopupWindow can catch the user clicking.
PopupWindow has several options for displaying:
  • showAtLocation(View parent, int gravity, int x, int y): display the content view in a popup window at the specified location.
  • showAsDropDown(View anchor): display the content view in a popup window anchored to the bottom-left corner of the anchor view.
  • showAsDropDown(View anchor, int xoff, int yoff): display the content view in a popup window anchored to the bottom-left corner of the anchor view offset by the specified x and y coordinates.
As the working project will use a project created in a previous article.
Change the class CustomToast to work with PopupMenu.
Add a static attribute, which indicates: displayed or not PopupWindow..
private static boolean isShow = false;
Also add a Listener when triggered which is closing PopupWIndow.
private static OnClickListener listner = new OnClickListener() {
  
  @Override
  public void onClick(View v) {
   isShow = false;
  }
 };

Change the method makeToast. PopupWindow needs to View, concerning which it will be displayed.
public static void makeToast(Context context, View contentView, String msg, long duration) {
  
  if (isShow)
   return;

  LayoutInflater inflater = (LayoutInflater) context
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  View view = inflater.inflate(R.layout.layout_toast, null);
  view.setOnClickListener(listner);
  
  ((TextView) view.findViewById(R.id.text)).setText(msg);

  showToast(context, contentView, view, duration);
 }
public static void makeToast(Context context, View contentView, int msg, long duration) {
  
  if (isShow)
   return;

  LayoutInflater inflater = (LayoutInflater) context
    .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
  View view = inflater.inflate(R.layout.layout_toast, null);

  ((TextView) view.findViewById(R.id.text)).setText(msg);
  view.setOnClickListener(listner);

  showToast(context, contentView, view, duration);
 }

Completely changed the method showToast, which will create our PopupWindow. To our pop-up window stretched across the width of the window at all, and the height adjusts to the TextView, using constants ViewGroup.LayoutParams.MATCH_PARENT and ViewGroup.LayoutParams.WRAP_CONTENT.
private static void showToast(Context context, View contentView, View view, long duration) {
  PopupWindow window = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, false);

  show(context, contentView, duration * 1000, window);
 }

Modified method for displaying PopupWindow. To display a pop-up window in the lower part of the screen is used constant Gravity.BOTTOM.
private static void show(Context context, final View contentView, final long durationInMilliseconds,
   final PopupWindow window) {
     
       window.showAtLocation(contentView, Gravity.BOTTOM, 0, 0);

  Thread t = new Thread() {
   long timeElapsed = 0l;

   public void run() {
    try {

     isShow = true;
         
     while (timeElapsed <= durationInMilliseconds && isShow) {
      long start = System.currentTimeMillis();
      sleep(250);
      timeElapsed += System.currentTimeMillis() - start;
     }
     isShow = false;
     window.dismiss();

    } catch (InterruptedException e) {
    }
   }
  };
  t.start();
 }

Now slightly change the layout for the main window. Add the ID for the main Layout window to PopupWindow appear for him.

Source code (main.xml)
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/toast_layout_root"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/toast"
    android:orientation="horizontal"
    android:padding="8dp" >

    <TextView
        android:id="@+id/text"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_marginBottom="5dp"
        android:gravity="center"
        android:padding="8dp"
        android:textColor="#FFF"
        android:textSize="14sp" />

</LinearLayout>

Source code main Activity with changes:
private EditText ed_txt, ed_time;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.main);
  
  ed_time = (EditText)findViewById(R.id.ed_time);
  ed_txt = (EditText)findViewById(R.id.ed_txt);
  
  final Context context = this;
  final View contentView = findViewById(R.id.main);
  
  findViewById(R.id.btn_show).setOnClickListener(new OnClickListener() {
   
   @Override
   public void onClick(View v) {
    int duration = 1;
    try 
    {
     duration = Integer.parseInt(ed_time.getText().toString());
    } catch (Exception e) {
    }
    CustomToast.makeToast(context, contentView, ed_txt.getText().toString(), duration);
   }
  });
 }

Links

  • The source codes of this project can be downloaded here: zip