Программа для пересчета температуры (приложение для Android)
Разработаем очень простое приложение для Android - программу пересчета температуры, измеренной по шкале Цельсия, в температуру по шкалам Фаренгейта и Реомюра.Формулы пересчета:
1) T°F=(9/5T + 32)°C
2) T°C=(4/5T )°R
Поскольку сама программа получается очень простая, потренируемся заодно работать с фрагментами. Ввод данных будет расположен в одном фрагменте, а вывод результатов – в другом. Сделаем разную разметку для альбомной и портретной ориентации. Предусмотрим сохранение информации в текстовых полях после смены ориентации экрана.
У вас должна быть установлена среда разработки, например, Eclipse, а также Android SDK.
Создаем новый проект
Далее выбираем иконку для приложения. Можно выбрать готовую из клипарта, а можно сделать свою (я нарисовал свою).
Затем выбираем Blank Activity (пустое окно). Имя активности (Activity) можно оставить по умолчанию.
Если выбрать Blank Activity with Fragment, то будет создан фрагмент и добавлен к активности. Но мы это сделаем сами.
После создания проекта активность выглядит так:
Удалим поле с «HelloWorld».
Создадим новые текстовые ресурсы (файл strings.xml в папке values).
<?xml version="1.0" encoding="utf-8"?>Это названия текстовых полей, надписи на кнопках и пункты меню.
<resources>
<string name="app_name">Пересчет температуры</string>
<string name="action_settings">Settings</string>
<string name="txtPrompt">Введите температуру в градусах Цельсия</string>
<string name="txtC">Температура по Цельсию</string>
<string name="txtF">Температура по Фаренгейту</string>
<string name="txtR">Температура по Реомюру</string>
<string name="btnCalc">Вычислить</string>
<string name="btnExitCaption">Выход</string>
<string name="menu_exit">Выход</string>
</resources>
Создадим еще один xml-файл в этой папке. Идем File->New->Other, в появившемся окне выбираем Android XML file:
Пишем название файла (colors)
Текст файла (цвета можете выбрать сами, я взял первые попавшиеся):
<?xml version="1.0" encoding="utf-8"?>Это цвет фона и цвет поля для ввода текста.
<resources>
<color name="colorBack">#42DAE5</color>
<color name="white_color">#FFFFFF</color>
</resources>
Сейчас нам нужно создать два файла с разметкой фрагментов и два файла с текстом программы.
Переходим в папку layout и выбираем File->New->Other, затем выбираем файл разметки:
Затем пишем название файла (fragment1) и завершаем работу мастера.
Затем копируем его и вставляем в эту же папку, переименовываем при копировании во fragment2.xml.
Затем добавим текстовые поля и две кнопки. Можно все это добавлять с помощью панели инструментов, а можно просто скопировать xml-текст.
Разметка первого фрагмента:
<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" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:gravity="center_horizontal"
android:text="@string/txtPrompt" />
<EditText
android:id="@+id/edC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="5dp"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@color/white_color"
android:ems="10"
android:inputType="numberSigned|numberDecimal">
<requestFocus />
</EditText>
<Button
android:id="@+id/btnCalcul"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:text="@string/btnCalc" />
<Button
android:id="@+id/btnExit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="@string/btnExitCaption" />
</LinearLayout>
Разметка второго фрагмента
<?xml version="1.0" encoding="utf-8"?>Результат
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/textView1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:gravity="center_horizontal"
android:text="@string/txtF" />
<TextView
android:id="@+id/tvF"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="5dp"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@color/white_color" />
<TextView
android:id="@+id/textView2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:gravity="center_horizontal"
android:text="@string/txtR" />
<TextView
android:id="@+id/tvR"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="5dp"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@color/white_color" />
</LinearLayout>
Создадим два java-файла фрагментов. Каждый фрагмент будет выполнять свою задачу (один – ввод данных, другой – вывод) и не должен знать о других фрагментах приложения. Координацию между ними выполняет activity, как слушатель нажатия кнопки расчета.
Создаем новый java-class.
Пишем название файла, наследуемся от класса Fragment из библиотеки поддержки - android.support.v4.app.Fragment.
Код первого фрагмента fragment1.java:
package ru.studentshelper.fahrenheit1;Добавляем implements OnClickListener, то есть делаем слушателем кнопки фрагмент.
import ru.studentshelper.fahrenheit1.R;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
public class fragment1 extends Fragment implements OnClickListener {
double tCelsius;
private EditText edC;
public interface OnbtnCalcClickListener {
void onBtnCalcClick(double tCels);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
// return super.onCreateView(inflater, container, savedInstanceState);
View viewHierarchy = inflater.inflate(R.layout.fragment1, container,
false);
Button btnCalcul = (Button) viewHierarchy.findViewById(R.id.btnCalcul);
Button btnExit = (Button) viewHierarchy.findViewById(R.id.btnExit);
btnCalcul.setOnClickListener(this);
btnExit.setOnClickListener(this);
;
edC = (EditText) viewHierarchy.findViewById(R.id.edC);
return viewHierarchy;
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.btnExit:
getActivity().finish();
break;
case R.id.btnCalcul:
// TODO Auto-generated method stub
if (edC.getText().length() != 0) {
tCelsius = Double.parseDouble(edC.getText().toString());
OnbtnCalcClickListener listener = (OnbtnCalcClickListener) getActivity();
listener.onBtnCalcClick(tCelsius);
} else {
Toast.makeText(getActivity(), "Не введена температура!",
Toast.LENGTH_SHORT).show();
return;
}
break;
}
}
}
Создаем интерфейс OnbtnCalcClickListener с одной функцией, которую только объявляем, но не реализуем. Реализация будет происходить в activity. Аргумент этой функции – температура по Цельсию.
В функции onCreateView заполняем разметку, объявляем все элементы, к которым будем обращаться в коде.
Затем нужно обработать нажатие кнопок. Создаем функцию OnClick(View v). Получаем id нажатой кнопки, сравниваем его с id из R-файла. Если это кнопка выхода, то закрываем приложение. Поскольку из фрагмента нельзя вызвать функцию finish(), то получаем activity и с его помощью завершаем работу.
Если это кнопка расчета, то проверим, введена ли температура. Если нет, то выведем всплывающее сообщение и выйдем из функции. Если все нормально, то считываем значение температуры и преобразовываем его в значение типа Double.
Затем создаем объект интерфейса и присваиваем ему значение нашей главной активности. И уже этот объект (то есть активность) вызывает объявленную функцию.
Перейдем ко второму фрагменту. Создаем его так же, как и первый, называем fragment2.java. Здесь нам нужно будет выполнить расчет и вывести результат на экран.
Кроме того, надо учесть, что при повороте экрана активность (и фрагменты тоже) пересоздается, при этом уничтожаются значения в текстовых полях (TextView). Значения в EditText сохраняются, если поле имеет id. Поэтому будем сохранять эти значения в объект Bundle, а при создании фрагмента подставлять в нужные поля. Перед уничтожением активности вызывается функция onSaveInstanceState, вот в ней и будем сохранять значения.
Текст фрагмента:
package ru.studentshelper.fahrenheit1;
import ru.studentshelper.fahrenheit1.R;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
public class fragment2 extends Fragment {
private TextView tvF;
private TextView tvR;
CharSequence sText;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// TODO Auto-generated method stub
// return super.onCreateView(inflater, container, savedInstanceState);
View viewHierarchy = inflater.inflate(R.layout.fragment2, container,
false);
tvF = (TextView) viewHierarchy.findViewById(R.id.tvF);
tvR = (TextView) viewHierarchy.findViewById(R.id.tvR);
if (savedInstanceState != null) {
tvF.setText(savedInstanceState.getString("tvF"));
tvR.setText(savedInstanceState.getString("tvR"));
}
return viewHierarchy;
}
void Calc(double tC) {
tvR.setText(String.valueOf(5 * tC / 4));
tvF.setText(String.valueOf(tC * 9 / 5 + 32));
}
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putString("tvF", tvF.getText().toString());
outState.putString("tvR", tvR.getText().toString());
}
}
Выполняет расчет и вывод результат на экран функция Calc.
Осталось скоординировать эти фрагменты между собой.
Перейдем к разметке activity_main:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"Результат:
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBack"
android:orientation="vertical"
tools:context="ru.studentshelper.fahrenheit1.MainActivity"
tools:ignore="MergeRootFrame">
<fragment
android:id="@+id/fragment1"
android:name="ru.studentshelper.fahrenheit1.fragment1"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:layout="@layout/fragment1" />
<fragment
android:id="@+id/fragment2"
android:name="ru.studentshelper.fahrenheit1.fragment2"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
tools:layout="@layout/fragment2" />
</LinearLayout>
Большую часть текста MainActivity уже создала среда разработки. Я не буду почти ничего менять, только добавлю кнопку меню «Выход». Еще нужна реализации функции из первого фрагмента. В этой функции (onBtnCalcClick) создается объект – менеджер фрагментов. Затем этот менеджер находит второй фрагмент по id, И, наконец, этот найденный фрагмент запускает функцию Calc.
Текст файла меню из папки menu (main.xml):
<menu xmlns:android="http://schemas.android.com/apk/res/android"Текст MainActivity.java:
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context="ru.studentshelper.fahrenheit1.MainActivity" >
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
android:title="@string/action_settings"
app:showAsAction="never"/>
<item
android:id="@+id/exit_menu"
android:orderInCategory="100"
android:title="@string/menu_exit"
app:showAsAction="never"/>
</menu>
package ru.studentshelper.fahrenheit1;Да, не забывайте добавить implements OnbtnCalcClickListener к классу фрагмента.
import ru.studentshelper.fahrenheit1.fragment1.OnbtnCalcClickListener;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
public class MainActivity extends ActionBarActivity implements OnbtnCalcClickListener{
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void onBtnCalcClick(double tCels) {
// TODO Auto-generated method stub
android.support.v4.app.FragmentManager fm = getSupportFragmentManager();
fragment2 f2 = (fragment2) fm.findFragmentById(R.id.fragment2);
if (f2 != null)
f2.Calc(tCels);
}
@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);
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();
if (id == R.id.exit_menu) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
}
Сейчас создадим папку layout-land, скопируем в нее файл activity_main.xml и изменим его (ориентация LinearLayout и параметры фрагментов):
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"Запускаем эмулятор и проверяем:
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorBack"
android:orientation="horizontal"
tools:context="ru.studentshelper.fahrenheit1.MainActivity"
tools:ignore="MergeRootFrame" >
<fragment
android:id="@+id/fragment1"
android:name="ru.studentshelper.fahrenheit1.fragment1"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="@layout/fragment1" />
<fragment
android:id="@+id/fragment2"
android:name="ru.studentshelper.fahrenheit1.fragment2"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
tools:layout="@layout/fragment2" />
</LinearLayout>
