Главная страница
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
qrcode

Программирование под Android. Для профессионалов


Скачать 19.35 Mb.
НазваниеПрограммирование под Android. Для профессионалов
АнкорBrayn Khardi Bill Fillips - Programmirovanie po.
Дата23.05.2017
Размер19.35 Mb.
Формат файлаpdf
Имя файлаBrayn_Khardi_Bill_Fillips_-_Programmirovanie_po.pdf
оригинальный pdf просмотр
ТипДокументы
#21061
страница48 из 55
КаталогОбразовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей
1   ...   44   45   46   47   48   49   50   51   ...   55
Глава 31. Просмотр веб-страниц и WebView
Листинг 31.4 (продолжение)
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_photo_page, parent, false);
mWebView = (WebView)v.findViewById(R.id.webView);
return v;
}
}
Пока это всего лишь заготовка — вскоре мы заполним ее кодом. А пока создайте класс-контейнер
PhotoPageActivity на основе хорошо знакомого класса
Single-
FragmentActivity
Листинг 31.5. Создание веб-активности (PhotoPageActivity.java)
package com.bignerdranch.android.photogallery;
public class PhotoPageActivity extends SingleFragmentActivity {
@Override
public Fragment createFragment() {
return new PhotoPageFragment();
}
}
Измените код
PhotoGalleryFragment
, чтобы вместо неявного интента происходило обращение к новой активности.
Листинг 31.6. Переключение на обращение к новой активности (PhotoGalleryFragment.java)
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mGridView.setOnItemClickListener(new OnItemClickListener() {
@Override public void onItemClick(AdapterView gridView, View view, int pos,
long id) {
GalleryItem item = mItems.get(pos);
Uri photoPageUri = Uri.parse(item.getPhotoPageUrl());
Intent i = new Intent(Intent.ACTION_VIEW, photoPageUri);
Intent i = new Intent(getActivity(), PhotoPageActivity.class);
i.setData(photoPageUri);
startActivity(i);
}
});
return v;
}
Наконец, добавьте новую активность в манифест.

Простой способ: неявные интенты
513
Листинг 31.7. Добавление активности в манифест (AndroidManifest.xml)
package="com.bignerdranch.android.photogallery"
android:versionCode="1"
android:versionName="1.0" >
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
android:launchMode="singleTop"
android:label="@string/title_activity_photo_gallery" >


android:name=".PhotoPageActivity" />





Запустите приложение PhotoGallery и нажмите на фотографии. На экране появ- ляется новая пустая активность.
Возьмемся за дело и заставим наш фрагмент делать что-то полезное. Чтобы виджет
WebView успешно отображал страницу фотографии на сайте Flickr, необходимо выполнить три условия. Первое условие очевидно — нужно сообщить ему, какой
URL-адрес необходимо загрузить.
Второе условие — необходимо включить поддержку JavaScript. По умолчанию она отключена. Постоянно держать ее включенной не обязательно, но для Flickr она нужна. Android Lint выдает предупреждение (из-за потенциальной опасности меж- сайтовых сценарных атак), так что предупреждения Lint тоже нужно отключить.
Наконец, необходимо переопределить в классе
WebViewClient один метод с именем shouldOverrideUrlLoading(WebView,String)
и вернуть false
. Мы рассмотрим этот класс после того, как вы введете код.
Листинг 31.8. Добавление новых переменных экземпляров (PhotoPageFragment.java)
@SuppressLint("SetJavaScriptEnabled")
@Override public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_photo_page, parent, false);
mWebView = (WebView)v.findViewById(R.id.webView);
продолжение


514
Глава 31. Просмотр веб-страниц и WebView
Листинг 31.8 (продолжение)
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
return false;
}
});
mWebView.loadUrl(mUrl);
return v;
}
Загрузка данных с URL-адреса должна происходить после настройки
WebView
, по- этому она выполняется в последнюю очередь. До этого мы включаем JavaScript, вызывая getSettings()
для получения экземпляра
WebSettings
, с последующим вызовом
WebSettings.setJavaScriptEnabled(true)
. Объект
WebSettings
— первый из трех механизмов настройки
WebView
. Он содержит различные свойства, которые можно задать в коде — например, строку пользовательского агента и размер текста.
Далее выполняется настройка
WebViewClient
WebViewClient представляет собой событийный интерфейс. Предоставляя собственную реализацию
WebViewClient
, вы можете реагировать на события вывода. Например, можно определить, когда ядро визуализации начинает загрузку изображения с конкретного URL-адреса, или решить, стоит ли заново отправить серверу POST-запрос.
WebViewClient содержит много методов, которые можно переопределить; большин- ство этих методов нам не понадобится. Однако мы должны заменить стандартную реализацию shouldOverrideUrlLoading(WebView,String)
из
WebViewClient
. Этот метод указывает, что должно происходить при загрузке нового URL-адреса в
WebView
(например, при нажатии на ссылке). Если он возвращает true
, это означает: «Не об- рабатывать этот URL-адрес, я обрабатываю его сам». Если он возвращает false
, вы говорите: «Давай,
WebView
, загружай данные с URL-адреса, я с ним ничего не делаю».
Реализация по умолчанию инициирует неявный интент с URL, по аналогии с тем, как это делалось ранее в этой главе. Для страницы с фотографией это создает се- рьезные проблемы, потому что Flickr первым делом выполняет перенаправление на мобильную версию сайта. Для
WebViewClient это означает немедленное пере- ключение на браузер по умолчанию; совсем не то, что нам нужно.
Проблема решается просто — переопределите реализацию по умолчанию, чтобы она возвращала false
Запустите приложение PhotoGallery, и вы увидите
WebView на экране.
Класс WebChromeClient
Раз уж мы занялись созданием собственной реализации
WebView
, давайте немного украсим ее, добавив представление заголовка и индикатор прогресса. Откройте файл fragment_photo_page.xml и внесите следующие изменения.

Простой способ: неявные интенты
515
Рис. 31.2. Добавление заголовка и индикатора прогресса (fragment_photo_page.xml)
Добавить
ProgressBar и
TextView несложно, но чтобы подключить их, нам пона- добится вторая точка обратного вызова
WebView
:
WebChromeClient
. Если
WebView-
Client определяет интерфейс обработки событий визуализации,
WebChromeClient определяет событийный интерфейс обработки событий, которые должны изменять элементы «хрома» (chrome) в браузере. К этой категории относятся сигналы (alerts)
JavaScript, значки сайтов favicon, обновления прогресса загрузки и т. д.
Подключите его в методе onCreateView(…)

516
Глава 31. Просмотр веб-страниц и WebView
Листинг 31.9. Использование WebChromeClient (PhotoPageFragment.java)
@SuppressLint("SetJavaScriptEnabled")
@Override public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_photo_page, parent, false);
final ProgressBar progressBar = (ProgressBar)v.findViewById(R.id.progressBar);
progressBar.setMax(100); // значения в диапазоне 0-100
final TextView titleTextView = (TextView)v.findViewById(R.id.titleTextView);
mWebView = (WebView)v.findViewById(R.id.webView);
mWebView.getSettings().setJavaScriptEnabled(true);
mWebView.setWebViewClient(new WebViewClient() {
});
mWebView.setWebChromeClient(new WebChromeClient() {
public void onProgressChanged(WebView webView, int progress) {
if (progress == 100) {
progressBar.setVisibility(View.INVISIBLE);
} else {
progressBar.setVisibility(View.VISIBLE);
progressBar.setProgress(progress);
}
}
public void onReceivedTitle(WebView webView, String title) {
titleTextView.setText(title);
}
});
mWebView.loadUrl(mUrl);
return v;
}
Обновления индикатора прогресса и заголовка имеют собственные методы об- ратного вызова, onProgressChanged(WebView,int)
и onReceivedTitle(WebView,
String)
. Информация о прогрессе, получаемая от onProgressChanged(WebView,int)
, представляет собой целое число от 0 до 100. Если результат равен 100, значит, за- грузка страницы завершена, поэтому мы скрываем
ProgressBar
, задавая режим
View.INVISIBLE
Запустите приложение PhotoGallery и протестируйте внесенные изменения.
Повороты в WebView
Попробуйте повернуть экран. Хотя приложение работает правильно, вы замети- те, что
WebView полностью перезагружает веб-страницу. Дело в том, что у
WebView слишком много данных, чтобы сохранить их все в onSaveInstanceState(…)
, и их

Для любознательных: внедрение объектов JavaScript
517
приходится создавать «с нуля» каждый раз, когда их приходится создавать заново при повороте.
Для таких классов (другой пример —
VideoView
) документация Android рекомендует позволить активности самой обработать все изменения конфигурации. Это означает, что вместо уничтожения активности она просто перемещает свои представления для размещения по новым размерам экрана. В результате
WebView не приходится заново загружать свои данные.
(Почему бы не делать так всегда, спросите вы? Такое решение не всегда работает правильно с любыми представлениями. Иначе жизнь разработчика была бы на- много проще, но… увы.)
Чтобы заставить класс
PhotoPageActivity обрабатывать свои изменения конфигу- рации, внесите следующее изменения в
AndroidManifest.xml
Листинг 31.10. Самостоятельный обработчик изменений конфигурации (AndroidManifest.xml)
package="com.bignerdranch.android.photogallery"
android:versionCode="1"
android:versionName="1.0" >
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
android:configChanges="keyboardHidden|orientation|screenSize" />


Атрибут сообщает, что в случае изменения конфигурации из-за открытия или за- крытия клавиатуры, изменения ориентации или размеров экрана (которое также происходит при переключении между книжной и альбомной ориентацией в An- droid после версии 3.2) активность должна обрабатывать изменения самостоятельно.
Вот и все. Попробуйте снова повернуть устройство; на этот раз все должно быть в ажуре.
Для любознательных: внедрение
объектов JavaScript
Вы уже видели, как следует использовать
WebViewClient и
WebChromeClient для обработки некоторых событий, происходящих в
WebView
. Однако еще больше воз- можностей открывает внедрение произвольных объектов JavaScript в документ,

518
Глава 31. Просмотр веб-страниц и WebView содержащийся в виджете
WebView
. Откройте документацию по адресу https://
developer.android.com/reference/android/webkit/WebView.html
и прокрутите до описания метода addJavascriptInterface(Object,String)
. Этот метод позволяет внедрить произвольный объект в документ с заданным именем.
mWebView.addJavascriptInterface(new Object() {
public void send(String message) {
Log.i(TAG, "Received message: " + message);
}
}, "androidObject");
После этого объект используется следующим образом:


Такое решение весьма рискованно — фактически вы разрешаете потенциально небезопасной веб-странице вмешиваться в работу вашей программы. Следователь- но, его стоит применять только для принадлежащей вам разметки HTML — или ограничиться предоставлением в высшей степени консервативного интерфейса.

Пользовательские
представления и события
касания
В этой главе мы займемся обработкой событий касания. Для этого мы создадим субкласс
View с именем
BoxDrawingView
. На этом представлении пользователь рисует прямоугольники, прикасаясь к экрану и перемещая палец.
Рис. 32.1. Прямоугольники разных форм и размеров
32

520
Глава 32. Пользовательские представления и события касания
Создание проекта DragAndDraw
Класс
BoxDrawingView занимает центральное место в новом проекте DragAndDraw.
Выполните команду
New

Android
Application
Project
. Задайте параметры проекта, как показано на рис. 32.2, и создайте пустую активность с именем
DragAndDrawActivity
Рис. 32.2. Создание проекта DragAndDraw
Создание класса DragAndDrawActivity
Класс
DragAndDrawActivity представляет собой субкласс
SingleFragmentActiv- ity
, который заполняет обычный макет с одним фрагментом. На панели
Package
Explorer скопируйте файл
SingleFragmentActivity.java в пакет com.bignerdranch.android.
draganddraw
. Затем скопируйте файл activity_fragment.xml в каталог res/layout проекта
DragAndDraw.
В файле
DragAndDrawActivity.java объявите
DragAndDrawActivity субклассом
Single-
FragmentActivity
. Этот класс должен создавать экземпляр
DragAndDrawFragment
(класс, который будет создан следующим).
Листинг 32.1. Изменение активности (DragAndDrawActivity.java)
public class DragAndDrawActivity extends Activity SingleFragmentActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drag_and_draw);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_drag_and_draw, menu);
return true;
}

Создание проекта DragAndDraw
521
@Override
public Fragment createFragment() {
return new DragAndDrawFragment();
}
}
Создание класса DragAndDrawFragment
Чтобы подготовить макет
DragAndDrawFragment
, переименуйте файл activity_drag_
and_draw.xml в fragment_drag_and_draw.xml
Макет
DragAndDrawFragment в конечном итоге будет состоять из
BoxDrawingView
— пользовательского представления, которое мы собираемся написать. Весь графи- ческий вывод и обработка событий касания будут реализованы в
BoxDrawingView
Создайте новый класс с именем
DragAndDrawFragment и назначьте его суперклассом android.support.v4.app.ListFragment
. Переопределите метод onCreateView(…)
, чтобы он заполнял макет fragment_drag_and_draw.xml
Листинг 32.2. Создание фрагмента (DragAndDrawFragment.java)
public class DragAndDrawFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup parent,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_drag_and_draw, parent, false);
return v;
}
}
Запустите приложение DragAndDraw и убедитесь в том, что настройка была вы- полнена правильно.
Рис. 32.3. DragAndDraw с макетом по умолчанию

522
Глава 32. Пользовательские представления и события касания
Создание нестандартного представления
Android предоставляет много превосходных стандартных представлений и вид- жетов, но иногда требуется создать нестандартное представление с визуальным оформлением, полностью уникальным для вашего приложения.
Все многообразие нестандартных представлений можно условно разделить на две общие категории:

простые представления
— простое представление может быть устроено до- статочно сложно; «простым» оно называется только потому, что не имеет до- черних представлений. Простое представление почти всегда также выполняет нестандартную прорисовку;

составные представления
— состоят из других объектов представлений. Со- ставные представления обычно управляют дочерними представлениями, но не занимаются своей прорисовкой. Вместо этого каждому дочернему представле- нию делегируется своя часть работы по прорисовке.
Создание нестандартного представления состоит из трех шагов:

Выбор суперкласса. Для простого нестандартного представления
View предо- ставляет пустой «холст» для рисования, поэтому этот выбор является наиболее распространенным. Для составных нестандартных представлений выберите подходящий класс макета.

Субклассируйте выбранный класс и переопределите как минимум один кон- структор из суперкласса или создайте собственный конструктор, вызывающий один из конструкторов суперкласса.

Переопределите другие ключевые методы для настройки поведения.
Создание класса BoxDrawingView
Класс
BoxDrawingView относится к категории простых представлений и является прямым субклассом
View
Создайте новый класс с именем
BoxDrawingView и назначьте
View его суперклассом.
Добавьте в файл
BoxDrawingView.java два конструктора.
Листинг 32.3. Исходная реализация BoxDrawingView (BoxDrawingView.java)
public class BoxDrawingView extends View {
// Используется при создании представления в коде
public BoxDrawingView(Context context) {
this(context, null);
}
// Используется при заполнении представления по разметке XML
public BoxDrawingView(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
Два конструктора нужны потому, что экземпляр представления может создаваться как в коде, так и по файлу разметки. Представления, созданные на базе файла макета,

Создание нестандартного представления
523
получают экземпляр
AttributeSet с атрибутами XML, заданными в XML. Даже если вы не собираетесь использовать оба конструктора, их рекомендуется включить.
Затем обновите файл макета fragment_drag_and_draw.xml
, чтобы в нем использовалось новое представление.
Листинг 32.4. Включение Add BoxDrawingView в макет (fragment_drag_and_draw.xml)

xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>

android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="@string/hello_world" />


xmlns:android="https://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Рис. 32.4. BoxDrawingView без прямоугольников

524
1   ...   44   45   46   47   48   49   50   51   ...   55

перейти в каталог файлов

Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей

Образовательный портал Как узнать результаты егэ Стихи про летний лагерь 3агадки для детей