Android Spinner Footer - PullRequest
       2

Android Spinner Footer

1 голос
/ 10 августа 2011

Есть ли способ добавить нижний колонтитул в выпадающий список счетчика?Например, скажем, я заполняю счетчик из базы данных, но я хочу, чтобы выборка находилась внизу списка независимо от того, как я упорядочил список.Список может быть «Элемент базы данных 1, 2 .., 3 ...», а в нижней части списка находится нижний колонтитул «Добавить элемент в базу данных».

До сих пор я использовал ваш класс CustomSpinner.следующим образом:

public class CustomSpinner extends Spinner implements OnItemClickListener {

private AlertDialog myDialog = null;
private OnClickListener myButtonClickListener = null;
private GrainSpinnerAdapter adapter = null;

public CustomSpinner(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public void setButtonClickListener(OnClickListener listener) {
    myButtonClickListener = listener;
}

public void setAdapter(GrainSpinnerAdapter adapter){
    this.adapter = adapter;
}

@Override
public boolean performClick() {
    Context context = getContext();

    //Inflate the layout
    final LayoutInflater inflater = LayoutInflater.from(getContext());
    final View v = inflater.inflate(R.layout.my_custom_spinner, null);

    // set up list view
    final ListView lv = (ListView) v.findViewById(R.id.list);
    lv.setAdapter(adapter);
    lv.setSelection(getSelectedItemPosition());
    lv.setOnItemClickListener(this);

    // set up button
    final Button btn = (Button) v.findViewById(R.id.addButton);
    btn.setOnClickListener(myButtonClickListener);

    // build our dialog
    AlertDialog.Builder builder = new AlertDialog.Builder(context);

    // show prompt, just as our Spinner parent does
    if (getPrompt() != null) {
        builder.setTitle(getPrompt());
    }

    // create and show dialog
    myDialog = builder.setView(v).create();
    myDialog.show();

    return true;
}

@Override
public void onItemClick(AdapterView<?> view, View itemView, int position, long id) {
    setSelection(position);
    if (myDialog != null) {
        myDialog.dismiss();
        myDialog = null;
    }

}

} Я хочу использовать отдельный адаптер, такой как этот:

public class GrainListAdapter extends SimpleCursorAdapter {

private static final String DEFAULT_UNITS = "American";
private Button upButton;
private Context myContext;
private RecipeGrainActivity parentActivity;
private Button downButton;
private String units;
private double getLbs;

public GrainListAdapter(Context context, int layout, Cursor c, String[] from, int[] to) {
    super(context, layout, c, from, to);
    myContext = context;
    parentActivity = (RecipeGrainActivity) myContext;

    //Checks for metric pref.
    SharedPreferences myPrefs = PreferenceManager.getDefaultSharedPreferences(context);
    units = String.valueOf(myPrefs.getString(context.getString(R.string.pref_measurement), DEFAULT_UNITS));
}

@Override
public void bindView(View view, Context context, Cursor cursor) {
    int idColumn = cursor.getColumnIndex("_id");
    final int getId = cursor.getInt(idColumn);
    final double increment = 0.25;

    UnitsConversions convert = new UnitsConversions();

    int nameColumn = cursor.getColumnIndex("name");
    String getName = cursor.getString(nameColumn);
    TextView name = (TextView)view.findViewById(R.id.GrainName);
    name.setText(getName);

    int originColumn = cursor.getColumnIndex("origin");
    String getOrigin = cursor.getString(originColumn);
    TextView origin = (TextView)view.findViewById(R.id.GrainOrigin);
    origin.setText(getOrigin);

    if(units.equals("Metric")){
        //Sets labels to metric.
        String kilos = context.getResources().getString (R.string.kilograms);
        TextView weightLabel = (TextView)view.findViewById(R.id.GrainLbsLabel);
        weightLabel.setText(kilos);
    }


}

@Override
public View newView(Context context, Cursor cursor, final ViewGroup parent) {
    View view = View.inflate(context, R.layout.grain_list_item, null);
    return view;
}

}

, который позволяет мне создавать пользовательские строки длякаждый список в спиннер.Я думал, что смогу установить адаптер на CustomSpinner, используя обычайpinpinner.setadapter () в своей деятельности.Однако ListView, определенный в классе CustomSpinner, использует адаптер, указанный в классе.Как передать адаптер в класс, чтобы он мог его использовать?

Вот как я должен был добавить пользовательский элемент в свой макет:

<com.bluelightuniverse.android.brewmobile.CustomSpinner
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:id="@+id/GrainNameSpinner"
    android:layout_toRightOf="@id/GrainOriginSpinner"
    android:layout_toLeftOf="@+id/AddGrainButton">
</com.bluelightuniverse.android.brewmobile.CustomSpinner>

Ответы [ 3 ]

8 голосов
/ 07 декабря 2011

в вашем CursorAdapter, переопределите методы getCount () и getDropDownView: Например, если вы хотите поставить кнопку в конце, вы можете сделать это:

new SimpleCursorAdapter(...) {

        @Override
        public int getCount() {
            return super.getCount()+1;
        }

        @Override
        public View getDropDownView(int position, View convertView,
                ViewGroup parent) {
            View res=null;
            if (position == getCount()-1) {
                //better not try to reuse our view as it can be requested for the spinner or by the list with different kind of layouts.
                View mButton= getActivity().getLayoutInflater().inflate(R.layout.create_activity_button, parent,false);
                mButton.setOnClickListener(ObservationListFragment.this);
                res= mButton;
            } else if (convertView != null && android.R.id.button1 == convertView.getId() ){
             // If the adapter is trying to recycle our footer view, we force the generation of a new view (check on the id of our custom view)
                res= super.getDropDownView(position, null, parent);
            } else {
                res= super.getDropDownView(position, convertView, parent);
            }
            return res;
        }
    };
0 голосов
/ 10 августа 2011

Я экспериментировал с созданием более сложных представлений в диалогах Spinners.

Чтобы сделать то, что вы объяснили, я создал подкласс Spinner.Я изучил источник устройства Spinner для Android и переопределил performClick, чтобы выполнить, по сути, то, что вам нужно: заполнить собственный диалог пользовательским представлением.

package me.ribose.example; // you'll have to change this

import android.app.AlertDialog;
import android.content.Context;
import android.database.DataSetObserver;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.SpinnerAdapter;

public class CustomSpinner extends Spinner implements OnItemClickListener {
    private AlertDialog mDialog = null;
    private OnClickListener mButtonClickListener = null;

    public UnitSelectionSpinner(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setButtonClickListener(OnClickListener listener) {
        mButtonClickListener = listener;
    }

    @Override
    public boolean performClick() {
        Context context = getContext();

        // get the set adapter
        final DropDownAdapter adapter = new DropDownAdapter(getAdapter());

        // inflate our layout
        final LayoutInflater inflater = LayoutInflater.from(getContext());
        final View v = inflater.inflate(R.layout.customSpinner, null);

        // set up list view
        final ListView lv = (ListView) v.findViewById(R.id.list);
        lv.setAdapter(adapter);
        lv.setSelection(getSelectedItemPosition());
        lv.setOnItemClickListener(this);

        // set up button
        final Button btn = (Button) v.findViewById(R.id.addButton);
        btn.setOnClickListener(mButtonClickListener);

        // build our dialog
        AlertDialog.Builder builder = new AlertDialog.Builder(context);

        // show prompt, just as our Spinner parent does
        if (getPrompt() != null) {
            builder.setTitle(getPrompt());
        }

        // create and show dialog
        mDialog = builder.setView(v).create();
        mDialog.show();

        return true;
    }

    @Override
    public void onItemClick(AdapterView<?> view,
                            View itemView, int position, long id) {
        setSelection(position);
        if (mDialog != null) {
            mDialog.dismiss();
            mDialog = null;
        }
    }

    /**
     * <p>Wrapper class for an Adapter. Transforms the embedded Adapter instance
     * into a ListAdapter.</p>
     */
    private static class DropDownAdapter implements ListAdapter, SpinnerAdapter {
        private SpinnerAdapter mAdapter;

        /**
         * <p>Creates a new ListAddapter wrapper for the specified adapter.</p>
         *
         * @param adapter the Adapter to transform into a ListAdapter
         */
        public DropDownAdapter(SpinnerAdapter adapter) {
            this.mAdapter = adapter;
        }

        public int getCount() {
            return mAdapter == null ? 0 : mAdapter.getCount();
        }

        public Object getItem(int position) {
            return mAdapter == null ? null : mAdapter.getItem(position);
        }

        public long getItemId(int position) {
            return mAdapter == null ? -1 : mAdapter.getItemId(position);
        }

        public View getView(int position, View convertView, ViewGroup parent) {
            return getDropDownView(position, convertView, parent);
        }

        public View getDropDownView(int position, View convertView, ViewGroup parent) {
            return mAdapter == null ? null :
                    mAdapter.getDropDownView(position, convertView, parent);
        }

        public boolean hasStableIds() {
            return mAdapter != null && mAdapter.hasStableIds();
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {
            if (mAdapter != null) {
                mAdapter.registerDataSetObserver(observer);
            }
        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {
            if (mAdapter != null) {
                mAdapter.unregisterDataSetObserver(observer);
            }
        }

        /**
         * <p>Always returns false.</p>
         *
         * @return false
         */
        public boolean areAllItemsEnabled() {
            return true;
        }

        /**
         * <p>Always returns false.</p>
         *
         * @return false
         */
        public boolean isEnabled(int position) {
            return true;
        }

        public int getItemViewType(int position) {
            return 0;
        }

        public int getViewTypeCount() {
            return 1;
        }

        public boolean isEmpty() {
            return getCount() == 0;
        }
    }
}

Вам понадобится мой customSpinner.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent">
    <ListView
            android:id="@+id/list"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1"
            android:layout_marginTop="5px"
            android:cacheColorHint="@null"
            android:background="@android:color/background_light"
            android:divider="@android:drawable/divider_horizontal_bright"
            android:scrollbars="vertical">
    </ListView>
    <Button
            android:id="@+id/addButton"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Add to Database">
    </Button>
</LinearLayout>

Конечно, сделайте это android:text строковым ресурсом.

Еще несколько слов по этому поводу: просто сделайте CustomSpinner в своеммакет действия, как вам нужно, и позвоните setButtonClickListener (вероятно, рядом с тем местом, где вы установили адаптер), чтобы добавить обратный вызов для вашей кнопки, который, возможно, предложит пользователю добавить или все, что вам нужно.И, конечно, notifyDataSetChanged() на вашем адаптере после добавления в базу данных.Все, что работает на Spinner, должно работать точно так же с этим пользовательским Spinner.

Примечание (ОБНОВЛЕНО): Вы должны будете убедиться, что элементы списка вашего адаптера имеют черный текст (например: android:textColor="@android:color/primary_text_light_nodisable")!Я изменил приведенный выше XML, чтобы он не требовал белого фона для элементов (из-за чего выделение элементов не работает).


Примечания к коду: поскольку люди, создавшие Android, решили не делать легкий путьчтобы настроить диалоги вращения (жестко запрограммированное использование AlertDialog.Builder с использованием setSingleChoiceItems(), а также закрытый класс для «преобразования» SpinnerAdapter s в ListAdapter s), мне пришлось скопировать весь их внутренний класс, чтобы получить желаемыйэффект.Также обратите внимание, что они плохие документаторы (см. DropDownAdapter. isEnabled / areAllItemsEnabled для смеха дня!).

0 голосов
/ 10 августа 2011

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

...