В предыдущей статье мы реализовали меню приложения. Сегодня мы продолжим реализацию задач, имеющих статус High.
10. Подсказка
Приступая к решению головоломки, хотелось бы видеть конечную позицию, при достижении которой, головоломка считается решенной. Эта позиция может содержать не все, а только некоторые ключевые Tag-и, описывая их расположение на игровом поле. Возможны различные решения для отображения конечной позиции. Мы используем класс Toast для формирования splash-экрана, показывающего финальную позицию (при этом, для отображения позиции, используем уже разработанный нами класс MainView).
Начнем с создания xml-ресурса, help.xml, используемого для построения отображаемого нами окна. Добавляем в res/layout Android xml-файл. Его содержимое тривиально:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/help_page"
android:padding="10dp"
android:background="#DAAA"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal" >
</LinearLayout>
Внесем необходимые изменения в PuzzleActivity (при этом нам придется дополнительно реализовать логику загрузки головоломок из БД). Поскольку изменений довольно много приведу весь класс целиком:
...
public class PuzzleActivity extends Activity {
private static final int BASE_MENU = 100;
private static final int BASE_LOCALE_MENU = 200;
private static final int BASE_NEW_MENU = 300;
private static final int MENU_PROFILE_ITEM = 5;
private static final int MENU_NEW_ITEM = 6;
private MainView view = null;
private Menu mainMenu = null;
private Map<Long, String> stringCache = new HashMap<Long, String>();
private int currentLocale = PuzzleDb.Locales.LOCALE_EN;
private int currentPuzzle;
private long currentPosition;
private static final String[] STRINGS_PROJECTION =
new String[] {
PuzzleDb.StringValues._ID,
PuzzleDb.StringValues.COLUMN_NAME_VALUE
};
private static final String[] LOCALE_PROJECTION =
new String[] {
PuzzleDb.Locales._ID,
PuzzleDb.StringValues.COLUMN_NAME_VALUE
};
private static final String[] MENU_PROJECTION =
new String[] {
PuzzleDb.Puzzles._ID,
PuzzleDb.StringValues.COLUMN_NAME_VALUE
};
private static final String[] PROFILE_PROJECTION =
new String[] {
PuzzleDb.Profiles._ID,
PuzzleDb.Profiles.COLUMN_NAME_LOCALE_ID,
PuzzleDb.Profiles.COLUMN_NAME_PUZZLE_ID,
PuzzleDb.Puzzles.COLUMN_NAME_START_POSITION_ID
};
private static final String[] ENDPOS_PROJECTION =
new String[] {
PuzzleDb.EndPositions._ID,
PuzzleDb.EndPositions.COLUMN_NAME_POSITION_ID
};
private static final String[] PARAMS_PROJECTION =
new String[] {
PuzzleDb.Params._ID,
PuzzleDb.Params.COLUMN_NAME_PARAM_TYPE_ID,
PuzzleDb.Params.COLUMN_NAME_VALUE
};
private static final String[] PUZZLE_PROJECTION =
new String[] {
PuzzleDb.Items._ID,
PuzzleDb.Tags.COLUMN_NAME_IX,
PuzzleDb.Items.COLUMN_NAME_TAG_ID,
PuzzleDb.Items.COLUMN_NAME_IMG_ID,
PuzzleDb.Items.COLUMN_NAME_ITEM_X,
PuzzleDb.Items.COLUMN_NAME_ITEM_Y,
PuzzleDb.Items.COLUMN_NAME_X,
PuzzleDb.Items.COLUMN_NAME_Y
};
public String getLocalizedString(long id) {
String r = stringCache.get(id);
if (r != null) {
return r;
}
Uri uri = ContentUris.withAppendedId(PuzzleDb.Strings.CONTENT_URI, id);
Cursor cursor = managedQuery(
uri,
STRINGS_PROJECTION,
PuzzleDb.StringValues.COLUMN_NAME_LOCALE_ID + " = ?",
new String [] {Integer.toString(currentLocale)},
null
);
if (cursor.moveToFirst()) {
int stringsValueColumn = cursor.getColumnIndex(PuzzleDb.StringValues.COLUMN_NAME_VALUE);
r = cursor.getString(stringsValueColumn);
}
stringCache.put(id, r);
return r;
}
public void getLocales(Menu menu) {
Uri uri = PuzzleDb.Locales.CONTENT_URI;
Cursor cursor = managedQuery(
uri,
LOCALE_PROJECTION,
"b." + PuzzleDb.StringValues.COLUMN_NAME_LOCALE_ID + " = ?",
new String [] {Integer.toString(currentLocale)},
null
);
for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) {
int idColumn = cursor.getColumnIndex(PuzzleDb.Puzzles._ID);
int nameColumn = cursor.getColumnIndex(PuzzleDb.StringValues.COLUMN_NAME_VALUE);
int id = cursor.getInt(idColumn);
String name = cursor.getString(nameColumn);
menu.add(0, id + BASE_LOCALE_MENU, id, name);
}
}
public void getMenu(Menu menu) {
Uri uri = PuzzleDb.Puzzles.CONTENT_URI;
Cursor cursor = managedQuery(
uri,
MENU_PROJECTION,
PuzzleDb.StringValues.COLUMN_NAME_LOCALE_ID + " = ?",
new String [] {Integer.toString(currentLocale)},
null
);
for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) {
int idColumn = cursor.getColumnIndex(PuzzleDb.Puzzles._ID);
int nameColumn = cursor.getColumnIndex(PuzzleDb.StringValues.COLUMN_NAME_VALUE);
int id = cursor.getInt(idColumn);
String name = cursor.getString(nameColumn);
menu.add(0, id + BASE_NEW_MENU, 1000 - id, name);
}
}
private int saveProfile() {
Uri uri = PuzzleDb.Profiles.CONTENT_URI;
ContentValues values = new ContentValues();
values.put(PuzzleDb.Profiles.COLUMN_NAME_LOCALE_ID, Integer.toString(currentLocale));
return getContentResolver().update(uri, values, null, null);
}
private void loadProfile() {
Uri uri = PuzzleDb.Profiles.CONTENT_URI;
Cursor cursor = managedQuery(
uri,
PROFILE_PROJECTION,
null,
null,
null
);
if (cursor.moveToFirst()) {
int puzzleIdColumn = cursor.getColumnIndex(PuzzleDb.Profiles.COLUMN_NAME_PUZZLE_ID);
int localeIdColumn = cursor.getColumnIndex(PuzzleDb.Profiles.COLUMN_NAME_LOCALE_ID);
int positionIdColumn = cursor.getColumnIndex(PuzzleDb.Puzzles.COLUMN_NAME_START_POSITION_ID);
currentPuzzle = cursor.getInt(puzzleIdColumn);
currentPosition = cursor.getInt(positionIdColumn);
currentLocale = cursor.getInt(localeIdColumn);
}
}
public long getEndPositionId(int puzzleId) {
Uri uri = ContentUris.withAppendedId(PuzzleDb.EndPositions.CONTENT_URI, puzzleId);
Cursor cursor = managedQuery(
uri,
ENDPOS_PROJECTION,
null,
null,
null
);
if (cursor.moveToFirst()) {
int positionIdColumn = cursor.getColumnIndex(PuzzleDb.EndPositions.COLUMN_NAME_POSITION_ID);
return cursor.getLong(positionIdColumn);
}
return -1;
}
public void getEndPositions(Model callback, int id) {
Uri uri = ContentUris.withAppendedId(PuzzleDb.EndPositions.CONTENT_URI, id);
Cursor cursor = managedQuery(
uri,
ENDPOS_PROJECTION,
null,
null,
null
);
for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) {
int positionIdColumn = cursor.getColumnIndex(PuzzleDb.EndPositions.COLUMN_NAME_POSITION_ID);
long positionId = cursor.getLong(positionIdColumn);
getPosition(callback, positionId);
}
}
public void getParams(Model callback, int id) {
Uri uri = ContentUris.withAppendedId(PuzzleDb.Params.CONTENT_URI, id);
Cursor cursor = managedQuery(
uri,
PARAMS_PROJECTION,
null,
null,
null
);
for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) {
int paramIdColumn = cursor.getColumnIndex(PuzzleDb.Params.COLUMN_NAME_PARAM_TYPE_ID);
int paramValueColumn = cursor.getColumnIndex(PuzzleDb.Params.COLUMN_NAME_VALUE);
int paramId = cursor.getInt(paramIdColumn);
int paramValue = cursor.getInt(paramValueColumn);
callback.setParam(paramId, paramValue);
}
}
public void getPosition(Model callback, long id) {
callback.clearTags();
Uri uri = ContentUris.withAppendedId(PuzzleDb.Positions.CONTENT_URI, id);
Cursor cursor = managedQuery(
uri,
PUZZLE_PROJECTION,
"b." + PuzzleDb.Tags.COLUMN_NAME_PUZZLE_ID + " = ?",
new String[] {Long.toString(currentPuzzle)},
null
);
for (cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext()) {
int tagIdColumn = cursor.getColumnIndex(PuzzleDb.Items.COLUMN_NAME_TAG_ID);
int tagIxColumn = cursor.getColumnIndex(PuzzleDb.Tags.COLUMN_NAME_IX);
int xColumn = cursor.getColumnIndex(PuzzleDb.Items.COLUMN_NAME_X);
int yColumn = cursor.getColumnIndex(PuzzleDb.Items.COLUMN_NAME_Y);
int imgColumn = cursor.getColumnIndex(PuzzleDb.Items.COLUMN_NAME_IMG_ID);
int itemXColumn = cursor.getColumnIndex(PuzzleDb.Items.COLUMN_NAME_ITEM_X);
int itemYColumn = cursor.getColumnIndex(PuzzleDb.Items.COLUMN_NAME_ITEM_Y);
int tagId = cursor.getInt(tagIdColumn);
int tagIx = cursor.getInt(tagIxColumn);
int x = cursor.getInt(xColumn);
int y = cursor.getInt(yColumn);
int itemX = cursor.getInt(itemXColumn);
int itemY = cursor.getInt(itemYColumn);
long img = cursor.getLong(imgColumn);
callback.addItem(tagId, x, y, (itemX == 0)&&(itemY == 0), tagIx, img);
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
mainMenu = menu;
super.onCreateOptionsMenu(menu);
SubMenu newMenu = menu.addSubMenu(BASE_MENU, BASE_MENU + MENU_NEW_ITEM, Menu.NONE, getLocalizedString(MENU_NEW_ITEM));
getMenu(newMenu);
newMenu = menu.addSubMenu(BASE_MENU, BASE_MENU + MENU_PROFILE_ITEM, Menu.NONE, getLocalizedString(MENU_PROFILE_ITEM));
getLocales(newMenu);
return true;
}
public void reloadPuzzle() {
saveProfile();
loadProfile();
view.loadPuzzle(currentPuzzle, currentPosition);
}
private void help() {
long endPosId = getEndPositionId(currentPuzzle);
if (endPosId > 0) {
LayoutInflater inflater = getLayoutInflater();
LinearLayout layout = (LinearLayout)inflater.inflate(R.layout.help,
(ViewGroup) findViewById(R.id.help_page));
MainView vw = new MainView(this, this);
int sizeX = view.getPhysX() / 2;
int sizeY = view.getPhysY() / 2;
vw.setMaxSizes(sizeX, sizeY);
vw.loadPuzzle(currentPuzzle, endPosId);
layout.addView(vw);
Toast toast = new Toast(getApplicationContext());
toast.setGravity(Gravity.CENTER_VERTICAL, 0, 0);
toast.setDuration(Toast.LENGTH_LONG);
toast.setView(layout);
toast.show();
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int itemId = item.getItemId();
if (itemId >= BASE_NEW_MENU) {
reloadPuzzle();
help();
} else if (itemId >= BASE_LOCALE_MENU) {
currentLocale = itemId - BASE_LOCALE_MENU;
stringCache.clear();
view.invalidate();
if (mainMenu != null) {
mainMenu.clear();
onCreateOptionsMenu(mainMenu);
}
saveProfile();
}
return true;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout.LayoutParams containerParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT, 0.0F);
LinearLayout root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
root.setBackgroundColor(Color.LTGRAY);
root.setLayoutParams(containerParams);
view = new MainView(this, this);
loadProfile();
view.loadPuzzle(currentPuzzle, currentPosition);
root.addView(view);
setContentView(root);
}
}
В PuzzleActivity стоит обратить внимание на метод help, реализующий вывод справки. Добавим новые методы (осуществляющие загрузку головоломки) в Model:
package com.whiterabbit.tags;
...
public class Model {
...
private int marginSize = 0;
private Map<Long, Tag> tags = new HashMap<Long, Tag>();
private Map<Long, Tag> currTagSet = null;
private Set<Map<Long, Tag>> endpositions = new HashSet<Map<Long, Tag>>();
private PuzzleActivity callback;
public Model(PuzzleActivity callback) {
this.callback = callback;
}
public void loadPuzzle(int puzzleId, long positionId) {
callback.getParams(this, puzzleId);
callback.getPosition(this, positionId);
currTagSet = new HashMap<Long, Tag>();
callback.getEndPositions(this, puzzleId);
if (!currTagSet.isEmpty()) {
endpositions.add(currTagSet);
}
currTagSet = null;
setSizes(physX, physY);
}
public void setParam(int paramId, int value) {
switch (paramId) {
case PuzzleDb.ParamTypes.SizeX:
sizeX = value;
break;
case PuzzleDb.ParamTypes.SizeY:
sizeY = value;
break;
}
}
public void clearTags() {
if (currTagSet == null) {
tags.clear();
endpositions.clear();
} else {
if (!currTagSet.isEmpty()) {
endpositions.add(currTagSet);
currTagSet = new HashMap<Long, Tag>();
}
}
}
public void addItem(int tagId, int x, int y, boolean isMain, int tagIx, long type) {
Map<Long, Tag> tagSet = currTagSet;
if (tagSet == null) {
tagSet = tags;
}
Long id = new Long(tagId);
Tag t = tagSet.get(id);
if (t == null) {
t = new Tag(tagId);
tagSet.put(id, t);
}
t.addItem(x, y);
}
public int getPhysX() {
return sizeX * tagSize;
}
public int getPhysY() {
return sizeY * tagSize;
}
public void setMarginSize() {
marginSize = 3;
}
public void setSizes(int x, int y) {
physX = x;
physY = y;
int szX = (physX - 2 * marginSize) / sizeX;
int szY = (physY - 2 * marginSize) / sizeY;
if (szX < szY) {
tagSize = szX;
marginY = (physY - tagSize * sizeY) / 2;
marginX = marginSize;
} else {
tagSize = szY;
marginY = marginSize;
marginX = (physX - tagSize * sizeX) / 2;
}
}
...
}
Изменения в MainView тривиальны:
package com.whiterabbit.tags;
...
public class MainView extends View {
...
public void loadPuzzle(int puzzleId, long positionId) {
model.loadPuzzle(puzzleId, positionId);
invalidate();
}
public int getPhysX() {
return model.getPhysX();
}
public int getPhysY() {
return model.getPhysY();
}
public void setMaxSizes(int x, int y) {
maxX = x;
maxY = y;
model.setMarginSize();
}
...
}
В PuzzleProvider добавим логику обработки новых запросов, традиционно исправим ошибки с неправильными идентификаторами (БД придется пересоздать, также как это делалось в предыдущей статье), а также добавим строковый ресурс и его локализацию для нового пункта меню (New):
package com.whiterabbit.tags;
...
public class PuzzleProvider extends ContentProvider {
private static final String DATABASE_NAME = "puzzle.db";
private static final int DATABASE_VERSION = 2;
private DatabaseHelper mOpenHelper;
private static final UriMatcher uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
private static final int STRING_URI_INDICATOR = 1;
private static final int LOCALE_URI_INDICATOR = 2;
private static final int PROFILE_URI_INDICATOR = 3;
private static final int PUZZLE_LIST_URI_INDICATOR = 4;
private static final int ENDPOS_ITEM_URI_INDICATOR = 5;
private static final int PARAMS_URI_INDICATOR = 6;
private static final int POSITION_ITEM_URI_INDICATOR = 7;
static {
uriMatcher.addURI(PuzzleDb.AUTHORITY, PuzzleDb.Strings.PATH_STRING + "/#", STRING_URI_INDICATOR);
uriMatcher.addURI(PuzzleDb.AUTHORITY, PuzzleDb.Locales.PATH_LOCALE, LOCALE_URI_INDICATOR);
uriMatcher.addURI(PuzzleDb.AUTHORITY, PuzzleDb.Profiles.PATH_PROFILE, PROFILE_URI_INDICATOR);
uriMatcher.addURI(PuzzleDb.AUTHORITY, PuzzleDb.Puzzles.PATH_PUZZLE, PUZZLE_LIST_URI_INDICATOR);
uriMatcher.addURI(PuzzleDb.AUTHORITY, PuzzleDb.EndPositions.PATH_ENDS + "/#", ENDPOS_ITEM_URI_INDICATOR);
uriMatcher.addURI(PuzzleDb.AUTHORITY, PuzzleDb.Params.PATH_PARAMS + "/#", PARAMS_URI_INDICATOR);
uriMatcher.addURI(PuzzleDb.AUTHORITY, PuzzleDb.Positions.PATH_POSITION + "/#", POSITION_ITEM_URI_INDICATOR);
}
@Override
public boolean onCreate() {
mOpenHelper = new DatabaseHelper(getContext());
return true;
}
@Override
public String getType(Uri uri) {
switch (uriMatcher.match(uri)) {
case STRING_URI_INDICATOR:
return PuzzleDb.Strings.CONTENT_ITEM_TYPE;
case LOCALE_URI_INDICATOR:
return PuzzleDb.Locales.CONTENT_DIR_TYPE;
case PROFILE_URI_INDICATOR:
return PuzzleDb.Profiles.CONTENT_DIR_TYPE;
case PUZZLE_LIST_URI_INDICATOR:
return PuzzleDb.Puzzles.CONTENT_DIR_TYPE;
case ENDPOS_ITEM_URI_INDICATOR:
return PuzzleDb.EndPositions.CONTENT_ITEM_TYPE;
case PARAMS_URI_INDICATOR:
return PuzzleDb.Params.CONTENT_ITEM_TYPE;
case POSITION_ITEM_URI_INDICATOR:
return PuzzleDb.Positions.CONTENT_ITEM_TYPE;
}
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
// TODO:
return null;
}
@Override
public int update(Uri uri, ContentValues values, String where, String[] whereArgs) {
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
switch (uriMatcher.match(uri)) {
case PROFILE_URI_INDICATOR:
return db.update(PuzzleDb.Profiles.TABLE_NAME,
values,
PuzzleDb.Profiles.COLUMN_NAME_IS_DEFAULT + " = 1",
null);
}
return 0;
}
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
int r = 0;
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
// TODO:
return r;
}
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = mOpenHelper.getReadableDatabase();
switch (uriMatcher.match(uri)) {
case STRING_URI_INDICATOR:
return db.rawQuery("select " + PuzzleDb.StringValues._ID +
", " + PuzzleDb.StringValues.COLUMN_NAME_VALUE +
" from " + PuzzleDb.StringValues.TABLE_NAME +
" where " + PuzzleDb.StringValues.COLUMN_NAME_STRING_ID +
" = " + uri.getPathSegments().get(1) +
" and " + selection, selectionArgs);
case LOCALE_URI_INDICATOR:
return db.rawQuery("select a." + PuzzleDb.Locales._ID + " as " + PuzzleDb.Locales._ID + ", " +
"b." + PuzzleDb.StringValues.COLUMN_NAME_VALUE + " as " + PuzzleDb.StringValues.COLUMN_NAME_VALUE + " " +
"from " + PuzzleDb.Locales.TABLE_NAME + " a, " +
PuzzleDb.StringValues.TABLE_NAME + " b " +
"where b." + PuzzleDb.StringValues.COLUMN_NAME_STRING_ID + " = " +
"a." + PuzzleDb.Locales.COLUMN_NAME_STRING_ID + " and " + selection, selectionArgs);
case PUZZLE_LIST_URI_INDICATOR:
return db.rawQuery("select " +
"a." + PuzzleDb.Puzzles._ID + " as " + PuzzleDb.Puzzles._ID + ", " +
"b." + PuzzleDb.StringValues.COLUMN_NAME_VALUE + " as " + PuzzleDb.StringValues.COLUMN_NAME_VALUE + " from " +
PuzzleDb.Puzzles.TABLE_NAME + " a, " +
PuzzleDb.StringValues.TABLE_NAME + " b where " +
"b." + PuzzleDb.StringValues.COLUMN_NAME_STRING_ID + " = " +
"a." + PuzzleDb.Puzzles.COLUMN_NAME_STRING_ID + " and " +
"b." + selection, selectionArgs);
case PROFILE_URI_INDICATOR:
return db.rawQuery("select a." + PuzzleDb.Profiles._ID + " as " + PuzzleDb.Profiles._ID + ", " +
"a." + PuzzleDb.Profiles.COLUMN_NAME_LOCALE_ID + " as " + PuzzleDb.Profiles.COLUMN_NAME_LOCALE_ID + ", " +
"a." + PuzzleDb.Profiles.COLUMN_NAME_PUZZLE_ID + " as " + PuzzleDb.Profiles.COLUMN_NAME_PUZZLE_ID + ", " +
"b." + PuzzleDb.Puzzles.COLUMN_NAME_START_POSITION_ID + " as " + PuzzleDb.Puzzles.COLUMN_NAME_START_POSITION_ID + " " +
"from " + PuzzleDb.Profiles.TABLE_NAME + " a, " +
PuzzleDb.Puzzles.TABLE_NAME + " b " +
"where a." + PuzzleDb.Profiles.COLUMN_NAME_IS_DEFAULT + " = 1 " +
"and b." + PuzzleDb.Puzzles._ID + " = a." + PuzzleDb.Profiles.COLUMN_NAME_PUZZLE_ID, selectionArgs);
case ENDPOS_ITEM_URI_INDICATOR:
return db.rawQuery("select " + PuzzleDb.EndPositions.COLUMN_NAME_POSITION_ID + " " +
"from " + PuzzleDb.EndPositions.TABLE_NAME + " " +
"where " + PuzzleDb.EndPositions.COLUMN_NAME_PUZZLE_ID + " = " + uri.getPathSegments().get(1), selectionArgs);
case PARAMS_URI_INDICATOR:
return db.rawQuery("select " +
PuzzleDb.Params._ID + ", " +
PuzzleDb.Params.COLUMN_NAME_PARAM_TYPE_ID + ", " +
PuzzleDb.Params.COLUMN_NAME_VALUE + " from " +
PuzzleDb.Params.TABLE_NAME + " where " +
PuzzleDb.Params.COLUMN_NAME_PUZZLE_ID + " = " +
uri.getPathSegments().get(1), selectionArgs);
case POSITION_ITEM_URI_INDICATOR:
return db.rawQuery("select " +
"b." + PuzzleDb.Tags.COLUMN_NAME_IX + " as " + PuzzleDb.Tags.COLUMN_NAME_IX + ", " +
"d." + PuzzleDb.Items._ID + " as " + PuzzleDb.Items._ID + ", " +
"b." + PuzzleDb.Tags._ID + " as " + PuzzleDb.Items.COLUMN_NAME_TAG_ID + ", " +
"c." + PuzzleDb.TagPositions.COLUMN_NAME_X + " + d." + PuzzleDb.Items.COLUMN_NAME_X + " as " + PuzzleDb.Items.COLUMN_NAME_X + ", " +
"c." + PuzzleDb.TagPositions.COLUMN_NAME_Y + " + d." + PuzzleDb.Items.COLUMN_NAME_Y + " as " + PuzzleDb.Items.COLUMN_NAME_Y + ", " +
"d." + PuzzleDb.Items.COLUMN_NAME_IMG_ID + " as " + PuzzleDb.Items.COLUMN_NAME_IMG_ID + ", " +
"d." + PuzzleDb.Items.COLUMN_NAME_X + " as " + PuzzleDb.Items.COLUMN_NAME_ITEM_X + ", " +
"d." + PuzzleDb.Items.COLUMN_NAME_Y + " as " + PuzzleDb.Items.COLUMN_NAME_ITEM_Y + " " +
"from " + PuzzleDb.Tags.TABLE_NAME + " b, " + PuzzleDb.TagPositions.TABLE_NAME + " c, " + PuzzleDb.Items.TABLE_NAME + " d " +
"where c." + PuzzleDb.TagPositions.COLUMN_NAME_TAG_ID + " = b." + PuzzleDb.Tags._ID + " " +
"and d." + PuzzleDb.Items.COLUMN_NAME_TAG_ID + " = b." + PuzzleDb.Tags._ID + " " +
"and " + selection + " " +
"and c." + PuzzleDb.TagPositions.COLUMN_NAME_POSITION_ID + " = " +
uri.getPathSegments().get(1), selectionArgs);
}
return null;
}
static class DatabaseHelper extends SQLiteOpenHelper {
...
@Override
public void onCreate(SQLiteDatabase db) {
...
patch_2(db);
}
private void patch_2(SQLiteDatabase db) {
addString(db, "6"); // New
addValue(db, "9, 1, 6, 'New'");
addValue(db, "10, 2, 6, 'Заново'");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {patch_2(db);}
}
}
}
Обратите внимание, что добавление строкового ресурса мы оформили патчем, увеличив номер версии БД (поскольку БД пришлось пересоздавать, делать это, строго говоря, было совсем необязательно).
Запустив приложение, и выполнив пункт меню New, увидим вполне вменяемую подсказку, показывающую финальную позицию головоломки:
В следующей статье, мы создадим новую Activity, для отображения списка рекордов. Исходники по текущему состоянию проекта можно скачать здесь.
Комментариев нет:
Отправить комментарий