Время на прочтение
20 мин
Количество просмотров 26K
Здравствуйте, уважаемые Хабровчане! Вы видели немало постов на тему разработки под android. В данном посте я попытаюсь наиболее подробно изложить свой небольшой опыт разработки под эту ОС.
Небольшое вступление
Проанализировав маркет я понял, что на нем очень много игр, развлекательных и социальных приложений. По-настоящему нужных приложений очень мало, поэтому я решил сделать «карманный» справочник по высшей математике с удобной навигацией по темам, состоящий из трех разделов: математический анализ, аналитическая геометрия, теория вероятностей. Далее обо всем по порядку.
Структура приложения
О создании приложения такого плана на Хабре уже писали в посте
Пишем шпаргалку на Android
. Разумеется есть некоторые отличия. Первое и главное из них в том, что в нашем приложении нужно будет сделать чуть побольше Activity, второе — добавление в приложение социальных возможностей, таких как отправить письмо разработчику и самостоятельно поучаствовать в создании приложения любому желающему, также добавим в приложение меню опций и несколько диалоговых окон, ну и собственно подключим к нему рекламу Begun, чтобы хоть как-то оправдать затраты на приобретение аккаунта разработчика на маркете.
Activity
MainActivity
При запуске приложения пользователь будет видеть экран MainActivity:
Он содержит три кнопки, при нажатии на которые осуществляется переход на MatanActivity, GeomActivity, или TerverActivity, содержащие в своих файлах-разметки элементы ListView, представляющие набор соответствующих тем по нужному предмету. Подробный код MainActivity представлен ниже:
public class MainActivity extends Activity {
AdView ad;
//Объявление идентификатора диалогового окна HELP и диалогового окна Exit
static final int EXIT_DIALOG=0;
static final int HELP_DIALOG=1;//Вызов меню опций с одной кнопкой About
Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.gameoptions, menu);
menu.findItem(R.id.about_menu_item);
menu.findItem(R.id.btn_email);
return true;
}
//обработка нажатий на эл-ты меню опций
//Вызов диалога HELP из меню опций при нажатии на «О приложении» и переход на EmailActivity при нажатии на «свяжитесь с нами»
Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.about_menu_item:
showDialog(HELP_DIALOG);
return true;
case R.id.btn_email:
startActivity(new Intent(getApplicationContext(),EmailActivity.class));
return true;
default:
return super.onOptionsItemSelected(item);
}
}/** Called when the activity is first created. */Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //скрываем заголовок
setContentView(R.layout.second); //подключение рекламы
// Получаем вид
ad = (AdView)findViewById(R.id.ad);
ad.onDebug = true;
// Устанавливаем слушатели событий
// callback — слушатель, благодаря которому можно получить информацию
// о событиях в библиотеке. Пока доступны следующие листенеры: AdLoaded, AdClickThru
// и AdStopped. Для инициализации необходимо передать параметр environmentVars,
// который содержит информацию о зарегистрированной площадке в системе
// (BEGUN_PAD_ID, BEGUN_BLOCK_ID).
// Для начала инициализации необходимо вызвать метод ad.init. Затем дождаться
// callback со статусом adLoaded и только после этого вызвать метод
// ad.api(«initAd»,al);
ad.setOnApiListener(new Callback() {Override
public void init() {
Log.d(«BEGUN_AD», «ad.api|initAd»);
ArrayList<RequestParam> al = new ArrayList<RequestParam>();
RequestParam rp = new RequestParam();
rp.name = «environmentVars»;
rp.value = «pad_id:261629112|block_id:261629500»;
al.add(rp);
ad.api(«initAd», al);
Log.d(«BEGUN_AD», «CALLBACK params: « + al.toString());
}Override
public void callback(String c) {
Log.d(«BEGUN_AD», «CALLBACK API : « + c);
if (c.equals(«AdLoaded»)) {
Log.d(«BEGUN_AD», «startAd « + c);
ad.api(«startAd»);
}
}
});
Log.d(«BEGUN_AD», «ad.init»);
ad.init();//Запуск MatanActivity
Button b=(Button)this.findViewById(R.id.btn_mathan);
b.setOnClickListener(new OnClickListener(){
public void onClick(View arg0){
startActivity(new Intent(getApplicationContext(),MatanActivity.class));
}
}); //Запуск GeomActivity
Button d=(Button)this.findViewById(R.id.btn_geom);
d.setOnClickListener(new OnClickListener(){
public void onClick(View arg0){
startActivity(new Intent(getApplicationContext(),GeomActivity.class));
}
}); //Запуск TerverActivityButton c=(Button)this.findViewById(R.id.btn_terver);
c.setOnClickListener(new OnClickListener(){
public void onClick(View arg0){
startActivity(new Intent(getApplicationContext(),TerverActivity.class));
}
});}protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
Log.d(«BEGUN_AD», «resumeAd»);
ad.api(«resumeAd»);
} //Создание диалоговых окон HELP_DIALOG и EXIT_DIALOG
Override
protected Dialog onCreateDialog(int id)
{
switch (id)
{
case HELP_DIALOG:
LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.help,
(ViewGroup) findViewById(R.id.root));
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setView(layout)
.setCancelable(true)
.setTitle(«О приложении»)
.setNeutralButton(«ОК», new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int id)
{
dialog.cancel();
}
});
AlertDialog alert = builder.create();
return builder.create();case EXIT_DIALOG:
AlertDialog.Builder builder3 = new AlertDialog.Builder(this);
builder3.setMessage(«Уверены, что хотите выйти?»)
.setCancelable(false)
.setPositiveButton(«Да», new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
SecondActivity.this.finish();
}
})
.setNegativeButton(«Нет», new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}});
AlertDialog alert3 = builder3.create();
return builder3.create();default:
return null;
}}//Вызов диалога EXIT_DIALOG при нажатии на клавишу back смартфона
Override
public void onBackPressed (){
showDialog(EXIT_DIALOG);
}}
Диалоговое окно «О приложении»
Диалоговое окно выхода из приложения
Реклама добавлена в приложение больше из интереса, чем из коммерческих соображений, т.к. очевидно, что на русском приложении много не заработать. Поэтому я подключил в него чисто русскую рекламу системы Begun, до этого на Хабре многое писалось про подключение рекламы, но в основном это были зарубежные «конторы».
Плюсы использования рекламы Бегун
1. Удобный, качественный API.
2. Удобный вывод денег на WebMoney.
3. Хорошая служба поддержки, стабильно отвечающая на любые ваши вопросы.
Минусы использования рекламы Бегун
Единственный минус заключается в том, что оплата осуществляется только за переходы, но в скором времени обещают запустить систему оплаты и за клики, и за показы.
Как подключить рекламу BEGUN
1. Заходим на сайт бегуна в раздел партнерам.
2. Жмем «Стать партнером».
3. Заполняем анкету.
4. Жмем зарегестрироваться.
5. Далее входим в свой кабинет на сайте.
6. В правом верхнем углу жмете «Написать» (Перейдете в меню написания письма в службу поддержки).
7. Пишите в службу поддержки о том, что у вас есть android-приложение и вы бы хотели подключить в него рекламу Begun, вам вышлют ваш pad_id и block_id, которые в ы и вставляете в код, написанный выше, вместо тегов <Ваш pad_id> <Ваш block_id>.
Интеграция рекламы Begun в приложение
1. В classpath проекта необходимо добавить jar — библиотеку рекламы, доступную
по адресу appsmobile.begun.ru/begunAdView.jar.
2. Необходимо добавить в layout следующий блок:
<ru.begun.adlib.AdView
android:id=«@+id/ad»
android:orientation=«vertical»
android:layout_width=«fill_parent»
android:layout_height=«wrap_content»
android:layout_alignParentBottom=«true»
/>
В качестве родительского слоя рекомендуется использовать RelativeLayout.
3. Файл манифеста необходимо добавить следующие разрешения:
<uses-permission android:name=«android.permission.INTERNET»/>
<uses-permission android:name=«android.permission.ACCESS_COARSE_LOCATION»/>
<uses-permission android:name=«android.permission.READ_PHONE_STATE»/>
4. Инициализация библиотеки происходит следующим образом:
import ru.begun.adlib.AdView;
import ru.begun.adlib.Callback;
import ru.begun.adlib.RequestParam;
AdView ad;
// Получаем вид
ad = (AdView)findViewById(R.id.ad);
// Устанавливаем слушатели событий
// callback — слушатель, благодаря которому можно получить информацию
// о событиях в библиотеке. Пока доступны следующие листенеры: AdLoaded, AdClickThru
// и AdStopped. Для инициализации необходимо передать параметр environmentVars,
// который содержит информацию о зарегистрированной площадке в системе
// (BEGUN_PAD_ID, BEGUN_BLOCK_ID).
// Для начала инициализации необходимо вызвать метод ad.init. Затем дождаться
// callback со статусом adLoaded и только после этого вызвать метод
// ad.api(«initAd»,al);
ad.setOnApiListener(new Callback() {Override
public void init() {
ArrayList<RequestParam> al = new ArrayList<RequestParam>();
RequestParam rp = new RequestParam();
rp.name = «environmentVars»;
rp.value = «pad_id:<BEGUN_PAD_ID>|block_id:<BEGUN_BLOCK_ID>»;
al.add(rp);
ad.api(«initAd», al);
}Override
public void callback(String c) {
if (c.equals(«AdLoaded»)) {
ad.api(«startAd»);
}
}
});
ad.init();
Для возобновления показа рекламных объявлений после того, как библиотека была остановлена,
необходимо вызвать метод ad.api с параметром resumeAd.
Все, реклама подключена и работает!
main.xml
Файл-разметки MainActivity.
<?xml version=«1.0» encoding=«utf-8»?>
<RelativeLayout xmlns:android=«schemas.android.com/apk/res/android»
android:orientation=«vertical»
android:layout_width=«fill_parent»
android:layout_height=«fill_parent»
android:weightSum=«1»
android:background=«@drawable/main_1»><Button
android:id=«@+id/btn1»
android:layout_width=«wrap_content»
android:layout_height=«wrap_content»
android:background=«@layout/button_selector_leftcorner»/><Button android:textStyle=«bold» android:textColor=«#FFC000» android:background=«@layout/button_selector» android:layout_height=«wrap_content» android:layout_width=«173dp» android:text=«Ан. геометрия и лин. алгебра» android:id=«@+id/btn_geom» android:layout_above=«@+id/btn_terver» android:layout_alignLeft=«@+id/btn_terver» android:layout_marginBottom=«16dp»></Button>
<Button android:textStyle=«bold» android:textColor=«#FFC000» android:background=«@layout/button_selector» android:layout_height=«wrap_content» android:layout_width=«173dp» android:text=«Математический анализ» android:id=«@+id/btn_mathan» android:layout_above=«@+id/btn_geom» android:layout_alignLeft=«@+id/btn_geom» android:layout_marginBottom=«15dp»></Button>
<Button android:textStyle=«bold» android:textColor=«#FFC000» android:background=«@layout/button_selector» android:layout_height=«wrap_content» android:layout_width=«173dp» android:text=«Теория вероятностей» android:id=«@+id/btn_terver» android:layout_alignParentBottom=«true» android:layout_centerHorizontal=«true» android:layout_marginBottom=«186dp»></Button>
<ImageView android:id=«@+id/imageView1» android:src=«@drawable/andro» android:layout_height=«wrap_content» android:layout_width=«wrap_content» android:layout_above=«@+id/btn_mathan» android:layout_centerHorizontal=«true»></ImageView>
<RelativeLayout android:layout_height=«wrap_content» android:layout_width=«fill_parent»>
<ImageView android:id=«@+id/imageView2» android:layout_height=«wrap_content» android:layout_width=«wrap_content» android:src=«@drawable/title» android:layout_alignParentTop=«true» android:layout_centerHorizontal=«true» android:layout_marginTop=«18dp»></ImageView>
</RelativeLayout>
<ru.begun.adlib.AdView
android:id=«@+id/ad»
android:orientation=«vertical»
android:layout_width=«fill_parent»
android:layout_height=«wrap_content»
android:layout_alignParentBottom=«true»
/><ImageView
android:id=«@+id/splashscreen»
android:layout_width=«fill_parent»
android:layout_height=«fill_parent»
android:src=«@drawable/splashscreen» android:background=«#000»>
</ImageView></RelativeLayout>
MatanActivity, GeomActivity и TerverActivity
После клика по элементам списка в MatanActivity, GeomActivity или TerverActivity будет осуществляться переход на соответствующую деятельность отображения материала по данной теме ViewMatanActivity, ViewGeomActivity или ViewTerverActivity
Код этих активити аналогичен указанным в посте
Пишем шпаргалку на Android
.
Единственное замечание во всех ViewActivity вместо кода:
WebView myWebView = (WebView) findViewById(R.id.webview);
String summary = «<html><body>» + text + «</body></html>»;
myWebView.loadData(summary, «text/html», «utf-8»); //загружаем текст в webview
лучше писать так:
WebView myWebView = (WebView) findViewById(R.id.webview);
String summary = «<html><body>» + text + «</body></html>»;
myWebView.loadDataWithBaseURL(«x-data://base»,summary, «text/html», «utf-8», null);
В противном случае код будет некорректно работать на устройствах с android 3.2. и некоторых других.
EmailActivity
EmailActivity реализует отправку письма со своими пожеланиями и предложениями разработчикам, а также представляет возможность перехода на страницу приложения в маркете.
public class EmailActivity extends Activity {
Button send;
EditText address, subject, emailtext;
Overridepublic void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE); //скрываем заголовок
setContentView(R.layout.email);Button b=(Button)this.findViewById(R.id.btn_market);
b.setOnClickListener(new OnClickListener(){
public void onClick(View arg0){
Uri address=Uri.parse(«market.android.com/details?id=com.mathhelper.math»);
Intent surf=new Intent(Intent.ACTION_VIEW, address);
startActivity(surf);
}
}); // Наши поля и кнопка
send = (Button) findViewById(R.id.emailsendbutton);
address = (EditText) findViewById(R.id.emailaddress);
//subject = (EditText) findViewById(R.id.emailsubject);
emailtext = (EditText) findViewById(R.id.emailtext);
send.setOnClickListener(new OnClickListener() {
Overridepublic void onClick(View v) {final Intent emailIntent = new Intent(android.content.Intent.ACTION_SEND);
emailIntent.setType(«plain/text»);
// Кому
emailIntent.putExtra(android.content.Intent.EXTRA_EMAIL,new String[] { address.getText().toString() });// О чём
emailIntent.putExtra(android.content.Intent.EXTRA_TEXT,emailtext.getText().toString());
EmailActivity.this.startActivity(Intent.createChooser(emailIntent,
«Отправка письма»));
}
});
}
}
email.xml
Файл разметки EmailActivity
<?xml version=«1.0» encoding=«utf-8»?>
<RelativeLayout xmlns:android=«schemas.android.com/apk/res/android»
android:orientation=«vertical»
android:layout_width=«fill_parent»
android:layout_height=«fill_parent»
android:weightSum=«1»><ScrollView
android:scrollbars=«vertical»
android:layout_width=«fill_parent»
android:layout_height=«fill_parent»>
<LinearLayout android:orientation=«vertical» android:id=«@+id/linearLayout2» android:background=«@drawable/metall» android:layout_alignParentTop=«true» android:layout_alignParentLeft=«true» android:layout_marginTop=«40dp» android:layout_width=«fill_parent» android:layout_height=«197dp»>
<TextView android:layout_width=«wrap_content» android:text=«Напишите нам:» android:layout_height=«wrap_content» android:id=«@+id/textView1» android:gravity=«left» android:textSize=«10pt» android:textStyle=«normal»></TextView>
<EditText android:id=«@+id/emailaddress» android:layout_width=«fill_parent» android:layout_height=«wrap_content» android:text=«svdsoftware@gmail.com»></EditText>
<EditText android:id=«@+id/emailtext» android:layout_width=«fill_parent» android:layout_height=«wrap_content» android:text=«Ваш отзыв…»></EditText>
<RelativeLayout android:layout_height=«wrap_content» android:layout_width=«fill_parent» android:id=«@+id/relativeLayout1»>
<TextView android:id=«@+id/textView1» android:text=«Отправить нам email →» android:layout_width=«wrap_content» android:gravity=«left» android:layout_height=«wrap_content» android:textSize=«9pt» android:textStyle=«normal» android:layout_centerVertical=«true»></TextView>
<Button android:id=«@+id/emailsendbutton» android:layout_width=«wrap_content» android:layout_height=«wrap_content» android:background=«@layout/button_selector_email» android:layout_alignParentTop=«true» android:layout_alignParentRight=«true»></Button>
</RelativeLayout>
<RelativeLayout android:id=«@+id/relativeLayout2» android:layout_height=«wrap_content» android:layout_width=«fill_parent»>
<Button android:id=«@+id/btn_market» android:layout_width=«wrap_content» android:layout_height=«wrap_content» android:background=«@layout/button_selector_am» android:layout_alignParentTop=«true» android:layout_alignParentRight=«true»></Button>
<TextView android:id=«@+id/textView1» android:text=«Оценить на маркете →» android:layout_width=«wrap_content» android:gravity=«left» android:layout_height=«wrap_content» android:textSize=«9pt» android:textStyle=«normal» android:layout_centerVertical=«true» ></TextView>
</RelativeLayout>
</LinearLayout>
</ScrollView></RelativeLayout>
Заключение
Надеюсь, что пост будет полезен начинающим разработчикам.
Результат всей работы можно найти здесь.
Пишем справочник про котов
В этой статье я покажу как сделать простейшую программу Справочник про котов. На этом примере можно сделать огромное количество полезных приложений — например, небольшой сборник рецептов или набор схем оригами, если использовать ListView с миниатюрами.
Что мы узнаем:
- Как сделать простой список из массива, используя ListView
- Как загрузить текст из ресурсов
- Как загрузить html-текст в WebView
- Как передать данные из одной активности в другую
Пример морально устарел. Теперь уже не используют ListView и отдельные активности для разделов. Вместо них следует использовать RecyclerView и фрагменты. Но для общего развития всё-равно полезно изучить пример.
Создаём новый проект Manual (не путать с манулом). Начнём с интерфейса программы. Программа будет состоять из двух активностей. В первой выводится список тем, а во второй — полное описание выбранной темы. Откроем разметку первой активности res/layout/activity_main.xml и добавим компонент ListView для отображения списка тем:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<ListView
android:id="@+id/listView"
android:layout_width="wrap_content"
android:layout_height="match_parent" />
</LinearLayout>
Сразу же создадим вторую активность DetailActivity (правой кнопкой мыши по имени пакета и выбираем New | Activity | Empty Activity). Создадим разметку для второй активности в файле res/layout/activity_detail.xml. Сюда мы добавим только компонент WebView. Скрытие строки состояния и заголовка сделаем в коде.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<WebView
android:id="@+id/webView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
Дизайн приложения готов. Осталось написать код. Открываем файл класса MainActivity. В нём программно создадим список заголовков тем справочника и через адаптер добавим в список. Когда пользователь выбирает элемент списка, то получаем позицию выбранного элемента и запоминаем его. А затем запускаем вторую активность, в которую передаём номер позиции. Мы проходили подобные вещи раньше, поэтому просто освежите свою память.
// Kotlin
// Если этот код работает, его написал Александр Климов,
// а если нет, то не знаю, кто его писал.
// http://developer.alexanderklimov.ru/android/
package ru.alexanderklimov.manual
import android.content.Intent
import android.os.Bundle
import android.widget.AdapterView.OnItemClickListener
import android.widget.ArrayAdapter
import android.widget.ListView
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
//Создаем массив разделов:
private val titles = arrayOf(
"00. Начало",
"01. Чем кормить кота",
"02. Как гладить кота",
"03. Как спит кот",
"04. Как играть с котом",
"05. Как разговаривать с котом",
"06. Интересные факты из жизни котов",
"07. Как назвать кота"
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val listView: ListView = findViewById(R.id.listView)
listView.adapter = ArrayAdapter<Any?>(this, android.R.layout.simple_list_item_1, titles)
listView.isTextFilterEnabled = true
listView.onItemClickListener =
OnItemClickListener { a, v, position, id ->
val intent = Intent()
intent.setClass([email protected], DetailActivity::class.java)
intent.putExtra("title", position)
startActivity(intent)
}
}
}
// Java
package ru.alexanderklimov.manual;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class MainActivity extends AppCompatActivity {
//Создаём массив разделов:
private String titles[] = {
"00. Начало",
"01. Чем кормить кота",
"02. Как гладить кота",
"03. Как спит кот",
"04. Как играть с котом",
"05. Как разговаривать с котом",
"06. Интересные факты из жизни котов",
"07. Как назвать кота",
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Получим идентификатор ListView
ListView listView = findViewById(R.id.listView);
//устанавливаем массив в ListView
listView.setAdapter(
new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, titles));
listView.setTextFilterEnabled(true);
//Обрабатываем щелчки на элементах ListView:
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
public void onItemClick(AdapterView<?> a, View v, int position, long id) {
Intent intent = new Intent();
intent.setClass(MainActivity.this, DetailActivity.class);
intent.putExtra("title", position);
//запускаем вторую активность
startActivity(intent);
}
});
}
}
Вторая активность
Запустив пример, вы можете щёлкнуть по любому элементу списка, чтобы открыть вторую активность. Сейчас вторая активность пуста, так как мы не написали никакого кода. Но при этом она получает номер позиции выбранного элемента через метод putExtra(). В зависимости от полученного номера мы формируем содержание веб-страницы.
Для справочника удобнее держать заранее подготовленные локальные файлы, чтобы не зависеть от интернета. Создадим новую папку — выбираем res | New | Directory и в диалоговом окне вводим имя папки raw.
Самостоятельно подготовьте текстовые файлы с именами n0.txt, n1.txt, n2.txt и т.д. Символ n в начале имён файлов понадобился, чтобы избежать конфликта. Файлы ресурсов не должные начинаться на цифру.
Напишем код для второй активности. Во-первых, получим номер позиции, которую нам прислала первая активность. Во-вторых, открываем нужный файл для чтения и помещаем его содержимое в WebView.
// Kotlin
package ru.alexanderklimov.manual
import android.content.Context
import android.os.Bundle
import android.webkit.WebView
import androidx.appcompat.app.AppCompatActivity
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
class DetailActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_detail)
val webView: WebView = findViewById(R.id.webView)
val intent = intent
//получаем строку и формируем имя ресурса
val resName = "n" + intent.getIntExtra("title", 0)
val context: Context = baseContext
//читаем текстовый файл из ресурсов по имени
val text: String = readRawTextFile(
context, resources.getIdentifier(
resName,
"raw", "ru.alexanderklimov.manual"
)
)
webView.loadDataWithBaseURL(null, text, "text/html", "en_US", null)
}
//читаем текст из raw-ресурсов
private fun readRawTextFile(context: Context, resId: Int): String {
val inputStream: InputStream = context.resources.openRawResource(resId)
val inputReader = InputStreamReader(inputStream)
val buffReader = BufferedReader(inputReader)
var line: String?
val builder = StringBuilder()
try {
while (buffReader.readLine().also { line = it } != null) {
builder.append(line)
builder.append("n")
}
} catch (e: IOException) {
return e.localizedMessage
}
return builder.toString()
}
}
// Java
package ru.alexanderklimov.manual;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.webkit.WebView;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
WebView webView = findViewById(R.id.webView);
Intent intent = getIntent();
//получаем строку и формируем имя ресурса
String resName = "n" + intent.getIntExtra("title", 0);
Log.i("name", resName);
Context context = getBaseContext(); //получаем контекст
//читаем текстовый файл из ресурсов по имени
String text = readRawTextFile(context, getResources().getIdentifier(resName,
"raw", "ru.alexanderklimov.manual"));
webView.loadDataWithBaseURL(null, text, "text/html", "en_US", null);
}
//читаем текст из raw-ресурсов
private String readRawTextFile(Context context, int resId)
{
InputStream inputStream = context.getResources().openRawResource(resId);
InputStreamReader inputReader = new InputStreamReader(inputStream);
BufferedReader buffReader = new BufferedReader(inputReader);
String line;
StringBuilder builder = new StringBuilder();
try {
while (( line = buffReader.readLine()) != null) {
builder.append(line);
builder.append("n");
}
} catch (IOException e) {
return null;
}
return builder.toString();
}
}
Запускаем проект и проверяем, что всё работает.
Раньше программу можно было скачать в Google Play. На данный момент я отказался от дальнейшей поддержки приложения и Гугл удалила мою программу. Взамен я создал веб-версию.
В примере показаны базовые функции, достаточные для понимания. Вы можете усложнить пример, добавив поддержку фрагментов. Также вы можете самостоятельно доработать пример. Например, добавить картинки к элементам списка, загружать готовые html-документы, а также загружать веб-страницы из интернета.
Дополнительное чтение
Обсуждение статьи на форуме.
Реклама
import
android.Manifest;
import
android.content.DialogInterface;
import
android.content.Intent;
import
android.database.Cursor;
import
android.net.Uri;
import
android.os.Bundle;
import
android.provider.ContactsContract;
import
android.provider.Settings;
import
android.view.Menu;
import
android.view.MenuInflater;
import
android.view.MenuItem;
import
android.view.View;
import
android.widget.ProgressBar;
import
android.widget.SearchView;
import
android.widget.Toast;
import
androidx.appcompat.app.AlertDialog;
import
androidx.appcompat.app.AppCompatActivity;
import
androidx.core.view.MenuItemCompat;
import
androidx.recyclerview.widget.LinearLayoutManager;
import
androidx.recyclerview.widget.RecyclerView;
import
com.google.android.material.floatingactionbutton.FloatingActionButton;
import
com.karumi.dexter.Dexter;
import
com.karumi.dexter.MultiplePermissionsReport;
import
com.karumi.dexter.PermissionToken;
import
com.karumi.dexter.listener.DexterError;
import
com.karumi.dexter.listener.PermissionRequest;
import
com.karumi.dexter.listener.PermissionRequestErrorListener;
import
com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import
java.util.ArrayList;
import
java.util.List;
public
class
MainActivity
extends
AppCompatActivity {
private
ArrayList<ContactsModal> contactsModalArrayList;
private
RecyclerView contactRV;
private
ContactRVAdapter contactRVAdapter;
private
ProgressBar loadingPB;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contactsModalArrayList =
new
ArrayList<>();
contactRV = findViewById(R.id.idRVContacts);
FloatingActionButton addNewContactFAB = findViewById(R.id.idFABadd);
loadingPB = findViewById(R.id.idPBLoading);
prepareContactRV();
requestPermissions();
addNewContactFAB.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
Intent i =
new
Intent(MainActivity.
this
, CreateNewContactActivity.
class
);
startActivity(i);
}
});
}
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
MenuItem searchViewItem = menu.findItem(R.id.app_bar_search);
final
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchViewItem);
searchView.setOnQueryTextListener(
new
SearchView.OnQueryTextListener() {
@Override
public
boolean
onQueryTextSubmit(String query) {
searchView.clearFocus();
return
false
;
}
@Override
public
boolean
onQueryTextChange(String newText) {
filter(newText.toLowerCase());
return
false
;
}
});
return
super
.onCreateOptionsMenu(menu);
}
private
void
filter(String text) {
ArrayList<ContactsModal> filteredlist =
new
ArrayList<>();
for
(ContactsModal item : contactsModalArrayList) {
if
(item.getUserName().toLowerCase().contains(text.toLowerCase())) {
filteredlist.add(item);
}
}
if
(filteredlist.isEmpty()) {
Toast.makeText(
this
,
"No Contact Found"
, Toast.LENGTH_SHORT).show();
}
else
{
contactRVAdapter.filterList(filteredlist);
}
}
private
void
prepareContactRV() {
contactRVAdapter =
new
ContactRVAdapter(
this
, contactsModalArrayList);
contactRV.setLayoutManager(
new
LinearLayoutManager(
this
));
contactRV.setAdapter(contactRVAdapter);
}
private
void
requestPermissions() {
Dexter.withActivity(
this
)
.withPermissions(Manifest.permission.READ_CONTACTS,
Manifest.permission.CALL_PHONE,
Manifest.permission.SEND_SMS, Manifest.permission.WRITE_CONTACTS)
.withListener(
new
MultiplePermissionsListener() {
@Override
public
void
onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
if
(multiplePermissionsReport.areAllPermissionsGranted()) {
getContacts();
Toast.makeText(MainActivity.
this
,
"All the permissions are granted.."
, Toast.LENGTH_SHORT).show();
}
if
(multiplePermissionsReport.isAnyPermissionPermanentlyDenied()) {
showSettingsDialog();
}
}
@Override
public
void
onPermissionRationaleShouldBeShown(List<PermissionRequest> list, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).withErrorListener(
new
PermissionRequestErrorListener() {
@Override
public
void
onError(DexterError error) {
Toast.makeText(getApplicationContext(),
"Error occurred! "
, Toast.LENGTH_SHORT).show();
}
})
.onSameThread().check();
}
private
void
showSettingsDialog() {
AlertDialog.Builder builder =
new
AlertDialog.Builder(MainActivity.
this
);
builder.setTitle(
"Need Permissions"
);
builder.setMessage(
"This app needs permission to use this feature. You can grant them in app settings."
);
builder.setPositiveButton(
"GOTO SETTINGS"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {
dialog.cancel();
Intent intent =
new
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts(
"package"
, getPackageName(),
null
);
intent.setData(uri);
startActivityForResult(intent,
101
);
}
});
builder.setNegativeButton(
"Cancel"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {
dialog.cancel();
}
});
builder.show();
}
private
void
getContacts() {
String contactId =
""
;
String displayName =
""
;
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null
,
null
,
null
, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +
" ASC"
);
if
(cursor.getCount() >
0
) {
while
(cursor.moveToNext()) {
int
hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if
(hasPhoneNumber >
0
) {
contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Cursor phoneCursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null
,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +
" = ?"
,
new
String[]{contactId},
null
);
if
(phoneCursor.moveToNext()) {
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsModalArrayList.add(
new
ContactsModal(displayName, phoneNumber));
}
phoneCursor.close();
}
}
}
cursor.close();
loadingPB.setVisibility(View.GONE);
contactRVAdapter.notifyDataSetChanged();
}
}
import
android.Manifest;
import
android.content.DialogInterface;
import
android.content.Intent;
import
android.database.Cursor;
import
android.net.Uri;
import
android.os.Bundle;
import
android.provider.ContactsContract;
import
android.provider.Settings;
import
android.view.Menu;
import
android.view.MenuInflater;
import
android.view.MenuItem;
import
android.view.View;
import
android.widget.ProgressBar;
import
android.widget.SearchView;
import
android.widget.Toast;
import
androidx.appcompat.app.AlertDialog;
import
androidx.appcompat.app.AppCompatActivity;
import
androidx.core.view.MenuItemCompat;
import
androidx.recyclerview.widget.LinearLayoutManager;
import
androidx.recyclerview.widget.RecyclerView;
import
com.google.android.material.floatingactionbutton.FloatingActionButton;
import
com.karumi.dexter.Dexter;
import
com.karumi.dexter.MultiplePermissionsReport;
import
com.karumi.dexter.PermissionToken;
import
com.karumi.dexter.listener.DexterError;
import
com.karumi.dexter.listener.PermissionRequest;
import
com.karumi.dexter.listener.PermissionRequestErrorListener;
import
com.karumi.dexter.listener.multi.MultiplePermissionsListener;
import
java.util.ArrayList;
import
java.util.List;
public
class
MainActivity
extends
AppCompatActivity {
private
ArrayList<ContactsModal> contactsModalArrayList;
private
RecyclerView contactRV;
private
ContactRVAdapter contactRVAdapter;
private
ProgressBar loadingPB;
@Override
protected
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
contactsModalArrayList =
new
ArrayList<>();
contactRV = findViewById(R.id.idRVContacts);
FloatingActionButton addNewContactFAB = findViewById(R.id.idFABadd);
loadingPB = findViewById(R.id.idPBLoading);
prepareContactRV();
requestPermissions();
addNewContactFAB.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
Intent i =
new
Intent(MainActivity.
this
, CreateNewContactActivity.
class
);
startActivity(i);
}
});
}
@Override
public
boolean
onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search_menu, menu);
MenuItem searchViewItem = menu.findItem(R.id.app_bar_search);
final
SearchView searchView = (SearchView) MenuItemCompat.getActionView(searchViewItem);
searchView.setOnQueryTextListener(
new
SearchView.OnQueryTextListener() {
@Override
public
boolean
onQueryTextSubmit(String query) {
searchView.clearFocus();
return
false
;
}
@Override
public
boolean
onQueryTextChange(String newText) {
filter(newText.toLowerCase());
return
false
;
}
});
return
super
.onCreateOptionsMenu(menu);
}
private
void
filter(String text) {
ArrayList<ContactsModal> filteredlist =
new
ArrayList<>();
for
(ContactsModal item : contactsModalArrayList) {
if
(item.getUserName().toLowerCase().contains(text.toLowerCase())) {
filteredlist.add(item);
}
}
if
(filteredlist.isEmpty()) {
Toast.makeText(
this
,
"No Contact Found"
, Toast.LENGTH_SHORT).show();
}
else
{
contactRVAdapter.filterList(filteredlist);
}
}
private
void
prepareContactRV() {
contactRVAdapter =
new
ContactRVAdapter(
this
, contactsModalArrayList);
contactRV.setLayoutManager(
new
LinearLayoutManager(
this
));
contactRV.setAdapter(contactRVAdapter);
}
private
void
requestPermissions() {
Dexter.withActivity(
this
)
.withPermissions(Manifest.permission.READ_CONTACTS,
Manifest.permission.CALL_PHONE,
Manifest.permission.SEND_SMS, Manifest.permission.WRITE_CONTACTS)
.withListener(
new
MultiplePermissionsListener() {
@Override
public
void
onPermissionsChecked(MultiplePermissionsReport multiplePermissionsReport) {
if
(multiplePermissionsReport.areAllPermissionsGranted()) {
getContacts();
Toast.makeText(MainActivity.
this
,
"All the permissions are granted.."
, Toast.LENGTH_SHORT).show();
}
if
(multiplePermissionsReport.isAnyPermissionPermanentlyDenied()) {
showSettingsDialog();
}
}
@Override
public
void
onPermissionRationaleShouldBeShown(List<PermissionRequest> list, PermissionToken permissionToken) {
permissionToken.continuePermissionRequest();
}
}).withErrorListener(
new
PermissionRequestErrorListener() {
@Override
public
void
onError(DexterError error) {
Toast.makeText(getApplicationContext(),
"Error occurred! "
, Toast.LENGTH_SHORT).show();
}
})
.onSameThread().check();
}
private
void
showSettingsDialog() {
AlertDialog.Builder builder =
new
AlertDialog.Builder(MainActivity.
this
);
builder.setTitle(
"Need Permissions"
);
builder.setMessage(
"This app needs permission to use this feature. You can grant them in app settings."
);
builder.setPositiveButton(
"GOTO SETTINGS"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {
dialog.cancel();
Intent intent =
new
Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts(
"package"
, getPackageName(),
null
);
intent.setData(uri);
startActivityForResult(intent,
101
);
}
});
builder.setNegativeButton(
"Cancel"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {
dialog.cancel();
}
});
builder.show();
}
private
void
getContacts() {
String contactId =
""
;
String displayName =
""
;
Cursor cursor = getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
null
,
null
,
null
, ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME +
" ASC"
);
if
(cursor.getCount() >
0
) {
while
(cursor.moveToNext()) {
int
hasPhoneNumber = Integer.parseInt(cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.HAS_PHONE_NUMBER)));
if
(hasPhoneNumber >
0
) {
contactId = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts._ID));
displayName = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME));
Cursor phoneCursor = getContentResolver().query(
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
null
,
ContactsContract.CommonDataKinds.Phone.CONTACT_ID +
" = ?"
,
new
String[]{contactId},
null
);
if
(phoneCursor.moveToNext()) {
String phoneNumber = phoneCursor.getString(phoneCursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER));
contactsModalArrayList.add(
new
ContactsModal(displayName, phoneNumber));
}
phoneCursor.close();
}
}
}
cursor.close();
loadingPB.setVisibility(View.GONE);
contactRVAdapter.notifyDataSetChanged();
}
}
0 / 0 / 0 Регистрация: 04.08.2013 Сообщений: 13 |
|
1 |
|
01.11.2014, 17:22. Показов 6079. Ответов 10
Стоит задача написать простой телефонный справочник, примерно 4к абонентов, но увы, мои познания в программирование под android скудны. Я понимаю, задача тривиальная, но все же.
__________________
0 |
1605 / 1337 / 291 Регистрация: 25.10.2009 Сообщений: 3,487 Записей в блоге: 2 |
|
01.11.2014, 18:50 |
2 |
мои познания в программирование под android скудны насколько скудны?
Как я понял лучше использовать БД, а не массив? Только БД.
И как реализовать динамическую подгрузку контента Можно запросом с параметрами limit и offset.
1 |
0 / 0 / 0 Регистрация: 04.08.2013 Сообщений: 13 |
|
01.11.2014, 20:50 [ТС] |
3 |
Максимально скудны
0 |
325 / 123 / 10 Регистрация: 01.11.2012 Сообщений: 586 |
|
01.11.2014, 23:44 |
4 |
Все решения кусковые, сразу готовых не найдете, т.к. определенных правил, как я уже убедился, не существует. Собирайте по мере надобности по кусочкам. Я начинал банально вывести данные из таблицы в листвью. Соответственно надо уметь хоть что то писать и понимать в SQL и учится делать кастомный адаптер. Все эти вещи есть тут на форуме.
1 |
14 / 14 / 3 Регистрация: 13.02.2012 Сообщений: 233 Записей в блоге: 1 |
|
07.03.2015, 10:25 |
5 |
qwer1i, нашел решение своей задачи? Тоже встала похожая задача.
0 |
420 / 357 / 47 Регистрация: 22.05.2013 Сообщений: 2,518 |
|
07.03.2015, 14:14 |
6 |
ИМХО 4к это слишком много записей! Будет тормозить! Норма (по моим наблюдениям) несколько (2-4) сотен!!! Я «для себя» пишу звонилку. У меня в книжке ~500~600 номеров (>10 лет копил) и если хочу вывести что-то больше чем 1-2 поля в одну строку (картинки, расчетные поля, у меня их уже больше 8ми), приходится оптимизировать…
0 |
325 / 123 / 10 Регистрация: 01.11.2012 Сообщений: 586 |
|
07.03.2015, 14:16 |
7 |
Tester64, тормозит из-за чего? Из-за получения данных из БД или при выводе в список?
0 |
420 / 357 / 47 Регистрация: 22.05.2013 Сообщений: 2,518 |
|
07.03.2015, 14:29 |
8 |
Получение почти мгновенное, хотя если столбцов в запросе много, может задуматься почти на секунду. так вот встать на позицию занимает СЛИШКОМ долго для быстрого листания! Один из хабравчанинов это решил общим запросом по индексу и скоростными запросами по каждому полю.
1 |
24 / 17 / 7 Регистрация: 05.12.2013 Сообщений: 70 |
|
07.03.2015, 22:48 |
9 |
Что-то запутоно, у меня есть опыт написания клиента для сервиса анонимных вопросов, ну так вот, выкачивал я и несколько тысячь вопросов — не тормозило (хранил в бд). Видимо у вас архитектура такова или многопоточностью не корректно воспользывались.
0 |
420 / 357 / 47 Регистрация: 22.05.2013 Сообщений: 2,518 |
|
08.03.2015, 11:26 |
10 |
выкачивал я и несколько тысячь вопросов Вы их ОДНОВРЕМЕННО пытались вывести на экран? все несколько тысяч? Хранить в базе можно и миллионы. Но если хотите выводить на экран по быстрому, то возникают проблемы. Когда вы скролите быстрым методом (ползунком, а не слайд пальцем), то за один слайд на экран надо вывести за одну секунду десяток-сотню строк. Даже если каждую выводит 0.1 секунды, то тормоза ОЧЕНЬ наглядные. Скажем так… у меня была база на 500-900 позиций. Надо было выводить 6-12 полей в одну строку (включая 3-4 картинки). Листвьюв справлялся. Но база выросла до 2500 и… тормоза! Вынужден переделывать адаптер. Сейчас сделал свой спид-адаптер на основе хабра и своих идей. Его использую как предок для спид-адаптер-sqlite. В том числе и для адаптера показа списка контактов и истории звонков. Планирую еще ускорить на порядок через многопоточность. Уже добивался, но вынужден был отключить — не победил утечку памяти — не было инструментов отлова (тупо перегружалась мобилка через 10 минут тестов).
0 |
0 / 0 / 0 Регистрация: 16.07.2013 Сообщений: 51 |
|
08.03.2015, 12:32 |
11 |
Есть ли кто, кто разбирается в AIDE(android integrated development environment)?
0 |
Код который изменился «Справочник рыбака»
MainActivity.java
package com.neco_desarrollo.fisher_hanbook;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.View;
import androidx.core.view.GravityCompat;
import androidx.appcompat.app.ActionBarDrawerToggle;
import android.view.MenuItem;
import com.google.android.material.navigation.NavigationView;
import com.neco_desarrollo.fisher_hanbook.settings.SettingsActivity;
import com.neco_desarrollo.fisher_hanbook.utils.CustomArrayAdapter;
import com.neco_desarrollo.fisher_hanbook.utils.ListItemClass;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import android.view.Menu;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private ListView list;
private String[] array, arraySecName;
private CustomArrayAdapter adapter;
private Toolbar toolbar;
private int category_index;
private int[] array_fish_color = new int []{R.color.green_2, R.color.yellow, R.color.green_2, R.color.red,R.color.red};
private List<ListItemClass> listItemMain;
private ListItemClass listItem;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
list = findViewById(R.id.listView);
listItemMain = new ArrayList<>();
fillArray(R.string.fish,getResources().getStringArray(R.array.fish_array),getResources().getStringArray(R.array.fish_array_2),array_fish_color, 0);
adapter = new CustomArrayAdapter(this,R.layout.list_view_item_1,listItemMain,getLayoutInflater());
list.setAdapter(adapter);
DrawerLayout drawer = findViewById(R.id.drawer_layout);
NavigationView navigationView = findViewById(R.id.nav_view);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
navigationView.setNavigationItemSelectedListener(this);
list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
Intent intent = new Intent(MainActivity.this,Text_Content_Activity.class);
intent.putExtra("category",category_index);
intent.putExtra("position",position);
startActivity(intent);
}
});
}@Override
public void onBackPressed() {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
toolbar.setTitle(R.string.fish);
return true;
}@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {Intent i = new Intent(MainActivity.this, SettingsActivity.class);
startActivity(i);
}return super.onOptionsItemSelected(item);
}@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.id_fish) {fillArray(R.string.fish,getResources().getStringArray(R.array.fish_array),getResources().getStringArray(R.array.fish_array_2),array_fish_color, 0);
}
else if
(id == R.id.id_na)
{}
else if (id == R.id.id_sna)
{}
else if (id == R.id.id_pri)
{}
else if (id == R.id.id_history)
{}
else if (id == R.id.id_advice)
{}
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
private void fillArray(int title,String[] nameArray,String[] secName,int[] image,int index )
{toolbar.setTitle(title);
if(adapter != null) adapter.clear();
for(int i = 0; i < nameArray.length; i++)
{
listItem = new ListItemClass();
listItem.setNameF(nameArray[i]);
listItem.setSecond_name(secName[i]);
listItem.setImage_id(image[i]);
listItemMain.add(listItem);
}
if(adapter != null) adapter.notifyDataSetChanged();
category_index = index;
}
}
ListItemClass.java
package com.neco_desarrollo.fisher_hanbook.utils;
public class ListItemClass {
String name;
String second_name;
int image_id;
public String getNameF() {
return name;
}public void setNameF(String name) {
this.name = name;
}public String getSecond_name() {
return second_name;
}public void setSecond_name(String second_name) {
this.second_name = second_name;
}public int getImage_id() {
return image_id;
}public void setImage_id(int image_id) {
this.image_id = image_id;
}
}
CustomArrayAdapter.java
package com.neco_desarrollo.fisher_hanbook.utils;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.neco_desarrollo.fisher_hanbook.R;
import java.util.ArrayList;
import java.util.List;
public class CustomArrayAdapter extends ArrayAdapter<ListItemClass> {
private LayoutInflater inflater;
private List<ListItemClass> listItem = new ArrayList<>();
private Context context;
public CustomArrayAdapter(@NonNull Context context, int resource, List<ListItemClass> listItem,LayoutInflater inflater) {
super(context, resource, listItem);
this.inflater = inflater;
this.listItem = listItem;
this.context = context;
}@NonNull
@Override
public View getView(int position, @Nullable View convertView, @NonNull ViewGroup parent) {
ViewHolder viewHolder;
ListItemClass listItemMain = listItem.get(position);
if(convertView == null){
convertView = inflater.inflate(R.layout.list_view_item_1, null, false);
viewHolder = new ViewHolder();
viewHolder.image = convertView.findViewById(R.id.imItem);
viewHolder.name = convertView.findViewById(R.id.tvName);
viewHolder.secName = convertView.findViewById(R.id.tvSecName);
convertView.setTag(viewHolder);
}
else
{
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.name.setText(listItemMain.getNameF());
viewHolder.secName.setText(listItemMain.getSecond_name());
viewHolder.image.setImageResource(listItemMain.image_id);
return convertView;
}
private class ViewHolder{
TextView name;
TextView secName;
ImageView image;
}
}
arrays.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="fish_array">
<item>Карп</item>
<item>Щука</item>
<item>Сом</item>
<item>Осетр</item>
<item>Налим</item>
</string-array>
<string-array name="fish_array_2">
<item>Карпиус</item>
<item>Щукариус</item>
<item>Сомариус</item>
<item>Осетрариус</item>
<item>Налимиус</item>
</string-array>
<string-array name="na_array">
<item>Червяк</item>
<item>Кукуруза</item>
<item>Хлеб</item>
<item>Рис</item>
</string-array>
<string-array name="sna_array">
<item>Грузила</item>
<item>Крючки</item>
<item>Леска</item>
<item>Блесна</item>
</string-array>
<string-array name="pri_array">
<item>Кукуруза</item>
<item>Хлеб</item>
<item>Рис</item>
</string-array>
<string-array name="history_array">
<item>Рыбак и море</item>
<item>Рыбак и щюка</item>
<item>На дону</item>
<item>Случай на рыбалке</item>
</string-array>
<string-array name="advice_array">
<item>Советы по прикормке</item>
<item>Сезон рыбалки</item>
<item>На что клюет</item>
<item>Большой улов</item>
</string-array>
<string-array name="main_text_size_array">
<item>Большой</item>
<item>Средний</item>
<item>Маленький</item>
</string-array>
</resources>
все остальные файлы без изменений. В файле arrays.xml добавляем если хотим свои собственные названия рыб и.т.д но помним если изменим название самого массива то нужно также поменять это в кодею