четверг, 21 февраля 2013 г.

Кастомизация интерфейса: Toast (Часть 2)

Кастомизация интерфейса: Toast (Часть 2)
В прошлой статье я рассказывал о том, как изменить интерфейс Toast и регулировать время отображения его на экране. Сегодня я расскажу, как закрывать Toast по нажатию.



Практика

К сожалению, отследить клик у самого элемента Toast никак не получится, так как он не активен для пользовательского взаимодействия. Мы прибегнем к хитрости, и вместо Toast будем использовать PopupWindow. Это всплывающее окно можно кастомизировать так же как Toast, но в отличие от него, PopupWindow может отлавливать пользовательские нажатия.
PopupWindow  имеет несколько вариантов отображения:
  • showAtLocation(View parent, int gravity, int x, int y): отображается в указанных координатах.
  • showAsDropDown(View anchor): отображается как выпадающий список в левом нижнем углу заданного View.
  • showAsDropDown(View anchor, int xoff, int yoff): отображается как выпадающий список в левом нижнем углу заданного View со смещением в велечину указанных координат.
В качестве рабочего проекта будем использовать проект, созданный в предыдущей статье.
Изменим класс CustomToast для работы с PopupMenu.
Добавим статический атрибут, который указывает: отображается или нет PopupWindow.
private static boolean isShow = false;
Также добавим Listener при срабатывании которого происходит закрытие PopupWIndow.
private static OnClickListener listner = new OnClickListener() {
  
  @Override
  public void onClick(View v) {
   isShow = false;
  }
 };

Изменим методы makeToast. Для PopupWindow необходим View, относительного которого он будет отображаться.
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);
 }

Полностью изменим метод showToast, который будет создавать наш PopupWindow. Чтобы наше всплывающее окно растягивалась по ширине на всю область окна, а по высоте подстраивалось под TextView, используем константы ViewGroup.LayoutParams.MATCH_PARENT и 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);
 }

Изменем метод для отображения PopupWindow. Чтобы отобразить всплывающее окно в нижней части экрана используется константа 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();
 }
Теперь немного изменим макет для основного окна. Добавим идентификатор для главного Layout окна, чтобы PopupWindow отображался относительного него.
Исходный код (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>
Исходный код основного Activity с изменениями.
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);
   }
  });
 }

Ссылки
  • Исходные коды данного проекта можно скачать отсюда: zip

Комментариев нет:

Отправить комментарий