Я новичок в Android и мне нужно использовать ListView для моего проекта. Я использую пример из Интернета, в котором нет открытого класса для ListView, поэтому я не могу гибко кодировать. Как я могу написать публичный класс для этого.

public class LIGHTS extends AppCompatActivity {

    ListView users_list;
    private DatabaseManager dbManager;
    private SimpleCursorAdapter adapter;
    private DatabaseHelper dbHelper;

    final String[] from = new String[]{dbHelper._ID, dbHelper.TITLE, dbHelper.DESC};
    final int[] to = new int[]{R.id.id, R.id.KEYCODE, R.id.NAME};

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

        dbManager = new DatabaseManager(this);
        dbManager.open();
        Cursor cursor = dbManager.fetch();

        users_list = findViewById(R.id.users_list);

        adapter = new SimpleCursorAdapter(this, R.layout.adapter, cursor, from, to, 0);
        users_list.setAdapter(adapter);}

И fetch () находится в следующем коде в dbmanager:

    public Cursor fetch() {
        String[] columns = new String[]{dbHelper._ID, dbHelper.TITLE, dbHelper.DESC};
        Cursor cursor = database.query(dbHelper.TABLE_NAME, columns, null, null, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
        }
        return cursor;
    }
0
Alireza Ma 10 Май 2019 в 19:58

2 ответа

Лучший ответ

Вот пример, основанный на вашем коде, который обрабатывает нажатие кнопки для каждого элемента в списке.

Если вы щелкнете по переключателю, то он отобразит идентификатор элемента через тост.

При этом используется пользовательский адаптер на основе (расширяет) класс CursorAdapter.

Во-первых, макет adaptor.xml , используемый для элемента (должен иметь основную информацию и включать переключатель, идентификатор которого - the_switch): -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <TextView
        android:id="@+id/id"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/KEYCODE"
        android:layout_width="0dp"
        android:layout_weight="2"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/NAME"
        android:layout_width="0dp"
        android:layout_weight="6"
        android:layout_height="wrap_content" />
    <Switch
        android:id="@+id/the_switch"
        android:layout_width="0dp"
        android:layout_weight="1"
        android:layout_height="wrap_content"
        android:focusable="false"
        />
</LinearLayout>

Активность Lights.java теперь:

public class Lights extends AppCompatActivity {

    ListView users_list, alt_users_list;
    private DatabaseManager dbManager;
    private MyCustomCursorAdapter adapter;
    //private DatabaseManager dbHelper; //?????? a second not needed
    Cursor cursor;
    Context mContext;

    //<<<<<<<<<< Not needed although could be passed
    //final String[] from = new String[]{DatabaseManager._ID, DatabaseManager.TITLE, DatabaseManager.DESC};
    //final int[] to = new int[]{R.id.id, R.id.KEYCODE, R.id.NAME};

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mContext = this;
        setContentView(R.layout.activity_lights);
        startconnection(); //?????? dummied out
        users_list = findViewById(R.id.users_list);
        alt_users_list = findViewById(R.id.alt_users_list);

        dbManager = new DatabaseManager(this);
        dbManager.open();
        manageListView(); //Handles the ListView
    }

    // Moved here handles list refresh if called (e.g. in onResume)
    private void manageListView() {
        cursor = dbManager.fetch();
        //Setup the adapter if not already setup else swaps (refreshes) the cursor
        if (adapter == null) {
            adapter = new MyCustomCursorAdapter(this, cursor);
            users_list.setAdapter(adapter);
            users_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
                @Override
                public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                    Toast.makeText(mContext,"You clicked on the item with an ID of " + String.valueOf(id),Toast.LENGTH_SHORT).show();
                }
            });
        } else {
            adapter.swapCursor(cursor);
        }
    }
    private void startconnection(){}

    @Override
    protected void onDestroy() {
        super.onDestroy();
        // Close the Cursors when done with them
        cursor.close();
    }

    @Override
    protected void onResume() {
        super.onResume();
        // Refresh the listviews when returning to the activity
        manageListView();
    }
}
  • Комментарии пытаются объяснить изменения (в основном это очень похоже).
  • Самое большое изменение заключается в том, что настройка просмотра списка была перенесена в собственный метод, который также обрабатывает обновление просмотра списка (его повторное отображение после изменения базовых данных).
  • Создание экземпляра адаптера также проще, чем для SimpleCursorAdapter (макет и столбец для просмотра обработки, закодированной в адаптере).

Адаптер myCustomAdapter.java :

public class MyCustomCursorAdapter extends CursorAdapter {

    public MyCustomCursorAdapter(Context context, Cursor c) {
        super(context, c, 0);
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);
        if (position % 2 == 0) {
            view.setBackgroundColor(0xFFAAAAFF);
        } else {
            view.setBackgroundColor(0xAAAAAAFF);
        }
        return view;
    }

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

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ((TextView)view.findViewById(R.id.id)).setText(cursor.getString(cursor.getColumnIndex(DatabaseManager._ID)));
        ((TextView)view.findViewById(R.id.KEYCODE)).setText(cursor.getString(cursor.getColumnIndex(DatabaseManager.TITLE)));
        ((TextView)view.findViewById(R.id.NAME)).setText(cursor.getString(cursor.getColumnIndex(DatabaseManager.DESC)));

        Switch thisswitch = view.findViewById(R.id.the_switch);
        thisswitch.setTag(cursor.getString(cursor.getColumnIndex(DatabaseManager._ID)));
        thisswitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                Toast.makeText(buttonView.getContext(),
                        "You clicked the switch for ID " + (String) buttonView.getTag() +
                                " the status is now " + (new Boolean(isChecked)).toString(),
                        Toast.LENGTH_SHORT)
                        .show()
                ;
            }
        });
    }
}
  • bindView в первую очередь был использован это: -
    • привязывает значения из столбцов курсора к представлениям для каждого элемента
    • и в этом случае устанавливает тег переключателя на id, а затем добавляет onCheckChangedListener для Button.
  • bindView имеет то преимущество, что ему передаются курсор и контекст.
  • Также можно использовать getView, он имеет преимущество в том, что позиция элемента в списке передается.
  • В этом случае он использовался для чередования цвета фона для каждого элемента.

Результат

Вот снимок экрана, показывающий тост (данные тестирования заметки были добавлены в базовую базу данных, так что это, очевидно, будет отличаться от вашей):

enter image description here

Дополнительные

Может случиться так, что вам нужно обработать изменение проверки переключателя в собственном действии.

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

Сначала интерфейс myOnCheckedChangedInterface.java

public interface myOnCheckedChangedInterface {
    void myOnCheckedChangedHandler(String id, boolean check_status);
}

Второе изменение Lights.java , добавив метод-обработчик myOnCheckedChangedHandler .

@Override
public void myOnCheckedChangedHandler(String id, boolean check_status) {
    Toast.makeText(
            this,
            "You changed the status for the row with an id of " + id +
                    " the status is now " + new Boolean(check_status).toString(),
            Toast.LENGTH_SHORT).show();
}
  • Проигнорируйте ошибку, что метод не переопределяет метод из его суперкласса.

В-третьих, измените объявление Class для реализации интерфейса, добавив implements myOnCheckedChangedInterface в соответствии с: -

public class Lights extends AppCompatActivity implements myOnCheckedChangedInterface {

Наконец, измените MyCustomCursorAdapter, чтобы иметь возможность вызывать myOnCheckedChangedHandler

Например

public class MyCustomCursorAdapter extends CursorAdapter {
    Lights calling_activity; //<<<<<<<<<<@@@@@@@@@@@ ADDED for interface

    public MyCustomCursorAdapter(Context context, Cursor c) {
        super(context, c, 0);
        this.calling_activity = (Lights) context; //<<<<<<<<<<@@@@@@@@@@@ ADDED for interface
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View view = super.getView(position, convertView, parent);
        if (position % 2 == 0) {
            view.setBackgroundColor(0xFFAAAAFF);
        } else {
            view.setBackgroundColor(0xAAAAAAFF);
        }
        return view;
    }

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

    @Override
    public void bindView(View view, Context context, Cursor cursor) {
        ((TextView)view.findViewById(R.id.id)).setText(cursor.getString(cursor.getColumnIndex(DatabaseManager._ID)));
        ((TextView)view.findViewById(R.id.KEYCODE)).setText(cursor.getString(cursor.getColumnIndex(DatabaseManager.TITLE)));
        ((TextView)view.findViewById(R.id.NAME)).setText(cursor.getString(cursor.getColumnIndex(DatabaseManager.DESC)));

        Switch thisswitch = view.findViewById(R.id.the_switch);
        thisswitch.setTag(cursor.getString(cursor.getColumnIndex(DatabaseManager._ID)));
        thisswitch.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                /**
                Toast.makeText(buttonView.getContext(),
                        "You clicked the switch for ID " + (String) buttonView.getTag() +
                                " the status is now " + (new Boolean(isChecked)).toString(),
                        Toast.LENGTH_SHORT)
                        .show()
                **/
                calling_activity.myOnCheckedChangedHandler((String)buttonView.getTag(),isChecked); //<<<<<<<<<<@@@@@@@@@@@ ADDED for interface
            }
        });
    }
}
  • Смотрите комментарии с помощью // <<<<<<<<<< @@@@@@@@@@@ ДОБАВЛЕНО для интерфейса для изменений
  • Оригинальный тост был закомментирован, так как он больше не нужен
  • Обратите внимание, что это не самый простой способ, поскольку адаптер привязан к активности Lights, это просто простой пример.
0
MikeT 11 Май 2019 в 07:36

Чтобы настроить ListAdapter, вам нужно создать свой собственный класс ListAdapter, который основан или «расширяет» встроенный ListAdapter (такой как SimpleListAdapter или BaseAdapter). Затем вы можете настроить внешний вид и какие поля данных для отображения. Ниже приведен пример пользовательского ListAdapter, который я назвал ClaimsListAdapter.java, который «расширяет» встроенный класс BaseAdapter:

package com.mycompany.myapp.adapter;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;

import com.mycompany.myapp.ClaimListFragment;
import com.mycompany.myapp.R;
import com.mycompany.myapp.TripListFragment;
import com.mycompany.myapp.model.ClaimItem;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.View.OnClickListener;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.TextView;

// You might be able to extend SimpleListAdapter instead if you wish
public class ClaimListAdapter extends BaseAdapter {

    private Context context;
    private ArrayList<ClaimItem> claimItems;
    ClaimListFragment fragment;

    //I'm passing references to both the active Context as well as the active Fragment
    //You might only need to pass the active Context
    public ClaimListAdapter(ClaimListFragment fragment, Context context, ArrayList<ClaimItem> claimItems){
        this.context = context;
        this.claimItems = claimItems;
        this.fragment = fragment;
    }

    @Override
    public int getCount() {
        return claimItems.size();
    }

    @Override
    public Object getItem(int position) {       
        return claimItems.get(position);
    }

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

    @SuppressLint("InflateParams")
    @Override
    public View getView(int position, View convertView, ViewGroup parent) {

        if (convertView == null) {
            LayoutInflater mInflater = (LayoutInflater)
                    context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
            //This is the layout for the list item.  A SimpleListAdapter doesn't need one
            //since it only has one text view, but this allows you to create multiple lines
            //and/or multiple fields, buttons, checkboxes etc if you wish
            convertView = mInflater.inflate(R.layout.claim_list_item, null);
        }

        //Get a reference to all of the items in the layout you wish to change
        Button btnDelete = (Button) convertView.findViewById(R.id.claim_delete_in_list);
        //Note, here I'm saving the row number in the tag of the button to tell the fragment
        //which row in the array to delete.
        btnDelete.setTag(position);
        //Here is an example of setting a click listener for a button in the list
        btnDelete.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {
                Integer position = (Integer)v.getTag();
                //Call the Public method in the parent Fragment (or Activity) to delete from the
                //array and refresh the list
                fragment.deleteItemList(position);
            }
        });

        btnDelete.setVisibility(View.GONE);

        //Get a reference to all of the text fields in the list item
        TextView txtTitle = (TextView) convertView.findViewById(R.id.claim_title);
        TextView txtStatus = (TextView) convertView.findViewById(R.id.claim_status);
        TextView txtDate = (TextView) convertView.findViewById(R.id.claim_date);
        TextView txtDistance = (TextView) convertView.findViewById(R.id.claim_distance);
        TextView txtAmount = (TextView) convertView.findViewById(R.id.claim_amount);

        String claim_title = claimItems.get(position).getDocumentID();
        String claim_status = claimItems.get(position).getClaimStatus();

        txtTitle.setText(claim_title);
        txtStatus.setText(claim_status);

        return convertView;
    }

}

И файл layout_list_item.xml:

<?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="wrap_content" 
    android:baselineAligned="false"
    android:orientation="horizontal">

    <LinearLayout
        android:id="@+id/whole_layout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.7"
        android:background="@drawable/list_selector_light"
        android:orientation="vertical" >

        <LinearLayout
            android:id="@+id/top_layout"
            android:layout_width="match_parent"
            android:layout_height="20dp"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="5dp"
            android:layout_weight="0.48"
            android:background="#00000000"
            android:orientation="horizontal" >

            <TextView
                android:id="@+id/claim_title"
                android:layout_width="match_parent"
                android:layout_height="20dp"
                android:layout_marginBottom="2dp"
                android:layout_marginLeft="5dp"
                android:layout_marginStart="5dp"
                android:layout_marginRight="5dp"
                android:layout_marginEnd="5dp"
                android:layout_weight="0.73"
                android:background="#00000000"
                android:gravity="start|center_vertical"
                android:text=""
                android:textColor="#FFFFFFFF"
                android:textSize="16sp" />

            <TextView
                android:id="@+id/claim_status"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginBottom="2dp"
                android:layout_marginEnd="5dp"
                android:layout_marginRight="5dp"
                android:background="#00000000"
                android:gravity="end|center_vertical"
                android:text=""
                android:textColor="#FFFFFFFF"
                android:textSize="14sp" />

        </LinearLayout>

        <LinearLayout
            android:id="@+id/bottom_layout"
            android:layout_width="match_parent"
            android:layout_height="20dp"
            android:layout_marginBottom="5dp"
            android:layout_marginTop="5dp"
            android:layout_weight="0.48"
            android:background="#00000000"
            android:orientation="horizontal" >

            <TextView
                android:id="@+id/claim_date"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginLeft="5dp"
                android:layout_marginStart="5dp"
                android:background="#00000000"
                android:gravity="start|center_vertical"
                android:text=""
                android:textColor="#FFFFFFFF"
                android:textSize="14sp" />

            <TextView
                android:id="@+id/claim_distance"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_marginLeft="50dp"
                android:layout_marginStart="50dp"
                android:layout_marginRight="50dp"
                android:layout_marginEnd="50dp"
                android:layout_weight="1.0"
                android:layout_gravity="center"
                android:background="#00000000"
                android:gravity="center|center_vertical"
                android:text=""
                android:textSize="12sp"
                android:textColor="#FFFFFFFF"/>

            <TextView
                android:id="@+id/claim_amount"
                android:layout_width="wrap_content"
                android:layout_height="match_parent"
                android:layout_marginBottom="2dp"
                android:layout_marginEnd="5dp"
                android:layout_marginRight="5dp"
                android:background="#00000000"
                android:gravity="end|center_vertical"
                android:text=""
                android:textColor="#FFFFFFFF"
                android:textSize="12sp" />

         </LinearLayout>
     </LinearLayout>

     <Button
        android:id="@+id/claim_delete_in_list"
        android:layout_width="100dp"
        android:layout_height="match_parent"
        android:layout_weight="0.3"
        android:text="@string/delete"
        android:textSize="16sp"
        android:textColor="#FFFFFFFF"
        android:background="@android:color/holo_red_dark"
        />

</LinearLayout>
0
Michael Dougan 10 Май 2019 в 17:41