Разработка Android приложение 'Я Переводчик'
Автономная
некоммерческая организация профессионального образования
"Балтийский
информационный техникум"
Курсовая
работа
По
дисциплине "Программирование в компьютерных системах"
Разработка
Android
приложение "Я Переводчик"
Подготовил: Студент 3-го курса
группы П-35
Шемягин С.О.
Проверил: Милютина С.Н.
Содержание
Введение
. Техническое задание
. Описание и обоснование
.1 Выбор технологии разработки
приложение
. Разработка основных модулей
приложения
.1 Модуль работы с сервисом перевода
текста
.2 Модуль работы с сервисом словаря
.3 Модуль работы с базой данных
. Разработка основного функционала
Заключение
Список литературы
Введение
Передо мной стояла задача разработать Android
приложение "Я Переводчик" с возможностью онлайн и офлайн перевода
текста, показа словаря, а также возможностью добавление переводов в избранное.
Приложение выступало в качестве тестового
задания для проекта "Яндекс Мобилизация".
Область применения.
Приложение позволяет преодолеть языковой барьер.
Имеет возможность перевода любого текста на 51 доступный язык, включая
"Урду, Хинди, Коса, Каталанский" языки. Может показать словарь с
любыми похожими словами на большинстве языков.
1. Техническое задание
Необходимо создать приложение
для Android на языке Java. Оно должно обладать такой минимальной
функциональностью:
· Поле для ввода
текста, который будет переведён на другой язык; переключатель языка и варианты
перевода, которые появляются, когда пользователь вводит текст в поле.
· Возможность
добавить переведённое слово или предложение в избранное.
· Возможность
просмотра истории переводов.
· Возможность
просмотра избранного.
· Перевод с одного
языка на другой с помощью API Яндекс. Переводчика.
· Чтобы вам было
легче, мы подготовили примерный вид экранов тестового приложения:
Приложение желательно должно иметь:
· общую плавность и
отзывчивость интерфейса, красивую анимацию,
· понятный интерфейс
- чтобы перед использованием приложения не приходилось читать инструкции.
· отсутствие
"падений" и непредусмотренного поведения приложения при выполнении
основных действий
· обработку ошибок,
· кэширование
(например, можно научить приложение сохранять предыдущий ответ сервера),
· комментарии в коде
2.
Описание и обоснование
.1 Выбор технологии
разработки приложение
В данном приложении должный
выполняться сетевые запросы. В качестве библиотеки для сетевых запросов
использовалась библиотека Volley от Google.
перевод приложение экран
Volley
- это библиотека HTTP, которая делает работу в сети для приложений Android
проще, а главное, быстрее.предлагает следующие преимущества:
· Автоматическое
планирование сетевых запросов.
· Несколько
одновременных сетевых подключений.
· Кэширование ответов
на диски и память со стандартной связностью кеша HTTP.
· Поддержка
приоритетов запросов.
· API-запрос отмены.
Вы можете отменить один запрос, или вы можете установить блоки или области
запросов для отмены.
· Простота настройки,
например, для повтора и задержки.
· Сильный порядок,
который упрощает правильное заполнение пользовательского интерфейса данными,
извлекаемыми из сети асинхронно.
· Средства отладки и
трассировки.
Volley
легко интегрируется с любым протоколом и поставляется в комплекте с поддержкой
необработанных строк, изображений и JSON.
Предоставляя встроенную
поддержку необходимых вам функций, Volley освобождает вас от написания кода
шаблона и позволяет сконцентрироваться на логике, характерной для вашего
приложения.
Пример GET
запроса через библиотеку Volley:
RequestQueue queue = Volley.newRequestQueue(context);
/** Новый запрос
*/
queue.cancelAll(new
RequestQueue.RequestFilter() { //Stop all request
@Overrideboolean
apply(Request<?> request) {
return true;
}
}); /** Отмена всех запросов */
String url = String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s"
,apiKey, Uri.encode(text),lang);
/** Создание
URL запроса
*/
Log.d("tran","Request
URL: " + url);stringRequest = new StringRequest(Request.Method.GET,
url,callback,errorCallback);
queue.add(stringRequest); /** Добавление в
очередь */
Разрабатывая приложение под ОС Android
стоит учитывать тот факт, что не все функции могут работать на более старых
версиях системы.
Для решения этой проблемы,
корпорация Google разработала
специальную библиотеку Support
Library
Support Library
- библиотека, которая на старых версиях Android делает доступными возможности
новых версий.
Например, фрагменты появились
только в третьей версии (API Level 11). Если вы хотите использовать их в своем
приложении, это приложение не будет работать на более старых версиях Android,
т.к. эти старые версии никогда не слышали про класс android.app.Fragment. Какие
тут есть выходы?
2)
Можно опустить старые версии и позиционировать свое приложение только для новых
версий. Тогда теряется ощутимая часть потенциальных пользователей вашей программы.
На момент написания этого материала на версии Android ниже третьей сидит 69,7%
пользователей. Ощутимая такая потеря получится - больше, чем две трети!
Конечно, со временем все перейдут на третью и последующие версии, и смогут
использовать ваше приложение. Но к тому времени выйдут новые версии Android с
новыми возможностями, вы их реализуете в своем приложении и, тем самым, снова
отсеете часть пользователей. В общем, вырисовывается постоянная дискриминация
пользователей по версии.
3)
Использовать библиотеку Support Library. Она содержит классы - аналоги новшеств
последних версий, которые будут работать на старых версиях.
Среда разработки
приложения Android
Studio
- это интегрированная среда разработки (IDE)
для работы с платформой Android,
анонсированная 16 мая 2013 года на конференции Google
I/O.
Особенности:
· Расширенный редактор макетов:
WYSIWYG, способность работать с UI компонентами при помощи Drag-and-Drop,
функция предпросмотра макета на нескольких конфигурациях экрана.
· Сборка приложений, основанная на
Gradle.
· Различные виды сборок и генерация
нескольких. apk файлов
· Рефакторинг кода
· Статический анализатор кода (Lint),
позволяющий находить проблемы производительности, несовместимости версий и
другое.
· Встроенный ProGuard и утилита для подписывания
приложений.
· Шаблоны основных макетов и
компонентов Android.
· Поддержка разработки приложений для
Android Wear и Android TV[6].
· Встроенная поддержка Google Cloud
Platform, которая включает в себя интеграцию с сервисами Google Cloud Messaging
и App Engine.
· Android Studio 2.1 поддерживает
Android N Preview SDK, а это значит, что разработчики смогут начать работу по
созданию приложения для новой программной платформы.
· Новая версия Android Studio 2.1
способна работать с обновленным компилятором Jack, а также получила улучшенную
поддержку Java 8 и усовершенствованную функцию Instant Run.
· Platform-tools 23.1.0 для Linux без
объявления стала исключительно 64-разрядной, даже при попытке установить
32-разрядную версию. Иными словами, Android Studio больше НЕ работает (выдаёт
неустранимые ошибки) в 32-разрядных версиях Linux.
· В Android Studio 3.0 будут по
стандарту включены инструменты языка Kotlin основанные на JetBrains IDE
3. Разработка
основных модулей приложения
Для полноценной реализации
переводчика, нужны модули, отвечающие за:
· Модуль работы с
сервисом перевода текста (API
Яндекс Переводчик)
· Модуль работы с
сервисом словаря (API
Яндекс Словарь)
· Модуль работы с
базой данных (SQLite)
3.1 Модуль работы с
сервисом перевода текста
Для перевода текста
используется сервис (API
Яндекс Переводчик).
При переводе текста
отправляется GET или POST
запрос с синтаксисом:
https://translate.yandex.net/api/v1.5/tr.json/translate
? =<API-ключ>
& text=<переводимый текст>
& lang=<направление перевода>
& [format=<формат текста>]
& [options=<опции перевода>]
& [callback=<имя callback-функции>]
Ответ возвращается в формате JSON. Если задан
параметр callback, JSON-объект оборачивается в функцию, с названием, указанным
в этом параметре (JSONP).
В модуле отвечающим за перевод текста имеется
всего один метод.
Метод translate имеющий
аргументы:
1. Text
- Текст
перевода
. Lang - Язык перевода. Пример (ru-en,ru)
. Callback
- Возвращение
результата перевода
. errorCallback
- Возвращение
ошибки перевода
Листинг модуля:class
Translator {final Context context; Translator
(Context context)
//Конструктор класса принимающий контекст приложения
{.context = context;
}
/** Yandex Translator Api KEY
*/static final String apiKey = "trnsl.1.1.20170319T102022Z.3c57ab893ab2ff9d.7790251552d1ad674f87d15327e4175ee8de83da";
/** Языки
перевода
*/final static String[] langsCode = {"en", "ru",
"az", "sq", "am", "ar", "hy",
"af", "eu", "ba", "be", "bn",
"bg", "bs",
"cy", "hu", "vi", "ht", "gl",
"nl", "mrj", "el", "ka",
"gu", "da", "he",
"yi", "id",
"ga", "it", "is", "es", "kk",
"kn", "ca", "ky", "zh", "ko",
"xh", "la",
"lv", "lt",
"lb", "mg", "ms", "ml", "mt",
"mk", "mi", "mr", "mhr",
"mn", "de", "ne",
"no", "pa",
"pap", "fa", "pl", "pt",
"ro", "ceb", "sr", "si",
"sk", "sl", "sw",
"su", "tg",
"th", "tl", "ta", "tt", "te",
"tr", "udm", "uz", "uk",
"ur", "fi", "fr",
"hi", "hr",
"cs", "sv", "gd", "et", "eo",
"jv", "ja"};
/**
* Метод перевода текста
* @param text Текст перевода
* @param lang Язык перевода. Пример (ru-en,ru)
* @param callback Возвращение результата
перевода
* @param errorCallback Возвращение ошибки
перевода
*/void translate(String text,String
lang,Response.Listener<String> callback, Response.ErrorListener
errorCallback) {queue = Volley.newRequestQueue(context); /** Новый
запрос
*/.cancelAll(new RequestQueue.RequestFilter() { //Stop all request
@Overrideboolean
apply(Request<?> request) {
return true;
}
}); /** Отмена всех запросов */
String url =
String.format("https://translate.yandex.net/api/v1.5/tr.json/translate?key=%s&text=%s&lang=%s"
,apiKey, Uri.encode(text),lang); /**
Создание
URL запроса
*/stringRequest = new StringRequest(Request.Method.GET,
url,callback,errorCallback);
queue.add(stringRequest); /** Добавление в
очередь */
}
}
.2 Модуль работы с
сервисом словаря
Для получения словаря
используется сервис (API
Яндекс Словарь).
При словарном запросе
отправляется GET или POST
запрос с синтаксисом:
https://dictionary.yandex.net/api/v1/dicservice/lookup?key=<API-ключ>
& text=<переводимый текст>
Параметр
|
Тип
|
Описание
|
Обязательные
|
key
|
string
|
API-ключ.
Получите бесплатный API-ключ на этой странице.
|
lang
|
string
|
Направление
перевода (например, "en-ru"). Задается в виде пары кодов языков,
перечисленных через дефис. Например, "en-ru" задает перевод с
английского на русский. Совет. Сервис работает не только с переводными
словарями. Например, вы можете указать направление "ru-ru" или
"en-en" и получить все возможные значения искомого слова на русском
или английском языке.
|
text
|
string
|
Слово
или фраза, которые требуется найти в словаре.
|
Необязательные
|
ui
|
string
|
Язык
интерфейса пользователя, на котором будут отображаться названия частей речи в
словарной статье. Возможные значения: · en
- английский; · ru -
русский; · uk -
украинский; · tr -
турецкий.
|
flags
|
int
|
Опции
поиска (битовая маска флагов). Возможные значения: · FAMILY = 0x0001 - применить
семейный фильтр; · SHORT_POS
= 0x0002 - отображать названия частей речи в краткой форме; · MORPHO = 0x0004 - включает
поиск по форме слова; ·
POS_FILTER
= 0x0008 - включает фильтр, требующий соответствия частей речи искомого слова
и перевода.
|
В модуле, отвечающем за словарь, имеются методы:
· getWords
· conCat
· setClickWord
· getDictionarySpannableString
Основным методом здесь является getWords. Он
отвечает за получения словаря к тексту.
Имеет аргументы:
1. Text
- Текст
перевода
. Lang - Язык перевода. Пример (ru)
. Callback
- Возвращение
результата перевода
. errorCallback
- Возвращение
ошибки перевода
Листинг:
/**
* Метод получения словаря
* @param text Текст/слово
* @param lang Язык словаря. Пример (en-ru)
* @param callback Результат получения словаря
* @param errorCallback Ошибка получения словаря
*/void getWords(String text, String
lang, Response.Listener<String> callback, Response.ErrorListener
errorCallback) {queue = Volley.newRequestQueue(context); /** Новый
запрос
*/.cancelAll(new RequestQueue.RequestFilter() { //Stop all request
@Overrideboolean
apply(Request<?> request) {
return true;
}
}); /** Отмена всех запросов */
String url =
String.format("https://dictionary.yandex.net/api/v1/dicservice.json/lookup?key=%s&lang=%s&text=%s&ui=ru"
,apiKey,Uri.encode(lang),
Uri.encode(text)); /** Создание
URL запроса
*/stringRequest = new StringRequest(Request.Method.GET, url,callback,errorCallback);
queue.add(stringRequest); /** Добавление в
очередь */
}
3.3 Модуль работы с базой данных
История переводов, избранные
переводы, а также оффлайн переводы должны где-то храниться. Самое верное для
этого решение, хранить все это в базе данных.
База данных в Android
представлена в виде SQLite.Для
удобной работы с БД был написан модуль, имеющий методы:
· reset () - Метод
очистки БД
· insert() - Метод
помещающий результат перевода в БД
· setIsFavorite() -
Метод добавляющий/убирающий в избранное перевод
· getHistory() -
Метод возвращающий историю всех переводов.
· getTranslate() -
Метод возвращающий перевод для слова/предложения (Оффлайн переводчик)
· dbCount() - Метод
возвращающий кол-во строк в БД
Листинг основных методов:
/**
* Метод помещающий результат перевода в БД
* @param result Результат перевода в виде
TranslateResultModel
* */void insert(TranslateResultModel
result)
{dataBase = getWritableDatabase();
/** Открывает
экземпляр
базы
данных
*/contentValues = new ContentValues(); /** Формирую
сроку
*/.put(FROM_TEXT,result.from);.put(TO_TEXT,result.to);.put(LANG,result.lang);.put(IS_FAVORITE,(result.favorite)
? 1 : 0);.insert(TABLE_RESULTS,null,contentValues); /** Добавляю
в
бд
*/.close();
}
/**
* Метод добавляющий/убирающий в
избранное перевод
* @param
id ID
результата перевода в БД
* @param state
Значение
* */void
setIsFavorite(int id, boolean state)
{dataBase =
getWritableDatabase();c = dataBase.query(TABLE_RESULTS, null,"_id = "
+ id,null,null,null,null,null);(c.moveToFirst()) {{contentValues = new ContentValues();idFrom
=c.getColumnIndex(FROM_TEXT);idTo = c.getColumnIndex(TO_TEXT);idLang =
c.getColumnIndex(LANG);.put(FROM_TEXT,c.getString(idFrom));.put(TO_TEXT,c.getString(idTo));.put(LANG,c.getString(idLang));.put(IS_FAVORITE,(state)
? 1 : 0);
/** Обновляю БД
*/.update(TABLE_RESULTS,contentValues,"_id = " + id,null);
while
(c.moveToNext());
}
}
/**
* Метод возвращающий историю
всех переводов.
* @param
text Текст перевода.
Может отсутствовать, но тогда будет возвращены все значения
* @param favorite В
избранном
*
*/ArrayList<TranslateResultModel> getHistory(String text, boolean
favorite)
{<TranslateResultModel>
results = new ArrayList<>();dataBase = getReadableDatabase();c =
null;filter = '%' + text + '%';(favorite) {(TextUtils.isEmpty(text))= dataBase.query(TABLE_RESULTS,
null, "_favorite=1", null, null, null, null, null);=
dataBase.query(TABLE_RESULTS, null, "_from LIKE (?) OR _to LIKE (?) AND
_favorite=1"
, new
String[]{filter,filter}, null, null, null, null);
}{(TextUtils.isEmpty(text))=
dataBase.query(TABLE_RESULTS, null, null, null, null, null, null, null);=
dataBase.query(TABLE_RESULTS, null, "_from LIKE (?) or _to LIKE (?)"
, new
String[]{filter,filter}, null, null, null, null);
}(c.moveToLast())
{{idFrom =c.getColumnIndex(FROM_TEXT);idTo = c.getColumnIndex(TO_TEXT);idLang =
c.getColumnIndex(LANG);idFavorite = c.getColumnIndex(IS_FAVORITE);idID =
c.getColumnIndex(KEY_ID);.add(new
TranslateResultModel(c.getString(idFrom),c.getString(idTo),.getString(idLang),(c.getInt(idFavorite)
== 1),c.getInt(idID)));
}(c.moveToPrevious());
}.close();
results;
}
/**
* Метод возвращающий перевод
для слова/предложения (Оффлайн переводчик)
* @param
text Текст перевода.
* @param
lang Язык перевода
*
*/ArrayList<TranslateResultModel> getTranslate(String text, String lang)
{<TranslateResultModel>
results = new ArrayList<>();dataBase = getReadableDatabase(); //Открывает
экземпляр базы данныхc = null;= dataBase.query(TABLE_RESULTS,
null,"_lang=\"" + lang + "\" and _from=\"" +
text + "\""
, null, null, null,
null, null);(c.moveToFirst()) {{idFrom =c.getColumnIndex(FROM_TEXT);idTo =
c.getColumnIndex(TO_TEXT);idLang = c.getColumnIndex(LANG);idFavorite =
c.getColumnIndex(IS_FAVORITE);idID = c.getColumnIndex(KEY_ID);.add(new
TranslateResultModel(c.getString(idFrom),c.getString(idTo),.getString(idLang),(c.getInt(idFavorite)
== 1),c.getInt(idID)));
}(c.moveToNext());
}.close();
results;
}
4. Разработка
основного функционала
Основной функционал приложение
разбит на 3 составляющие.
. Переводчик текста
. История передов и
избранные переводы
. Настройки переводов
Каждое окно приложение сделано
в виде отдельного фрагмента переключение между которыми происходит по средствам
свайпа либо же нажатиями клавиш.
Фрагмент
(класс Fragment) - представляет поведение или часть пользовательского интерфейса
в операции (класс Activity). Разработчик может объединить несколько фрагментов
в одну операцию для построения многопанельного пользовательского интерфейса и
повторного использования фрагмента в нескольких операциях. Фрагмент можно
рассматривать как модульную часть операции. Такая часть имеет свой жизненный
цикл и самостоятельно обрабатывает события ввода. Кроме того, ее можно добавить
или удалить непосредственно во время выполнения операции. Это нечто вроде
вложенной операции, которую можно многократно использовать в различных
операциях.
Листинг фрагмента
перевода текста:
* Метод перевода текста с последующим
отображением
* @param text Текст для перевода
* @param fromLang С какого языка перевод
* @param toLang На какой язык перевод
* @param isDictionaryWord Нужно ли заменить
текст в поле ввода
* */void translate(final String
text, final String fromLang, final String toLang, boolean isDictionaryWord)
{
/** Нужно
ли
показывать
словарь
*/boolean showDictionary = getPreferences().getBoolean("showDictionary",true);
/** Офлайн
перевод
*/boolean offlineTranslate =
getPreferences().getBoolean("offlineTranslate",true);
/** Проверка текста перевода на пустату
*/(TextUtils.isEmpty(text)) {
/** Скрываю frame с результатом перевода и
словарем */
dictionatyResultFrame.setVisibility(View.GONE);.setVisibility(View.GONE);;
}
/** Язык
перевода
*/String translateLang = fromLang + "-" + toLang;
/** Замена текста в поле ввода */
if(isDictionaryWord)
{.removeTextChangedListener(editTextWatcher);.setTextKeepState(text);.addTextChangedListener(editTextWatcher);.setVisibility((text.length()
> 0) ? View.VISIBLE : View.INVISIBLE);
}
/** Смена
языков
перевода
spinners
*/.setOnItemSelectedListener(null);.setOnItemSelectedListener(null);.setSelection(Arrays.asList(Translator.langsCode).indexOf(fromLang),false);.setSelection(Arrays.asList(Translator.langsCode).indexOf(toLang),false);.setOnItemSelectedListener(onSpinnerChanged);.setOnItemSelectedListener(onSpinnerChanged);
/** Скрываю frame с результатом перевода и
словарем */
dictionatyResultFrame.setVisibility(View.GONE);.setVisibility(View.GONE);
/** Включаю
ProgressBar */.setVisibility(View.VISIBLE);
/** Офлайн перевод */(offlineTranslate) {
/** Проверяем в БД перевод такого текста и языка
*/
ArrayList<TranslateResultModel>
dbTranslate = dataBaseHelper.getTranslate(text, translateLang);
/** Если пеервод встечается, то выводим и делаем
запрос на словарь
* Словарь в БД не хранится
* */
if (dbTranslate.size() != 0)
{.setVisibility(View.GONE);.setVisibility(View.VISIBLE);.setText(dbTranslate.get(0).to);.startAnimation(AnimationUtils.loadAnimation(getContext(),
R.anim.move));(showDictionary)(text, fromLang, toLang);;
}
}
/** Онлайн
перевод
*/.translate(text, translateLang, new Response.Listener<String>() {
@Overridevoid onResponse(String
response) {{
/** Вытаксиваем
результат
перевода
*/jObject = new JSONObject(response);jArray =
jObject.getJSONArray("text");String translatedText =
jArray.getString(0);String origText = text;
/** Добавляю
в
БД
результат
пеервода
*/.insert(new TranslateResultModel(origText,translatedText,translateLang,false));
/** Обновляю
историю
переводов
*/
/** Включаю
фреймы
*/.setVisibility(View.VISIBLE);.setVisibility(View.GONE);
/** Ставлю
текст
перевода
*/.setText(translatedText);.startAnimation(AnimationUtils.loadAnimation(getContext(),R.anim.move));(showDictionary)(text,fromLang,toLang);
} catch (JSONException e)
{.printStackTrace();
}
}
}, new Response.ErrorListener() {
@Overridevoid
onErrorResponse(VolleyError error) {
/** В
случае
ошибки
ответа
*/(error.networkResponse !=
null).setText(getResources().getString(R.string.failedTranslateText)
+ "\n" +
getResources().getString(R.string.errorCode)
+ error.networkResponse.statusCode);.setText(getResources().getString(R.string.failedTranslateText)
+ "\n" +
getResources().getString(R.string.checkInternet));.setVisibility(View.GONE);.setVisibility(View.VISIBLE);.startAnimation(AnimationUtils.loadAnimation(getContext(),R.anim.move));
}
});
}
/**
* Метод получения словаря, с последующим
отображением
* @param
text Текст для перевода
* @param
fromLang С какого языка
перевод
* @param
toLang На какой язык
перевод
* */void dictionary(final String
text, final String fromLang, final String toLang)
{
/** Язык
перевода
*/String translateLang = fromLang + "-" + toLang;
/** Скрываю
фрейм
словаря
*/.setVisibility(View.GONE);
/** Запрос
к
словарю
*/.getWords(text, translateLang, new Response.Listener<String>() {
@Overridevoid onResponse(String
response) {
/** Создание SpannableString
* Слова будут окрашены и начнут нажиматься
* */dict =
dictionary.getDictionarySpannableString(response,fromLang,toLang);
/** Проверка
на
пустую
строку
*/(!TextUtils.isEmpty(dict.toString())) {.setVisibility(View.VISIBLE);.setText(dict);.startAnimation(AnimationUtils.loadAnimation(getContext(),
R.anim.move));
}
}
}, new Response.ErrorListener() {
@Overridevoid
onErrorResponse(VolleyError error) {
/** Ошибки
словаря
не
выводятся
*/
}
});
}
@OverrideView onCreateView(final
LayoutInflater inflater, ViewGroup container,savedInstanceState) {rootView =
inflater.inflate(R.layout.translator_main, container, false);
((MainActivity)getActivity()).translatorFragment
= this;= ((MainActivity)getActivity()).getTranslator();=
((MainActivity)getActivity()).getDictionary();= (Spinner)
rootView.findViewById(R.id.spinnerFromLang);= (Spinner)
rootView.findViewById(R.id.spinnerToLang);=
(TextView)rootView.findViewById(R.id.translatedText);=
(TextView)rootView.findViewById(R.id.dictionaryText);.setMovementMethod(LinkMovementMethod.getInstance());=
(FrameLayout) rootView.findViewById(R.id.translateResult);= (FrameLayout)
rootView.findViewById(R.id.dictionaryResult);= (ProgressBar)
rootView.findViewById(R.id.translateProgressBar);translatedByYandex =
(TextView)rootView.findViewById(R.id.translatedByYandex);.setText(Html.fromHtml(getResources().getString(R.string.translatedByYandex)));.setMovementMethod(LinkMovementMethod.getInstance());=
(ImageButton) rootView.findViewById(R.id.switchLang);= (ImageButton)
rootView.findViewById(R.id.clearText);openFullscreen = (ImageButton)
rootView.findViewById(R.id.openFullscreen);.setOnClickListener(new
View.OnClickListener() {
@Overridevoid onClick(View v)
{intent = new Intent(getContext(),
TextReaderActivity.class);.putExtra("text",translateText.getText().toString());(intent);
}
});
/** Листеер
на
очистку
поля
ввода
*/.setOnClickListener(new View.OnClickListener() {
@Overridevoid onClick(View v) {.setText("");
}
});
/** Листеер на смену языков местами */
switchLang.setOnClickListener(new
View.OnClickListener() {
@Overridevoid onClick(View v) {
/** Анимации
*/.setRotation(0);.animate().rotation(180).setDuration(500);.animate().alpha(0).setDuration(300);.animate().alpha(0).setDuration(300);
}
});=
(EditText)rootView.findViewById(R.id.editText);
/** TextWatcher */= new
TextWatcher() {
@Override public void
onTextChanged(CharSequence s, int start, int before, int count) {
/** Включаем скопку очистки поля если поле не
пустое */
clearText.setVisibility((s.length()
> 0) ? View.VISIBLE : View.INVISIBLE);
}
@Override public void
beforeTextChanged(CharSequence s, int start, int count, int after) { }
/** Наймер на задержку после ввода текста
* Лучше наверно сделать через Handler */
private Timer timer=new Timer();
/** Время через которое начнется перевод текста,
после окончания ввода */
private final long DELAY = 1000;
@Overridevoid afterTextChanged(final
Editable s) {(s.toString().trim().length()>0) {.cancel();= new
Timer();.schedule(TimerTask() {
@Overridevoid run() {
/** В UI
потоке вызываем метод перевода текста */
getActivity().runOnUiThread(new
Runnable() {
@Overridevoid run()
{(editText.getText().toString(),.langsCode[sFirst.getSelectedItemPosition()],.langsCode[sSecond.getSelectedItemPosition()],false);
}
});
},
);
}
}
};
/** Додавляем
листенер
*/.addTextChangedListener(editTextWatcher);<CharSequence> adapter =
ArrayAdapter.createFromResource((), R.array.langs,
R.layout.spinner_lang_item);.setAdapter(adapter);.setAdapter(adapter);= new
AdapterView.OnItemSelectedListener() {
@Overridevoid
onItemSelected(AdapterView<?> parent, View view, int position, long id)
{(editText.getText().toString(),.langsCode[sFirst.getSelectedItemPosition()],.langsCode[sSecond.getSelectedItemPosition()],false);
}
@Overridevoid
onNothingSelected(AdapterView<?> parent) {}
});
/** Установка
начальных
языков
перевода
*/sysLang = Locale.getDefault().getLanguage();(sysLang)
{"en":.setSelection(Arrays.asList(Translator.langsCode).indexOf("en"));.setSelection(Arrays.asList(Translator.langsCode).indexOf("ru"));;"ru":.setSelection(Arrays.asList(Translator.langsCode).indexOf("ru"));.setSelection(Arrays.asList(Translator.langsCode).indexOf("en"));;:.setSelection(Arrays.asList(Translator.langsCode).indexOf("auto"));.setSelection(Arrays.asList(Translator.langsCode).indexOf("en"));;
}
return
rootView;
}
}
Листинг фрагмента с историей и
избранными переводами:
public static HistoryFragment
newInstance() {new HistoryFragment();
}
@OverrideView
onCreateView(LayoutInflater inflater, ViewGroup container,savedInstanceState)
{rootView = inflater.inflate(R.layout.history_main, container, false);=
((MainActivity)getActivity()).getDbHelper();
((MainActivity)getActivity()).historyFragment
= this;= (LinearLayout) rootView.findViewById(R.id.noTranslateHistory);=
(TextView) rootView.findViewById(R.id.noTranslateHistoryText);= (ImageButton)
rootView.findViewById(R.id.clearHistory);
/** Вкладки для переключения межно историей и
избранным */
mTabLayout = (TabLayout)
rootView.findViewById(R.id.historyTab);.addTab(mTabLayout.newTab().setText(R.string.history));.addTab(mTabLayout.newTab().setText(R.string.favorite));
/** Листенер на смену вкладок
*/.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Overridevoid
onTabSelected(TabLayout.Tab tab) {
/** Устанавливаю текст с SearchView
* Просто мелочь...
* */(tab.getPosition())
{0:.setQueryHint(getResources().getString(R.string.searchInHistory));;1:.setQueryHint(getResources().getString(R.string.searchInFavorite));;:lv
= (ListView)rootView.findViewById(R.id.searchList);= new
HistoryArrayAdapter(getContext());.setAdapter(adapter);=
(SearchView)rootView.findViewById(R.id.searchView);
/** Начальное обновления списка */
updateHistoryList();
return
rootView;
}void updateHistoryList()
{
/** Очищаю
список*/.clear();
/** Добавляю в список значения из БД */
adapter.addAll(dbHelper.getHistory(searchView.getQuery().toString(),
(mTabLayout.getSelectedTabPosition()
== 1)));
/** Обновляю в UI*/.notifyDataSetChanged();
/** Если в БД есть значения, то включаю кнопку
очистки истории */
clearHistory.setVisibility((dbHelper.dbCount()
> 0) ? View.VISIBLE : View.GONE);
/** Если есть элементы в БД */
if(adapter.getCount() >
0).setVisibility(View.GONE);
{.setVisibility(View.VISIBLE);.setText((mTabLayout.getSelectedTabPosition()
== 0) ?().getString(R.string.noTranslateHistory)
:().getString(R.string.noFavorites));
}
Заключение
Мною было разработано полноценное приложение в
точности по ТЗ имеющее полный функционал переводчика включая:
. Онлайн/оффлайн перевод текста
. Показа словаря
. История и избранные переводы
В качестве референса для дизайна использовалось
официальное приложение Yandex
Переводчик.
Также использовались технологии API
Yandex Translate
и API Yandex
Dictionary через которые был
реализован перевод текста и показ словаря.
Для сетевых запросов использовалась библиотека Volley.
Поддержка старых версий ОС Android
реализована через библиотеку Support
Library
Список литературы
1. IDE Android Studio
-https://ru.wikipedia.org/wiki/Android_Studio
2. Сервис перевода текста API
Yandex Translate
- https://tech.yandex.ru/translate/
3. Yandex Mobilization -
https://academy.yandex.ru/events/mobdev/msk-2017/
4. Сервис
словаря
API Yandex Dictionary - https://tech.yandex.ru/dictionary/
5. Библиотека сетевых запросов Volley
- https://developer.android.com/training/volley/index.html
. Фрагменты в ОС Android
- https://developer.android.com/guide/components/fragments.html?hl=ru