Member 9687317 Ответов: 2

Как прикрепить onitemclicklistener к customlistview в android studio


Я создал пользовательский ListView, который отображает данные из базы данных SQLite с помощью customCursorAdapter, который расширяет CursorAdapter, а затем добавил OnItemClickListener в ListView, но когда я нажимаю на элемент в ListView, ничего не происходит

Что я уже пробовал:

и вот что я попробовал
во-первых: макет для пользовательского элемента списка
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layoutDirection="rtl">

    <TextView
        android:id="@+id/txtLICustomerName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/ibDeleteCustomer"
        android:layout_alignBottom="@id/ibDeleteCustomer"
        android:layout_alignParentStart="true"
        android:layout_toStartOf="@id/ibUpdateCustomer"
        android:text=""
        android:textSize="24dp" />

    <TextView
        android:id="@+id/txtLICustomerBalance"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/txtLICustomerName"
        android:layout_alignParentStart="true"
        android:text=""
        android:textSize="24dp" />

    <ImageButton
        android:id="@+id/ibDeleteCustomer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:src="@drawable/ic_close_black_48dpn" />

    <ImageButton
        android:id="@+id/ibUpdateCustomer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toStartOf="@+id/ibDeleteCustomer"
        android:src="@drawable/ic_create_black_48dpn" />

    <ImageButton
        android:id="@+id/ibCallCustomer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toStartOf="@+id/ibUpdateCustomer"
        android:src="@drawable/ic_call_black_48dpn" />

    <ImageButton
        android:id="@+id/ibViewCustomerDetails"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignStart="@id/ibDeleteCustomer"
        android:layout_alignTop="@id/txtLICustomerBalance"
        android:layout_alignEnd="@id/ibDeleteCustomer"
        android:src="@drawable/ic_chrome_reader_mode_black_48dpn" />

</RelativeLayout>


второе: в планировку активности, который содержит элемент управления 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"

    xmlns:app="http://schemas.android.com/apk/res-auto"

    android:orientation="vertical"

    android:layout_width="match_parent"

    android:layout_height="match_parent"

    android:layoutDirection="rtl"

    tools:context=".ViewCustomersActivity">

    <TextView

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_marginTop="5dp"

        android:layout_marginStart="5dp"

        android:layout_gravity="start"

        android:background="@android:color/holo_blue_bright"

        android:textColor="@color/colorBlue"

        android:text="@string/stringChooseCustomer"

        android:textSize="24sp" />

    <ListView

        android:id="@+id/lstCustomers"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:layout_marginStart="8dp"

        android:layout_gravity="start"

        android:textDirection="rtl" />

</LinearLayout>


Третье: пользовательский адаптер курсора
package com.nsystems.elkest;

import android.content.Context;
import android.database.Cursor;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CursorAdapter;
import android.widget.ImageButton;
import android.widget.TextView;

public class CustomerCursorAdapter extends CursorAdapter {
    public CustomerCursorAdapter(Context context, Cursor c, boolean autoRequery) {
        super(context, c, autoRequery);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(R.layout.customer_list_row, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView txtLICustomerName = (TextView)view.findViewById(R.id.txtLICustomerName);
        TextView txtLICustomerBalance = (TextView)view.findViewById(R.id.txtLICustomerBalance);

        ImageButton ibUpdateCustomer = (ImageButton)view.findViewById(R.id.ibUpdateCustomer);
        ImageButton ibDeleteCustomer = (ImageButton)view.findViewById(R.id.ibDeleteCustomer);
        ImageButton ibCallCustomer = (ImageButton)view.findViewById(R.id.ibCallCustomer);
        ImageButton ibViewCustomerDetails = (ImageButton)view.findViewById(R.id.ibViewCustomerDetails);

        String customerName="";
        String customerBalance="";
        String customerId="";
        String customerPhone="01287622467";

        customerId = Long.toString(cursor.getLong(0));
        customerName = cursor.getString(1);
        customerBalance = cursor.getString(2);

        txtLICustomerName.setText(customerName);
        txtLICustomerBalance.setText(customerBalance);

        ibCallCustomer.setTag(customerPhone);
        ibDeleteCustomer.setTag(customerId);
        ibUpdateCustomer.setTag(customerId);
        ibViewCustomerDetails.setTag(customerId);
    }

}


Четвертое: деятельность, которая соединяет их всех
package com.nsystems.elkest;

import android.content.Intent;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.database.sqlite.SQLiteQueryBuilder;
import android.graphics.Color;
import android.os.AsyncTask;
import android.support.annotation.ColorRes;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.nsystems.elkest.Data.KestSQLiteHelper;

public class ViewCustomersActivity extends AppCompatActivity {

    long townId;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_view_customers);

        Intent intentCaller = getIntent();
        townId = intentCaller.getLongExtra("TownId", 0);
        new getCustomersAsyncTask().execute(townId);

        AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Toast.makeText(ViewCustomersActivity.this,"hiiiiiiiiiii",Toast.LENGTH_LONG).show();
                /*int customerBalance;
                String customerName;
                String balance;
                customerName = ((TextView) view.findViewById(R.id.txtLICustomerName)).getText().toString();
                Toast.makeText(ViewCustomersActivity.this,customerName,Toast.LENGTH_LONG).show();
                balance = ((TextView) view.findViewById(R.id.txtLICustomerBalance)).getText().toString();
                if (balance.isEmpty())
                    balance = "0";
                Toast.makeText(ViewCustomersActivity.this,balance,Toast.LENGTH_LONG).show();
                customerBalance = Integer.valueOf(balance);
                Intent intentStartTransactionActivity = new Intent(ViewCustomersActivity.this, TransactionActivity.class);
                intentStartTransactionActivity.putExtra("TownId", townId);
                intentStartTransactionActivity.putExtra("CustomerId", id);
                intentStartTransactionActivity.putExtra("CustomerName", customerName);
                intentStartTransactionActivity.putExtra("CustomerBalance", customerBalance);
                startActivity(intentStartTransactionActivity);*/
            }
        };
        ListView lstOfCustomers = (ListView) findViewById(R.id.lstCustomers);
        lstOfCustomers.setOnItemClickListener(itemClickListener);
    }

    @Override
    protected void onResume() {
        super.onResume();
        new getCustomersAsyncTask().execute(townId);
    }




    private class getCustomersAsyncTask extends AsyncTask<Long, Void, Result> {
        ListView lstCustomers;
        Cursor cursorCustomers;

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            lstCustomers = (ListView) findViewById(R.id.lstCustomers);
        }

        @Override
        protected Result doInBackground(Long... longs) {
            Result result = new Result();
            SQLiteOpenHelper kestDataBaseHelper = new KestSQLiteHelper(ViewCustomersActivity.this);
            try {
                SQLiteDatabase dbKest = kestDataBaseHelper.getReadableDatabase();
                SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
                queryBuilder.setTables("Customer LEFT OUTER JOIN MoneyTrans ON Customer._id = MoneyTrans.Customer_id AND Customer.Closed=0 AND MoneyTrans.Closed=0");
                cursorCustomers = queryBuilder.query(dbKest,
                        new String[]{"Customer._id", "Customer.Customer_Name", "SUM(Money)"},
                        "Customer.Town_id=?", new String[]{Long.toString(longs[0])},
                        "Customer.Customer_Name", null, "Customer._id");
                result.setSuccess(true);
                return result;
            } catch (Exception exception) {
                result.setSuccess(false);
                result.setException(exception);
                return result;
            }
        }

        @Override
        protected void onPostExecute(Result result) {
            super.onPostExecute(result);

            if (result.isSuccess()) {
                CustomerCursorAdapter adapterLstTowns= new CustomerCursorAdapter(ViewCustomersActivity.this, cursorCustomers,true);
                lstCustomers.setAdapter(adapterLstTowns);

                /*lstCustomers.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                    @Override
                    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                        Toast.makeText(ViewCustomersActivity.this,"Hiiiiiiiiiiiiiiiiiiii2",Toast.LENGTH_LONG).show();
                    }
                });*/
            } else {
                Toast toast = Toast.makeText(ViewCustomersActivity.this, result.getException().getMessage().toString(), Toast.LENGTH_LONG);
                toast.show();
            }
        }
    }
}

David Crow

Просто предположение, но с тех пор adapterLstTowns и cursorCustomers оба являются местными жителями getCustomersAsyncTask, когда эта задача выходит за рамки, возможно, эти локальные переменные тоже выходят за рамки. Попробуйте перенести их на основное занятие.

Member 9687317

Нет, сэр, это не сработало

2 Ответов

Рейтинг:
12

Member 9687317

просто добавить

android:descendantFocusability="blocksDescendants"

в XML-файл, описывающий строку пользовательского списка


Рейтинг:
0

TheOldFogie

Я считаю, что ваша проблема заключается в том, что ImageButtons ловят в ловушку onClickEvents, попробуйте изменить ImageButtons к ImageViews напр.


<ImageView
        android:id="@+id/ibDeleteCustomer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:src="@drawable/ic_launcher_foreground"
        />


Вместе с :-

ImageView ibUpdateCustomer = (ImageView) view.findViewById(R.id.ibUpdateCustomer);
ImageView ibDeleteCustomer = (ImageView) view.findViewById(R.id.ibDeleteCustomer);
ImageView ibCallCustomer = (ImageView) view.findViewById(R.id.ibCallCustomer);
ImageView ibViewCustomerDetails = (ImageView) view.findViewById(R.id.ibViewCustomerDetails);


Однако

Я подозреваю, что вы хотите обрабатывать кнопки/представления по отдельности. Это настройка ListView onItemClick слушатель, согласно вашему текущему коду, обрабатывает элемент***, а не конкретную кнопку/представление внутри элемента. Таким образом, приведенное выше исправление вызовет тост, но представление, возвращаемое слушателем, будет RelativeLayout. Вы не сможете узнать, какая кнопка была нажата и, следовательно, какое действие (обновление/удаление/вызов или просмотр) предпринять.

То, что вам нужно сделать, если вы хотите обрабатывать сами кнопки/представления, задано onCLickListeners для кнопок/представлений, чтобы обрабатывать их щелчок.

Быстрый, но обескураженный способ состоит в том, чтобы использовать функция onclick атрибут в XML.

например :-

С помощью :-

<ImageView
    android:id="@+id/ibDeleteCustomer"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_alignParentEnd="true"
    android:layout_alignParentRight="true"
    android:src="@drawable/ic_launcher_foreground"
    android:onClick="doDeleteOnClick"
    />


смотрите последнюю строку

А затем добавьте следующее к коду действия :-

public void doDeleteOnClick(View v) {
        Toast.makeText(v.getContext(),"You clicked the delete button for id " + ((String) v.getTag()), Toast.LENGTH_SHORT).show();
    }


Выдаст тост для соответствующей строки, отображая идентификатор, полученный из тега.

рабочий пример

Следующий код является рабочим примером, который обрабатывает щелчки элементов ListView (путем добавления строки в базу данных и, таким образом, обновленного ListView), а также щелчки ImageView (путем Тостирования сообщения, специфичного для кнопки).

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

customer_list_row.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layoutDirection="rtl">

    <TextView
        android:id="@+id/txtLICustomerName"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@id/ibDeleteCustomer"
        android:layout_alignBottom="@id/ibDeleteCustomer"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:layout_toStartOf="@id/ibUpdateCustomer"
        android:layout_toLeftOf="@+id/ibUpdateCustomer"
        android:text=""
        android:textSize="24dp" />

    <TextView
        android:id="@+id/txtLICustomerBalance"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@id/txtLICustomerName"
        android:layout_alignParentStart="true"
        android:layout_alignParentLeft="true"
        android:text=""
        android:textSize="24dp" />

    <ImageView
        android:id="@+id/ibDeleteCustomer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentEnd="true"
        android:layout_alignParentRight="true"
        android:src="@drawable/ic_launcher_foreground"
        android:onClick="doDeleteOnClick"
        />

    <ImageView
        android:id="@+id/ibUpdateCustomer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toStartOf="@+id/ibDeleteCustomer"
        android:layout_toLeftOf="@+id/ibDeleteCustomer"
        android:src="@drawable/ic_launcher_foreground"
        android:onClick="doUpdateOnClick"
        />

    <ImageView
        android:id="@+id/ibCallCustomer"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toStartOf="@+id/ibUpdateCustomer"
        android:layout_toLeftOf="@+id/ibUpdateCustomer"
        android:src="@drawable/ic_launcher_foreground"
        android:onClick="doCallOnCLick"
        />

    <ImageView
        android:id="@+id/ibViewCustomerDetails"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignStart="@id/ibDeleteCustomer"
        android:layout_alignLeft="@+id/ibDeleteCustomer"
        android:layout_alignTop="@id/txtLICustomerBalance"
        android:layout_alignEnd="@id/ibDeleteCustomer"
        android:layout_alignRight="@+id/ibDeleteCustomer"
        android:src="@drawable/ic_launcher_foreground"
        android:onClick="doViewOnClick"
        />
</RelativeLayout>


CustomerCursorAdapter.java

public class CustomerCursorAdapter extends CursorAdapter {

    public CustomerCursorAdapter(Context context, Cursor c, boolean autoRequery) {
        super(context, c, autoRequery);
    }

    @Override
    public View newView(Context context, Cursor cursor, ViewGroup parent) {
        return LayoutInflater.from(context).inflate(R.layout.customer_list_row, parent, false);
    }

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        TextView txtLICustomerName = (TextView)view.findViewById(R.id.txtLICustomerName);
        TextView txtLICustomerBalance = (TextView)view.findViewById(R.id.txtLICustomerBalance);

        ImageView ibUpdateCustomer = (ImageView) view.findViewById(R.id.ibUpdateCustomer);
        ImageView ibDeleteCustomer = (ImageView) view.findViewById(R.id.ibDeleteCustomer);
        ImageView ibCallCustomer = (ImageView) view.findViewById(R.id.ibCallCustomer);
        ImageView ibViewCustomerDetails = (ImageView)view.findViewById(R.id.ibViewCustomerDetails);

        String customerName="";
        String customerBalance="";
        String customerId="";
        String customerPhone="01287622467";

        customerId = Long.toString(cursor.getLong(0));
        customerName = cursor.getString(1);
        customerBalance = cursor.getString(2);

        txtLICustomerName.setText(customerName);
        txtLICustomerBalance.setText(customerBalance);

        ibCallCustomer.setTag(customerPhone);
        ibDeleteCustomer.setTag(customerId);
        ibUpdateCustomer.setTag(customerId);
        ibViewCustomerDetails.setTag(customerId);
    }
}


MainActivity.java (эквивалент ViewCustomersActivity)

public class MainActivity extends AppCompatActivity {

    long townId;
    KestSQLiteHelper kestDB;
    Cursor cursor;
    CustomerCursorAdapter adapterLstTowns;
    ListView lstOfCustomers;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        lstOfCustomers = this.findViewById(R.id.lstCustomers);
        kestDB = new KestSQLiteHelper(this);
        addSomeData(); // Add some testing data

        //Intent intentCaller = getIntent();
        townId =  /*intentCaller.getLongExtra("TownId", 0); */  1;
        //new getCustomersAsyncTask().execute(townId);
        //More of your code
    }

    @Override
    protected void onResume() {
        super.onResume();
        manageListView(); // Refreshes the listview when resuming (
        // note that onResume is called when the App is started so this invokes the initialiastion of thw adapter/listview)
        //new getCustomersAsyncTask().execute(townId);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (!cursor.isClosed()) {
            cursor.close();
        }
    }

    /**
     * Handles management of the ListView setting up the adapter,
     * tying it to the ListView and setting the onItemClick listener once when the activity is started
     * subsequently, when called it just refreshes the ListView by swapping the Cursor
     */
    public void manageListView() {
        cursor = getDataForListView();
        if (adapterLstTowns == null) {
            adapterLstTowns = new CustomerCursorAdapter(this,cursor,true);
            lstOfCustomers.setAdapter(adapterLstTowns);
            lstOfCustomers.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast.makeText(view.getContext(),"Hiiiiiiiiiiiiiiiiiiii2",Toast.LENGTH_SHORT).show();
                    kestDB.addCustomer("ANOTHER" + String.valueOf(System.currentTimeMillis()),300);
                    manageListView();
                }
            });
        } else {
            adapterLstTowns.swapCursor(cursor);
        }
    }

    /**
     * Handle the ibDeleteCustomer view being clicked.
     */
    public void doDeleteOnClick(V


Member 9687317

Кнопки изображения не захватывают onClickEvents, на самом деле я обрабатываю щелчки кнопок без проблем, проблема в том, что когда я нажимаю на элемент списка (а не на кнопки в нем), ничего не происходит

TheOldFogie

Этот вопрос был обновлен с помощью рабочего примера доказательства концепции. То есть если вы создадите приложение с рабочим примером, то увидите, что оно демонстрирует захват как элемента, так и кнопки (ImageView) щелчков. Если вы затем просто измените ImageView на ImageButtons, то рабочий пример будет ловить только щелчки кнопок. Существуют параметры XML, которые позволяют обрабатывать события Item onClick. Однако мне проще использовать представления, а не кнопки. (Я думаю, что descendantFocusability-это один из атрибутов, который необходимо настроить и, возможно, сделать кликабельным.)

Member 9687317

Правильно, я нашел решение на stackOverflow.com
добавьте android:descendantFocusability="blocksDescendants" в XML-файл
спасибо за вашу помощь.