为Custom ListView设置自定义适配器

时间:2014-01-02 23:36:40

标签: java android listview adapter

我目前正在开展一个项目,该项目将跟踪一个名为Farkle的游戏的玩家得分和其他信息。我已经完成了大约100次谷歌搜索,并在这里阅读了几个条目。我已经尝试过实现和使用我发现的所有内容,但我只是在这里结束。

row.xml 将作为ListView中的单个项目加载。

最终,我希望按顺序(您将在下面看到我的row.xml布局): “玩家姓名”复选框复选框“玩家得分”。

我可以让应用程序运行,所以我在发布时没有问题,但是,一旦我尝试添加新玩家,该应用就会中断。

现在,我在下面的代码是一个新项目,因为最后一个代码已经破解到它没有显示任何错误但会在启动时崩溃的程度。我尝试过使用自定义ArrayAdapter,我相信这是适用于我的方法,但我似乎无法在不崩溃的情况下加载row.xml。我还是ArrayAdapter的新手,我做了一些教程,但我仍然无法使用它。

如果有人想知道我能做些什么来实现这个目标,请帮助我,让我指出正确的方向。我已经为此工作了2个星期了!提前谢谢。

activity_main.xml中

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity" >

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/btnSetScore"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/winning_score" />

    <Button
        android:id="@+id/btnAddPlayer"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_weight="1"
        android:text="@string/add_player"
        android:textSize="@dimen/activity_horizontal_margin" />

    <Button
        android:id="@+id/btnSetPenalty"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/set_penalty"
        android:textSize="@dimen/activity_horizontal_margin" />

</LinearLayout>

<ListView
    android:id="@+id/lvScoreBoard"
    android:layout_width="match_parent"
    android:layout_height="0dp"
    android:layout_weight="10"
    tools:listitem="@layout/row" >

</ListView>

<LinearLayout
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/btnStatistics"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/statistics" />

    <Button
        android:id="@+id/btnNewGame"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/new_game" />

</LinearLayout>

这是我的 row.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal" >

    <TextView
        android:id="@+id/tvPlayer"
        android:layout_weight="4"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/player"
        android:textAppearance="?android:attr/textAppearanceLarge" />

    <CheckBox
        android:id="@+id/cbFarkle1"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:enabled="false"
        android:focusable="false"
        android:text="" />

    <CheckBox
        android:id="@+id/cbFarkle2"
        android:layout_weight="1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:enabled="false"
        android:focusable="false"
        android:text="" />

    <TextView
        android:id="@+id/tvScore"
        android:layout_weight="2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="@string/player_score"
        android:gravity="right"
        android:textAppearance="?android:attr/textAppearanceLarge" />

</LinearLayout>

这是我的 MainActivity.java

public class MainActivity extends Activity{

String winningScore = "";
String playerName = "";
String playerScore = "";
String farklePenalty = "";
int penalty;

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

    // Creates Buttons
    final Button btnSetScore = (Button) findViewById(R.id.btnSetScore);
    Button btnAddPlayer = (Button) findViewById(R.id.btnAddPlayer);
    final Button btnSetPenalty = (Button) findViewById(R.id.btnSetPenalty);
    Button btnStatistics = (Button) findViewById(R.id.btnStatistics);
    Button btnNewGame = (Button) findViewById(R.id.btnNewGame);

    // Creates ListView for player score board
    final ListView lvScoreBoard = (ListView) findViewById(R.id.lvScoreBoard);

    // Sets the game winning score when the Set Score button is pressed.
    btnSetScore.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO:
            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setTitle("Set Winning Score");

            final EditText input = new EditText(MainActivity.this);
            input.setInputType(InputType.TYPE_CLASS_NUMBER);

            builder.setView(input);

            builder.setPositiveButton("Save", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    winningScore = input.getText().toString();
                    btnSetScore.setText(winningScore);
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
                }
            });

            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {    
                    dialog.cancel();        
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
                }

            });

            builder.show();

            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

        }
    });

    // Adds a new player to the game when Add Player button is pressed.
    btnAddPlayer.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setTitle("Add Player");

            final EditText input = new EditText(MainActivity.this);
            input.setInputType(InputType.TYPE_CLASS_TEXT);

            builder.setView(input);

            builder.setPositiveButton("Save", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    playerName = input.getText().toString();



                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
                }
            });

            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {    
                    dialog.cancel();        
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
                }

            });

            builder.show();

            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

        }
    });

    // Sets the third farkle penalty when Set Penalty button is pressed.
    btnSetPenalty.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {

            AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
            builder.setTitle("Set Farkle Penalty");

            final EditText input = new EditText(MainActivity.this);
            input.setInputType(InputType.TYPE_CLASS_NUMBER);

            builder.setView(input);

            builder.setPositiveButton("Save", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    farklePenalty = input.getText().toString();
                    penalty = Integer.parseInt(input.getText().toString());
                    btnSetPenalty.setText(farklePenalty);
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
                }
            });

            builder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {    
                    dialog.cancel();        
                    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                    imm.toggleSoftInput(InputMethodManager.HIDE_NOT_ALWAYS, 0);
                }

            });

            builder.show();

            InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
            imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);

        }
    });

    // Changes to statistics activity when Statistics button is pressed.
    btnStatistics.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

        }

    });

    // Resets all data when New Game button is pressed.
    // This will also have the ability to keep player names, 
    // but erase farkle counts, player scores, penalty, 
    // and winning score.
    btnNewGame.setOnClickListener(new View.OnClickListener() {

        @Override
        public void onClick(View v) {
            // TODO Auto-generated method stub

        }
    });
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // Inflate the menu; this adds items to the action bar if it is present.
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

}

Customed ListAdapter,但我知道这是错误的。

public class GeneralAdapter extends BaseAdapter {

private static final CharSequence Name = null;
private LayoutInflater mInflater = null;
private ArrayList<String> info = null;

public GeneralAdapter( ArrayList<String> info) {
    this.info = info;
}

String name;
String score = "0";
boolean farkle1 = false;
boolean farkle2 = false;

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

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

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.row, null);

        holder = new ViewHolder();
        holder.generalTV = (TextView) convertView.findViewById(R.id.tvPlayer);
        holder.generalCB = (CheckBox) convertView.findViewById(R.id.cbFarkle1);
        holder.generalCB2 = (CheckBox) convertView.findViewById(R.id.cbFarkle2);
        holder.generalTV2 = (TextView) convertView.findViewById(R.id.tvScore);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.generalTV.setText(name);
    holder.generalCB.setChecked(farkle1);
    holder.generalCB2.setChecked(farkle2);
    holder.generalTV2.setText(score);

    return null;
}

private class ViewHolder {
    TextView generalTV;
    TextView generalTV2;
    CheckBox generalCB;
    CheckBox generalCB2;
}

}

2 个答案:

答案 0 :(得分:2)

崩溃日志或至少您遇到的异常会有所帮助。

那就是说,我可以看到一个问题。你从getView()返回null。请尝试返回convertView:

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.row, null);

        holder = new ViewHolder();
        holder.generalTV = (TextView) convertView.findViewById(R.id.tvPlayer);
        holder.generalCB = (CheckBox) convertView.findViewById(R.id.cbFarkle1);
        holder.generalCB2 = (CheckBox) convertView.findViewById(R.id.cbFarkle2);
        holder.generalTV2 = (TextView) convertView.findViewById(R.id.tvScore);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.generalTV.setText(name);
    holder.generalCB.setChecked(farkle1);
    holder.generalCB2.setChecked(farkle2);
    holder.generalTV2.setText(score);

    return convertView;  // HERE!!
}

此外,当您从convertView获取持有者时,您可能想要进行一些空检查。如果由于某种原因,最终为null,那么引用它的第一件事就会导致NRE。我从你的代码中看不出任何错误,但是因为你遇到崩溃,所以值得一试。


退一步,你永远不会在适配器中使用信息。换句话说,每个列表项看起来都完全相同,因为它们使用相同的值(name,farkle1,farkle2,score)。

也许你的意思是拥有一组包含这些成员的对象?像这样:

public class DataItem {
    String name;
    String score = "0";
    boolean farkle1 = false;
    boolean farkle2 = false;
}

然后将它传递到你的适配器,类似这样......(注意:我还没有尝试编译)

public class GeneralAdapter extends BaseAdapter {

private static final CharSequence Name = null;
private LayoutInflater mInflater = null;
private ArrayList<DataItem> info = null;

public GeneralAdapter( ArrayList<DataItem> info) {
    this.info = info;
}

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

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

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

@Override
public View getView(int position, View convertView, ViewGroup parent) {
    ViewHolder holder;
    DataItem dataItem = getItem(position);

    if (convertView == null) {
        convertView = mInflater.inflate(R.layout.row, null);

        holder = new ViewHolder();
        holder.generalTV = (TextView) convertView.findViewById(R.id.tvPlayer);
        holder.generalCB = (CheckBox) convertView.findViewById(R.id.cbFarkle1);
        holder.generalCB2 = (CheckBox) convertView.findViewById(R.id.cbFarkle2);
        holder.generalTV2 = (TextView) convertView.findViewById(R.id.tvScore);

        convertView.setTag(holder);
    } else {
        holder = (ViewHolder) convertView.getTag();
    }

    holder.generalTV.setText(dataItem.name);
    holder.generalCB.setChecked(dataItem.farkle1);
    holder.generalCB2.setChecked(dataItem.farkle2);
    holder.generalTV2.setText(dataItem.score);

    return convertView;
}

private class ViewHolder {
    TextView generalTV;
    TextView generalTV2;
    CheckBox generalCB;
    CheckBox generalCB2;
}
}

顺便说一下,这基本上一个ArrayAdapter,你可以轻松使用它。

答案 1 :(得分:1)

为什么要在null中返回getView

将其更改为return convertView;