Страницы

среда, 29 сентября 2010 г.

Ellipsize и TextView

Не секрет, что у мобильных устройств экран невелик, и поэтому часто длинный текст не умещается на экране целиком. Можно на это забить и оставить текст обрезанным либо можно поставить многоточие на месте обрезки (см. рисунок). Для этого есть метод setEllipsize() и соответствующий ему атрибут android:ellipsize.



Всё бы хорошо, но при попытке применения их я столкнулся с неожиданным поведением метода setEllipsize() у TextView: для однострочного текста из нескольких слов метод не работает. Строка обрезается, но многоточие в конце не появляется. То же самое и с XML-атрибутом android:ellipsize. Вот так это выглядит:


Можно заметить, что метод работает, но работает неверно: неуместившийся остаток текста просто отбрасывается.

Выяснил, что это давний баг, который не исправляется в течение двух лет. В багтрекере андроида есть соответствующие записи: http://code.google.com/p/android/issues/detail?id=882 и http://code.google.com/p/android/issues/detail?id=10554

Одним из вариантов обхода бага является установка атрибута android:singleLine="true", но он объявлен deprecated (хотя и замечательно работает до сих пор).
Другой обходной путь - имитировать поведение атрибута android:singleLine другими атрибутами: android:lines="1" и android:scrollHorizontally="true".

Советую пройти в багтрекер и проголосовать за баг. Может его и исправят когда-нибудь.

понедельник, 20 сентября 2010 г.

Получение числа непрочитанных СМС

Отвечал на вопросы на StackOverflow и среди них попался вопрос по теме поста. Как ни странно, в документации этот вопрос не освещён. Путём исследования исходников Андроида нашёл решение, оказалось, что это несложно.


Требуется выполнить простой запрос к SMS ContentProvider. Код будет выглядеть так:



  1. final Uri SMS_INBOX = Uri.parse("content://sms/inbox");
  2.  
  3. Cursor c = getContentResolver().query(SMS_INBOX, null, "read = 0", null, null);
  4. int unreadMessagesCount = c.getCount();
  5. c.deactivate();
* This source code was highlighted with Source Code Highlighter.

Условие прочтения сообщения задаётся в третьей строке параметром "read = 0", для получения числа прочитанных сообщений нужно заменить 0 на 1.

четверг, 16 сентября 2010 г.

Отслеживание изменений в EditText

В компоненте EditText, использующемся для редактирования текста, как нетрудно догадаться, нет методов позволяющих отслеживать изменение текста в поле ввода. Но реализовать этот функционал конечно же возможно.

Для отслеживания изменений в EditText нужно создать класс, реализующий интерфейс TextWatcher. Интерфейс содержит определения методов afterTextChanged, beforeTextChanged, onTextChanged, вызываемых соответственно после изменения текста, перед изменением и собственно во время изменения. Затем этот класс нужно зарегистрировать для отслеживаемого контрола EditText при помощи метода addTextChangedListener().

Рассмотрим на примере. Имеется несколько EditText'ов. Изначально видимым является только один, остальные скрыты. Требуется отслеживать в них изменения и при условии наличия текста в первом, показывать второй контрол, и наоборот, при условии отсутствия текста в первом контроле скрывать второй. Реализуется это несложным кодом:

  private class Watcher implements TextWatcher {
    protected EditText linkedView;
   
    public Watcher(EditText linkedView) {
      this.linkedView = linkedView;
    }
   
    public void afterTextChanged(Editable s) {
      if (s.length() > 0) {
        linkedView.setVisibility(View.VISIBLE);
      } else {
        linkedView.setVisibility(View.GONE);
      }
    }

    public void beforeTextChanged(CharSequence s, int start, int count, int after) { }
    public void onTextChanged(CharSequence s, int start, int before, int count) { }
  };

    participantEdits[0].addTextChangedListener(new Watcher(participantEdits[1]));


* This source code was highlighted with Source Code Highlighter.


Код довольно прост: отлавливаем событие после изменения текста и в зависимости от длины текста скрываем или отображаем привязанный контрол.