Получить идентификатор просмотра в GridView - PullRequest
5 голосов
/ 07 октября 2011

Что я пробовал


Здравствуйте, ребята, я сначала создал базу данных, которую я заполнил 3 столбцами, RowID, imageID, текст. Впоследствии я создал GridView, который, если заполнить мою базу данных. Теперь я создал onItemClickListner, в котором я хотел бы получить imageID поверх позиции. После этого я схожу по моей DB-таблице после этого imageID, чтобы получить текст . Этот материал мне нужно сохранить в другой таблице. Проблема в том, что я думаю, что я не получаю imageID, и, как этот поиск для ничего в БД, если вы посмотрите на Logcat, вы увидите, что он нулевой, поэтому он, вероятно, не получил imageID или я искать в моем DBAdapter не так, как я должен.

Вопрос


IMPORTRANT: Наконец, я получаю идентификатор View thx в FuzzialLogic, но проблема все еще не решена, и я не могу получить строку поверх курсора. Пожалуйста, взгляните на это!

<---------------------------------------------- -------РАБОТАЕТ------------------------------------------ ----------------------> Что мне нужно изменить в моем коде, чтобы я мог получить идентификатор изображения, по которому щелкнул пользователь. После этого я хотел бы выполнить поиск в моей БД с этим Image-ID, чтобы получить текст, который я сохранил вместе с изображением. Этот материал потом попадает в мою другую таблицу.

Здесь вы видите Код и LogCat-Log. Я также добавил свой DatabaseAdapter, если кому-то это нужно. Спасибо за вашу помощь заранее!

Код


SFilterConfigActivity.class:

    package de.retowaelchli.filterit;

import java.util.ArrayList;

import android.app.Activity;
import android.content.Intent;
import android.database.Cursor;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.GridView;
import android.widget.Toast;
import android.*;

import de.retowaelchli.filterit.database.SmileyDBAdapter;
import de.retowaelchli.filterit.database.SFilterDBAdapter;
import de.retowaelchli.filterit.stats.ImageAdapter;




public class SFilterConfigActivity extends Activity {

    //Variablen deklarieren
    private String name;
    private String keyword;
    private String smiley;
    private String text;

    private String source;
    private Integer[] info;

    private SmileyDBAdapter SmileyHelper;
    private SFilterDBAdapter mDbHelper;


@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.sfilter_config);

      SmileyHelper = new SmileyDBAdapter(this);
      mDbHelper = new SFilterDBAdapter(this);

      getImages();
      grid();
    }


public void grid(){

    //Hier wird die GridView definiert und anschliesend über den ImageAdapter gefüllt
    final GridView gridview = (GridView) findViewById(R.id.SmileyGrind);
    gridview.setAdapter(new ImageAdapter(this, info));


    //Hier wird definiert was passiert wenn auf ein Bild in der GridView geklickt wird
    gridview.setOnItemClickListener(new OnItemClickListener(){

        public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
            Toast.makeText(SFilterConfigActivity.this, "" + position, Toast.LENGTH_SHORT).show();
           // gridview.setSelection(position);
           // Funktioniert noch nich Custom GridView Layout dafür erstellen siehe Stackoverflow
            if(position == gridview.getSelectedItemPosition()){
                v.setBackgroundColor(0xFF00FF00);

            }
            else{
                v.setBackgroundColor(0x0000000);
            }

            //Hier wird herrausgefunden welche ID das Bild hat und in den jeweiligen String gespeichert
            source = (new Long(id)).toString();

            SmileyHelper.open();
            Cursor c = SmileyHelper.getSmiley(source);
            startManagingCursor(c);

            if (c.moveToFirst()) { 
                do { 
                text = c.getString(c.getColumnIndex(SmileyDBAdapter.SOURCE)); 
                smiley = c.getString(c.getColumnIndex(SmileyDBAdapter.INFO)); 

                } while (c.moveToNext());
            SmileyHelper.close();


            }

        }

    });
}


public Integer[] getImages(){

    SmileyHelper.open();

    Cursor c = SmileyHelper.getAllSmileys();

    ArrayList<Integer> infoList = new ArrayList<Integer>();

    c.getColumnIndex(SmileyDBAdapter.INFO);
    int ColumnIndex = c.getColumnIndex(SmileyDBAdapter.INFO);

    if(c!=null)
    {

       while(c.moveToNext()){
           String infoItem = c.getString( ColumnIndex );
           infoList.add(Integer.parseInt(infoItem));
       }
    }


    info = infoList.toArray(new Integer[]{});

    c.close();


    SmileyHelper.close();


    return info;

}



public void onClickSConfigSave(View v){

    EditText edtTextName = (EditText)findViewById(R.id.SFConfigName);
    EditText edtTextKeyword = (EditText)findViewById(R.id.SFConfigKeyword);

    name = edtTextName.getText().toString();
    keyword = edtTextKeyword.getText().toString();

    mDbHelper.open();
    mDbHelper.createSFilter(name, keyword, smiley, text);
    mDbHelper.close();

    final Intent i = new Intent(this, SmileyActivity.class);
    startActivity(i);
    }
}

ImageAdapter.class

    package de.retowaelchli.filterit.stats;

import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;


//import de.retowaelchli.filterit.SFilterConfigActivity;

public class ImageAdapter extends BaseAdapter {

    // references to our images
    private Integer[] mThumbIds;
    private Context mContext;


    public ImageAdapter(Context c, Integer[] imageIds) {
        mContext = c;
        mThumbIds = imageIds;

    }



    public int getCount() {
       return mThumbIds.length;
    }

    public Object getItem(int position) {
        return mThumbIds[position];
    }

    public long getItemId(int position) {
        return position;
    }

    // create a new ImageView for each item referenced by the Adapter
    public View getView(final int position, View convertView, ViewGroup parent) {
        ImageView imageView;
        if (convertView == null) {  // if it's not recycled, initialize some attributes
            imageView = new ImageView(mContext);
            imageView.setLayoutParams(new GridView.LayoutParams(85, 85));
            imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
            imageView.setPadding(8, 8, 8, 8);
        } else {
            imageView = (ImageView) convertView;
        }

        imageView.setId(mThumbIds[position]);

        imageView.setImageResource(mThumbIds[position]);




        return imageView;




    }

}

Вот так я добавил картинки с текстом в БД:

   private void angry(){

        int drawableID = context.getResources().getIdentifier("angry", "drawable", getPackageName());
        iv.setImageResource(drawableID);

        //String info = String.valueOf(drawableID);
        String info = String.valueOf(drawableID);

        mDbHelper.open();

        mDbHelper.createSmiley("You received a angry message", info);

        mDbHelper.close();
    }

Log-Cat


А вот и журнал:

10-12 11:32:29.632: DEBUG/Database(25130): dbopen(): path = /data/data/de.retowaelchli.filterit/databases/filterit, flag = 6
10-12 11:32:29.632: DEBUG/Database(25130): dbopen(): path = /data/data/de.retowaelchli.filterit/databases/filterit, free size = 663
10-12 11:32:30.612: DEBUG/Database(25130): dbopen(): path = /data/data/de.retowaelchli.filterit/databases/filterit, flag = 6
10-12 11:32:30.612: DEBUG/Database(25130): dbopen(): path = /data/data/de.retowaelchli.filterit/databases/filterit, free size = 663
10-12 11:32:30.632: ERROR/Database(25130): Error inserting text=null smiley=null keyword=test name=test
10-12 11:32:30.632: ERROR/Database(25130): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
10-12 11:32:30.632: ERROR/Database(25130):     at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
10-12 11:32:30.632: ERROR/Database(25130):     at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:61)
10-12 11:32:30.632: ERROR/Database(25130):     at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1671)
10-12 11:32:30.632: ERROR/Database(25130):     at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1515)
10-12 11:32:30.632: ERROR/Database(25130):     at de.retowaelchli.filterit.database.SFilterDBAdapter.createSFilter(SFilterDBAdapter.java:89)
10-12 11:32:30.632: ERROR/Database(25130):     at de.retowaelchli.filterit.SFilterConfigActivity.onClickSConfigSave(SFilterConfigActivity.java:143)
10-12 11:32:30.632: ERROR/Database(25130):     at java.lang.reflect.Method.invokeNative(Native Method)
10-12 11:32:30.632: ERROR/Database(25130):     at java.lang.reflect.Method.invoke(Method.java:507)
10-12 11:32:30.632: ERROR/Database(25130):     at android.view.View$1.onClick(View.java:2186)
10-12 11:32:30.632: ERROR/Database(25130):     at android.view.View.performClick(View.java:2532)
10-12 11:32:30.632: ERROR/Database(25130):     at android.view.View$PerformClick.run(View.java:9277)
10-12 11:32:30.632: ERROR/Database(25130):     at android.os.Handler.handleCallback(Handler.java:587)
10-12 11:32:30.632: ERROR/Database(25130):     at android.os.Handler.dispatchMessage(Handler.java:92)
10-12 11:32:30.632: ERROR/Database(25130):     at android.os.Looper.loop(Looper.java:143)
10-12 11:32:30.632: ERROR/Database(25130):     at android.app.ActivityThread.main(ActivityThread.java:4196)
10-12 11:32:30.632: ERROR/Database(25130):     at java.lang.reflect.Method.invokeNative(Native Method)
10-12 11:32:30.632: ERROR/Database(25130):     at java.lang.reflect.Method.invoke(Method.java:507)
10-12 11:32:30.632: ERROR/Database(25130):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
10-12 11:32:30.632: ERROR/Database(25130):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
10-12 11:32:30.632: ERROR/Database(25130):     at dalvik.system.NativeStart.main(Native Method)

Здесь вы найдете код моего SmileyDBAdapter.

SmileyDB

package de.retowaelchli.filterit.database;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class SmileyDBAdapter {

        public static final String ROW_ID = "_id";
        public static final String SOURCE = "source";
        public static final String INFO = "info";

        private static final String DATABASE_TABLE = "smiley";

        private DatabaseHelper mDbHelper;
        private SQLiteDatabase mDb;

        private final Context mCtx;

        private static class DatabaseHelper extends SQLiteOpenHelper {

            DatabaseHelper(Context context) {
                super(context, DBAdapter.DATABASE_NAME, null, DBAdapter.DATABASE_VERSION);
            }

            @Override
            public void onCreate(SQLiteDatabase db) {
            }

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            }
        }

        /**
         * Constructor - takes the context to allow the database to be
         * opened/created
         * 
         * @param ctx
         *            the Context within which to work
         */
        public SmileyDBAdapter(Context ctx) {
            this.mCtx = ctx;
        }


        public SmileyDBAdapter open() throws SQLException {
            this.mDbHelper = new DatabaseHelper(this.mCtx);
            this.mDb = this.mDbHelper.getWritableDatabase();
            return this;
        }

        /**
         * close return type: void
         */
        public void close() {
            this.mDbHelper.close();
        }


        public long createSmiley(String source, String info ){
            ContentValues initialValues = new ContentValues();
            initialValues.put(SOURCE, source);
            initialValues.put(INFO, info);
            return this.mDb.insert(DATABASE_TABLE, null, initialValues);
        }


        public boolean deleteSmiley(long rowId) {

            return this.mDb.delete(DATABASE_TABLE, ROW_ID + "=" + rowId, null) > 0;
        }

        public Cursor getAllSmileys() {

            return this.mDb.query(DATABASE_TABLE, new String[] { ROW_ID,
                    SOURCE, INFO }, null, null, null, null, null);
        }




        //Es wird nach der ID des smiley gesucht.
        public Cursor getSmiley(String info) throws SQLException {

            Cursor mCursor =

            this.mDb.query(true, DATABASE_TABLE, new String[] { ROW_ID, SOURCE,
                    INFO }, INFO + "=" + info, null, null, null, null, null);
            if (mCursor != null) {
                mCursor.moveToFirst();
            }
            return mCursor;
        }


        public boolean updateSmiley(long rowId, String source, String info,
                String cache){
            ContentValues args = new ContentValues();
            args.put(SOURCE, source);
            args.put(INFO, info);

            return this.mDb.update(DATABASE_TABLE, args, ROW_ID + "=" + rowId, null) >0; 
        }

    }

DBAdapter

package de.retowaelchli.filterit.database;

import android.content.Context;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

public class DBAdapter {

    public static final String DATABASE_NAME = "filterit";

    public static final int DATABASE_VERSION = 1;

    public static final String CREATE_TABLE_ADFILTER = "create table adfilter (_id integer primary key autoincrement, "
    + ADFilterDBAdapter.NAME+" not null ,"
    + ADFilterDBAdapter.KEYWORD+" not null ,"
    + ADFilterDBAdapter.CACHE + " not null );";

    private static final String CREATE_TABLE_SFILTER = "create table sfilter (_id integer primary key autoincrement, "
    +SFilterDBAdapter.NAME+" not null ,"
    +SFilterDBAdapter.KEYWORD+" not null ,"
    +SFilterDBAdapter.SMILEY+ " not null ,"
    +SFilterDBAdapter.TEXT+ " not null );";

    private static final String CREATE_TABLE_ADMESSAGES = "create table admessages (_id integer primary key autoincrement, "
    +MessagesDBAdapter.PHONENUMBER+" not null ,"
    +MessagesDBAdapter.MESSAGE+ " not null );";


    private static final String CREATE_TABLE_SMILEY = " create table smiley (_id integer primary key autoincrement, "
    +SmileyDBAdapter.SOURCE+" not null ,"
    +SmileyDBAdapter.INFO+ " not null );";


    private final Context context; 
    private DatabaseHelper DBHelper;
    private SQLiteDatabase db;

    /**
     * Constructor
     * @param ctx
     */
    public DBAdapter(Context ctx)
    {
        this.context = ctx;

    }

    private static class DatabaseHelper extends SQLiteOpenHelper 
    {
        DatabaseHelper(Context context) 
        {
            super(context, DATABASE_NAME, null, DATABASE_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) 
        {
            db.execSQL(CREATE_TABLE_ADFILTER);
            db.execSQL(CREATE_TABLE_SFILTER);
            db.execSQL(CREATE_TABLE_ADMESSAGES);
            db.execSQL(CREATE_TABLE_SMILEY);
        }

        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, 
        int newVersion) 
        {               
            // Adding any table mods to this guy here
        }
    } 

   /**
     * open the db
     * @return this
     * @throws SQLException
     * return type: DBAdapter
     */
    public DBAdapter open() throws SQLException 
    {
        this.DBHelper = new DatabaseHelper(this.context);
        this.db = this.DBHelper.getWritableDatabase();
        return this;
    }

    /**
     * close the db 
     * return type: void
     */
    public void close() 
    {
        this.DBHelper.close();
    }

}

Ответы [ 4 ]

2 голосов
/ 12 октября 2011

Safari,

После просмотра вашего кода и анализа того, что может быть причиной ошибки, я заметил несколько вещей.Проблема заключается в том, что ваш код пытается обменять rowID и viewID, но на самом деле это нежелательное поведение.

В OnItemClick() аргумент id относится к rowID.На самом деле у вас нет rowID, который гарантированно (по коду) является уникальным, поэтому он не работает.Хотя вы можете «форсировать проблему» через getItemId(), эта функция просто предоставляет указатель на объект (целое число).Игнорируйте getItemId(), поскольку это только причиняет вам боль.Вместо этого возьмите само представление и получите viewId непосредственно из него, например, так:

РЕДАКТИРОВАТЬ source = v.getId().toString(); Причина: Поскольку ваш TABLE не объявляет тип, он, скорее всего, входит как строка.Мы знаем, что ImageID теперь возвращается, и мы знаем, что данные есть ... Так что, насколько я могу судить, преобразование типов оставляет, насколько я знаю.

parent и view часто вызывают путаницу, особенно сизвилистые вложенные макеты, такие как GridViews и ListViews.Однако ваш GridView довольно прост, и v должен ссылаться на ImageView, который там хранится.Если ImageView был сохранен в LinearLayout или другом подобном родителе, возможно, существует проблема, но это не относится к вам.

Это избавит вас от необходимости беспокоиться о getItemId(int position)Как и прежде, это относится к rowId и работает только в том случае, если вы можете гарантировать Adapter определенные вещи, в частности, уникальный rowId для каждого элемента.

Во-вторых, ваш viewId установлен науказатель на Integer, а не само значение.int является примитивом, поэтому назначение происходит, как и ожидалось.Integer - это Object, поэтому присваивание происходит по адресу объекта, а не самому объекту.Я бы предложил изменить imageView.setId(mThumbIds[position]); (в вашем getView()) на:

   imageView.setId(mThumbIds[position].intValue());

Это даст примитивное значение int вместо ссылки на объект Integer в памяти.Если в вашем коде не происходит что-то еще странное (и я не вижу ничего правильного), это должно решить вашу проблему.setId предназначен для тихого сбоя, если ему назначен неподходящий id, поэтому он может не работать и просто не сообщать вам.

Наконец, я не вижу, какой тип поля 'SOURCE 'в вашем коде.Это не показывает фактическое создание таблицы.Таким образом, дальнейшие предположения по вашей конкретной базе данных невозможны.Надеюсь, это поможет!

Относительно вашей базы данных Главное, что выделяется в вашей базе данных, это утверждение CREATE TABLE для вашей таблицы Simleys.В SQLite, если вы явно не назначаете тип, SQLite будет определять тип каждый раз, когда вы делаете запрос, и возвращать тип в соответствии с тем, что, по его мнению, находится в поле.Это означает, что числа могут быть интерпретированы как String и наоборот.В целом, это может быть довольно надежно, однако, это может привести к подводным камням.

Одна из самых больших проблем в коде - это предположить, что код выполняет то, что вы хотите.На самом деле, вы можете гарантировать это, только если точно скажете, что делать.

Во-вторых, я заметил, что когда вы получаете изображения для построения вашего Array для вашего ImageAdapter, вы выполняете запрос к полю INFO, а не SOURCE.Это вводит в заблуждение ваш код, когда вы сообщаете onItemClick, что вы получаете SOURCE.Попробуйте изменить имя этой переменной.

Далее, при запросе к полю INFO через getSmiley(String info) возникает дисфункция.В соответствии с вашими аргументами он ожидает строку, а не целое число.Добавление String к ContentValues объекту отличается от добавления Integer.String добавляется с '' окружающим его, отделяющим '1' от 1. Это означает, что все ваши Integers были вставлены как String, и когда вы запрашиваете, вы не включаете необходимое ''.Поэтому рекомендуется внести ряд изменений.

  • Сначала настройте оператор CREATE TABLE.

    private static final String CREATE_TABLE_SMILEY = "create table smiley (_id integer autoincrement первичного ключа), "+ SmileyDBAdapter.SOURCE +" не ноль, "+ SmileyDBAdapter.INFO + "integer not null);";

Изменение оператора таким образом гарантирует, что вы получите целое число, а не строку.

  • Затем измените getImages() следующим образом: String infoItem = c.getString( ColumnIndex ); на int infoItem = c.getInt( ColumnIndex );

  • Затем измените createSmiley(String source, String info) на createSmiley(String source, int info). Это должно корректировать все ваши вставки правильно. Ваш ContentValues объект (с именем initialValues) будет знать, что делать.

  • Затем измените getSmiley(String info) на getSmiley(int info). Это также должно корректировать ваш запрос. Если это не так, измените ... + "=" + info + ... на ... + "=" + info.toString() + .... Это заставит проблему для вас.

  • Затем установите соответствие onItemClick(), изменив эту строку source = v.getId().toString(); обратно на source = v.getId();

  • Наконец, вам придется изменить любой из ваших вызовов на createSmiley(), чтобы отправить значение int, а не значение, преобразованное в строку.

Это много изменений (не совсем) для внесения. Поэтому, пожалуйста, сделайте резервную копию ваших исходных файлов, прежде чем вносить эти изменения. Затем нужно просто удалить пакет (в том числе из эмулятора, если он эмулируется) и переустановить его, чтобы он не сохранял исходные данные (со строками, а не с целыми числами).

FuzzicalLogic

2 голосов
/ 07 октября 2011

В вашем коде ImageAdapter. У вас есть переопределенный метод getItemid, если вы возвращаете 0, что вызывает проблему. Попытка возврата mThumbIds [position] Я думаю, это поможет вам.

веселит.

1 голос
/ 07 октября 2011

В классе ImageAdapter в методе getView добавьте следующую строку кода

imageView.setId(mThumbIds[postion]);

или другой параметр в вашем Onclick слушателе gridview внутри по методу клика

source = (new Long(id)).toString();

заменить эту строку кода на

source = parent.getItemId(position);

Теперь это определенно решит проблему.

0 голосов
/ 10 октября 2011

изменить

  if(c!=null)
    {

       while(c.moveToNext()){
           String infoItem = c.getString( ColumnIndex );
           infoList.add(Integer.parseInt(infoItem));
       }
    }

на

if(c!=null)
        {

           while(!c.isAfterLast()){
               String infoItem = c.getString( ColumnIndex );
               infoList.add(Integer.parseInt(infoItem));
               c.moveToNext();
           }
        }
...