Android 列表适配器一遍又一遍地膨胀相同的视图

Android List Adapter inflates the same View over and over

在我的数独应用程序中,我试图让列表适配器为每个列表扩充自定义预览视图 item/puzzle,但由于某种原因,适配器总是一遍又一遍地扩充相同的自定义视图。有什么建议吗?

Screenshot of Problem

这是我的列表适配器Class

package com.example.czhou.myapplication2;

import android.content.Context;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;

import java.io.File;

public class SudokuListAdapter extends BaseAdapter {
    Context context;
    String data[];
    private static LayoutInflater inflater = null;

    public SudokuListAdapter(Context context, String[] data) {
        this.context = context;
        this.data = data;
        inflater = (LayoutInflater) context
                .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    }
    @Override
    public int getCount() {
        return data.length;
    }

    @Override
    public Object getItem(int position) {
        return data[position];
    }

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

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        View vi = convertView;
        if (vi == null)
            vi = inflater.inflate(R.layout.row, null);
        TextView text = (TextView) vi.findViewById(R.id.date);
        text.setText(data[position]);
        System.out.println("pos: " + position);

        SudokuPreviewView view = (SudokuPreviewView) vi.findViewById(R.id.preview);
        view.setData("puzzle" + data[position]);
        return vi;
    }

    @Override
    public void notifyDataSetChanged() {
        super.notifyDataSetChanged();


    }

    public void setData(String[] data) {
        this.data = data;
    }
}

这是列表Activity

package com.example.czhou.myapplication2;

import android.app.Activity;
import android.content.ContentProviderOperation;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;

import android.app.ActionBar;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;

import java.io.File;
import java.io.FileOutputStream;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Scanner;

/**
 * Created by czhou on 1/18/2015.
 */
public class SudokuListActivity extends ActionBarActivity {

    public static String[] fileNames;
    public SudokuListAdapter mAdapter;
    public static File[] files;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Context c = this;

        setContentView(R.layout.activity_list);

        ListView lv = (ListView) findViewById(R.id.listView);




        files = c.getFilesDir().listFiles();
        fileNames = new String[files.length];
        for (int i = 0; i < files.length; i++) {
            fileNames[i] = files[i].getName().substring(6,files[i].getName().length());
        }


        mAdapter = new SudokuListAdapter(this, fileNames);
        lv.setAdapter(mAdapter);
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(SudokuListActivity.this,SudokuGameActivity.class);
                intent.putExtra("FILE","puzzle" + fileNames[position]);
                startActivity(intent);

            }
        });
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        MenuInflater menuInflater = getMenuInflater();
        menuInflater.inflate(R.menu.activity_list_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        Context c = this;
        switch (item.getItemId()) {
            case R.id.add:
                DateFormat dateFormat = new SimpleDateFormat("dd MMMM yy hh:mm:ss a");
                Calendar cal = Calendar.getInstance();

                String fn = "puzzle" + dateFormat.format(cal.getTime());
                SudokuGen sg = new SudokuGen();
                CellField cf = sg.generate();

                FileOutputStream outputStream;

                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < 9; i++) {
                    for (int j = 0; j < 9; j++) {
                        if (cf.field[i][j].isEditable) {
                            sb.append(",");
                        } else {
                            sb.append(".");
                        }
                        if (cf.field[i][j].isWrong) {
                            sb.append("!");
                        } else {
                            sb.append(".");
                        }

                        sb.append(cf.field[i][j].getValue());
                    }
                }

                try {

                    outputStream = openFileOutput(fn, Context.MODE_PRIVATE);
                    outputStream.write(sb.toString().getBytes());
                    outputStream.close();
                    System.out.println("Saving... ");
                } catch (Exception e) {
                    e.printStackTrace();
                }

                Intent intent = new Intent(this, SudokuGameActivity.class);
                intent.putExtra("FILE",fn);
                startActivity(intent);
            break;
            default:

        }
        return super.onOptionsItemSelected(item);
    }

    @Override
    protected void onRestart() {
        System.out.println("restarting.. ");
        Context c = this;

        setContentView(R.layout.activity_list);

        ListView lv = (ListView) findViewById(R.id.listView);




        files = c.getFilesDir().listFiles();
        fileNames = new String[files.length];
        for (int i = 0; i < files.length; i++) {
            fileNames[i] = files[i].getName().substring(6,files[i].getName().length());
        }


        mAdapter = new SudokuListAdapter(this, fileNames);
        lv.setAdapter(mAdapter);
        lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                Intent intent = new Intent(SudokuListActivity.this,SudokuGameActivity.class);
                intent.putExtra("FILE","puzzle" + fileNames[position]);
                startActivity(intent);

            }
        });
        super.onRestart();
    }


}

这是我的预览视图Class

package com.example.czhou.myapplication2;

import android.app.Activity;
import android.content.Context;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.os.Bundle;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;

/**
 * Created by czhou on 1/19/2015.
 */
public class SudokuPreviewView extends View{
        public float mCellSize = 0;
        public boolean mOrientationLandscape;
        public float mTextSize;

        private Paint mTextColor;
        private Paint mTextColorBold;
        private Paint mLineColor;
        private Paint mRect;
        private Paint mRectSecondary;
        private Paint mGridLine;
        private Paint mSelectedCellColor;
        private Paint mErrorCellColor;
        private DisplayMetrics displayMetrics;
        private float x;
        private float y;
        private int[] mSelectedCellCordPair;
        private ArrayList<Integer> mErrorCellPairs;
        public static CellField cf;
        private static String mFileName;
        public static Cell[][] cells;
        private Bundle bundle = new Bundle();

        Rect mTextBounds;


        private float dpHeight;
        private float dpWidth;

        public SudokuPreviewView(Context c, AttributeSet attrs) {

            super(c, attrs);
            setWillNotDraw(false);

            TypedArray a = c.getTheme().obtainStyledAttributes(
                    attrs,
                    R.styleable.SudokuPreviewView,
                    0, 0);
            mCellSize = a.getDimension(R.styleable.SudokuPreviewView_mCell,30f);
            mOrientationLandscape = a.getBoolean(R.styleable.SudokuPreviewView_mOrientationPortrait, false);
            mTextSize = a.getDimension(R.styleable.SudokuPreviewView_mTextSize, 5f);

            a.recycle();
            init();
        }

        private void init() {
            cf = new CellField();
            cells = new Cell[9][9];

            StringBuilder text = new StringBuilder();

            try {


                Context c = getContext();
                File inputStream = c.getFileStreamPath(mFileName);


                BufferedReader br = new BufferedReader(new FileReader(inputStream));
                String line;
                while ((line = br.readLine()) != null) {
                    text.append(line);
                }
                br.close();

            } catch (Exception e) {
                e.printStackTrace();

                cells = cf.field;
            }

            if (text.length() == 243) {

                for (int i = 0; i < 9; i++) {
                    for (int j = 0; j < 9; j++) {
                        Cell cell = new Cell();

                        int index = 0;

                        if (text.substring(index, index + 3).startsWith(",!")) {
                            cell.setValue(Integer.parseInt(text.substring(index + 2, index + 3)));
                            cell.isEditable = true;
                            cell.isWrong = true;
                        } else if (text.substring(index, index + 3).startsWith(",.")) {
                            cell.setValue(Integer.parseInt(text.substring(index + 2, index + 3)));
                            cell.isEditable = true;
                        } else if (text.substring(index, index + 3).startsWith("..")) {
                            cell.setValue(Integer.parseInt(text.substring(index + 2, index + 3)));
                        }


                        cells[i][j] = cell;
                        text.delete(index, index + 3);

                    }
                }
            }



            mTextBounds = new Rect();
            displayMetrics = getContext().getResources().getDisplayMetrics();
            dpHeight = displayMetrics.heightPixels / displayMetrics.density;
            dpWidth = displayMetrics.widthPixels / displayMetrics.density;

            mLineColor = new Paint(Paint.ANTI_ALIAS_FLAG);
            mLineColor.setColor(getResources().getColor(R.color.material_blue_grey_900));
            mLineColor.setStyle(Paint.Style.STROKE);
            mLineColor.setStrokeWidth(toDP(1f));

            mRect = new Paint(Paint.ANTI_ALIAS_FLAG);
            mRect.setColor(getResources().getColor(R.color.background_material_light));

            mRectSecondary = new Paint(Paint.ANTI_ALIAS_FLAG);
            mRectSecondary.setColor(Color.LTGRAY);

            mSelectedCellColor = new Paint(Paint.ANTI_ALIAS_FLAG);
            mSelectedCellColor.setColor(Color.YELLOW);
            mSelectedCellColor.setAlpha(100);
            mSelectedCellColor.setStyle(Paint.Style.FILL);

            mGridLine = new Paint(Paint.ANTI_ALIAS_FLAG);
            mGridLine.setColor(getResources().getColor(R.color.material_blue_grey_950));
            mGridLine.setStyle(Paint.Style.STROKE);
            mGridLine.setStrokeWidth(toDP(3f));

            Paint.FontMetrics fm = new Paint.FontMetrics();
            mTextColor = new Paint(Paint.ANTI_ALIAS_FLAG);
            mTextColor.setColor(Color.BLACK);
            mTextColor.setStyle(Paint.Style.FILL);
            mTextColor.setTextSize(mTextSize);
            mTextColor.setTextAlign(Paint.Align.CENTER);
            mTextColor.getFontMetrics(fm);

            mTextColorBold = new Paint(Paint.ANTI_ALIAS_FLAG);
            mTextColorBold.setTypeface(Typeface.DEFAULT_BOLD);
            mTextColorBold.setColor(Color.BLACK);
            mTextColorBold.setStyle(Paint.Style.FILL);
            mTextColorBold.setTextSize(mTextSize);
            mTextColorBold.setTextAlign(Paint.Align.CENTER);

            mTextColorBold.getFontMetrics(fm);

            mErrorCellColor = new Paint(Paint.ANTI_ALIAS_FLAG);
            mErrorCellColor.setStyle(Paint.Style.FILL);
            mErrorCellColor.setColor(Color.RED);
            mErrorCellColor.setAlpha(80);
            mErrorCellPairs = new ArrayList<>();
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
                setMeasuredDimension((int) mCellSize * 9, (int) mCellSize * 9);

        }

        public void onDraw(Canvas c) {
            super.onDraw(c);

            for (int i = 0; i < mCellSize * 9; i += mCellSize) {
                for (int j = 0; j < mCellSize * 9; j += mCellSize) {
                    String s = String.valueOf(cells[(int) (i / mCellSize)][(int) (j / mCellSize)].getValue());

                    // check for wrong cells and highlight them
//                if (j >= mCellSize * 3 && j < mCellSize * 6 && i >= 0 && i < mCellSize * 3 ||
//                        j >= mCellSize * 3 && j < mCellSize * 6 && i >= mCellSize * 6 && i < mCellSize * 9 ||
//                        i >= mCellSize * 3 && i < mCellSize * 6 && j >= 0 && j < mCellSize * 3 ||
//                        i >= mCellSize * 3 && i < mCellSize * 6 && j >= mCellSize * 6 && j < mCellSize * 9) {
//
                    if (!cells[(int) (i / mCellSize)][(int) (j / mCellSize)].isEditable) {
                        c.drawRect(j, i, j + mCellSize, i + mCellSize, mRectSecondary);
                        c.drawRect(j, i, j + mCellSize, i + mCellSize, mLineColor);
                    } else {
//                } else {
                        c.drawRect(j, i, j + mCellSize, i + mCellSize, mLineColor);
                    }
//                }

                    mTextColor.getTextBounds(s, 0, s.length(), mTextBounds);
                    float mTextHeight = mTextBounds.height();
                    float mTextWidth = mTextBounds.width();
                    if (!s.equals("0")) {
                        if (!cells[(int) (i / mCellSize)][(int) (j / mCellSize)].isEditable) {
                            c.drawText(s, j + mCellSize / 2, (i + mTextHeight) + ((mCellSize / 2) - (mTextHeight / 2)), mTextColorBold);
                        } else {
                            c.drawText(s, j + mCellSize / 2, (i + mTextHeight) + ((mCellSize / 2) - (mTextHeight / 2)), mTextColor);
                        }

                    }
                }
            }
            c.drawRect(0, 0, mCellSize * 9, mCellSize * 9, mGridLine);
            c.drawLine(mCellSize * 3, 0, mCellSize * 3, mCellSize * 9, mGridLine);
            c.drawLine(mCellSize * 6, 0, mCellSize * 6, mCellSize * 9, mGridLine);

            c.drawRect(0, mCellSize * 3, mCellSize * 9, mCellSize * 6, mGridLine);

            for (int i = 0; i < 9; i++) {
                for (int j = 0; j < 9; j++) {

                    if (cells[i][j].isWrong) {
                        Cell wrong = cells[i][j];
                        if (wrong.getValue() == 0) {
                            wrong.isWrong = false;
                        } else {
                            if (wrong.errorCords.isEmpty()) {

                                for (int k = 0; k < 9; k++) {
                                    if (cells[k][j].getValue() == wrong.getValue() && k != i) {
                                        wrong.errorCords.add(j);
                                        wrong.errorCords.add(k);
                                    }
                                }
                                for (int k = 0; k < 9; k++) {
                                    if (cells[i][k].getValue() == wrong.getValue() && k != j) {
                                        wrong.errorCords.add(k);
                                        wrong.errorCords.add(i);
                                    }
                                }
                                cf.field = cells;
                                wrong.errorCords.addAll(cf.getSectorCords(i, j, wrong.getValue()));
                            }
                            for (int k = 0; k < wrong.errorCords.size(); k += 2) {
                                c.drawRect(wrong.errorCords.get(k) * mCellSize, wrong.errorCords.get(k + 1) * mCellSize, (wrong.errorCords.get(k) * mCellSize) + mCellSize, (wrong.errorCords.get(k + 1) * mCellSize) + mCellSize, mErrorCellColor);
                            }

                        }
                    }
                    //               }

                }
            }


            if (mSelectedCellCordPair != null) {
                x = mSelectedCellCordPair[0];
                y = mSelectedCellCordPair[1];

                if (mSelectedCellCordPair[0] < 9 && mSelectedCellCordPair[1] < 9) {


                    if (x == 0 || y == 0) {
                        if (x == 0 && y == 0) {
                            c.drawRect(x, y, mCellSize, mCellSize, mSelectedCellColor);
                        } else if (x == 0) {
                            c.drawRect(x, y * mCellSize, (x + 1) * mCellSize, (y + 1) * mCellSize, mSelectedCellColor);
                        } else {
                            c.drawRect(x * mCellSize, y, (x + 1) * mCellSize, (y + 1) * mCellSize, mSelectedCellColor);
                        }
                    } else {
                        c.drawRect(x * mCellSize, y * mCellSize, (x + 1) * mCellSize, (y + 1) * mCellSize, mSelectedCellColor);
                    }
                }
            }
        }


        private float toDP(float dp) {
            DisplayMetrics metrics = getContext().getResources().getDisplayMetrics();
            float fpixels = metrics.density * dp;
            int pixels = (int) (fpixels + 0.5f);
            return pixels;
        }

        private float toPixels(float dp) {
            Resources r = getResources();
            float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics());
            return px;
        }

        public void setData (String FileName){
            mFileName = FileName;
            System.out.println(FileName);
            init();
            invalidate();
        }


    }

这里是row.xml

        <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:custom="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="5dp">

        <com.example.czhou.myapplication2.SudokuPreviewView
            android:layout_width="203dp"
            android:layout_height="258dp"
            android:id="@+id/preview"
            custom:mCell="15dp"
            custom:mTextSize="5sp"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Last played: 1/1/1"
            android:id="@+id/date"
            android:layout_gravity="right"
            android:layout_alignBottom="@+id/preview"
            android:layout_alignParentRight="true"
            android:layout_alignParentEnd="true" />
    </RelativeLayout>

**Here is the activity_list.xml**
<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    xmlns:android="http://schemas.android.com/apk/res/android">
<ListView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:id="@+id/listView">
    </ListView>
</RelativeLayout>

您视图中的 cells 字段是静态的。这意味着它适用于整个 class,而不适用于每个实例。每次使用新单元格对其进行初始化时,它都会更改每个预览视图的数据。

将静力学放在 cellscfmFileName 上,它应该会开始工作。