Java 如何访问GridView/阵列中的特定项目(在Android应用程序中)

Java 如何访问GridView/阵列中的特定项目(在Android应用程序中),java,android,gridview,Java,Android,Gridview,在androidstudio中编写一个Android应用程序时,我有一个GridView来显示一组图像/文本,我很难确定如何访问列表中的特定项目 如果我点击一个项目,我可以对它做一些事情(在下面的代码中,我更改了显示的图像),但我不知道如何以编程方式访问特定项目(例如更改显示的图像) 起初,我使用了一个示例中的ImageAdapter,但后来我发现,如果我将其更改为使用TextView,我可以将文本和图像分配给每个图像,并且可以与Talkback(Android屏幕阅读器)配合使用 我最初还将O

在androidstudio中编写一个Android应用程序时,我有一个GridView来显示一组图像/文本,我很难确定如何访问列表中的特定项目

如果我点击一个项目,我可以对它做一些事情(在下面的代码中,我更改了显示的图像),但我不知道如何以编程方式访问特定项目(例如更改显示的图像)

起初,我使用了一个示例中的ImageAdapter,但后来我发现,如果我将其更改为使用TextView,我可以将文本和图像分配给每个图像,并且可以与Talkback(Android屏幕阅读器)配合使用

我最初还将OnTouchListener添加到活动中,但我认为现在不需要它,因为我只需要在适配器中实现它

最后,我有点困惑,到底我需要在这里访问什么-我是要从GridView中获取项目,还是要从ImageAdapter中获取项目?我认为GridView设置了布局并定义了在集合中放置每个项目的位置,ImageAdapter是一个项目数组的容器,该数组定义集合中每个项目的属性,对吗

问候

昆廷

public class multitap extends Activity implements View.OnTouchListener {

    private GridView myGridView;
    public int numRows;
    public int numCols;
    public int currentChoice;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_multitap);
        if (savedInstanceState == null) {
            Bundle extras = getIntent().getExtras();
            if (extras == null) {
                numRows = 1;
                numCols = 1;
            } else {
                numRows = extras.getInt("NUMBER_OF_GAME_ROWS");
                numCols = extras.getInt("NUMBER_OF_GAME_COLS");
            }
        } else {
            numRows = (int) savedInstanceState.getSerializable("NUMBER_OF_GAME_ROWS");
            numCols = (int) savedInstanceState.getSerializable("NUMBER_OF_GAME_COLS");
        }

        myGridView = (GridView)
                findViewById(R.id.myGridView);
        myGridView.setNumColumns(numCols);
        myGridView.setAdapter(new ImageAdapter(this));

        // now that everything is initialised, choose a random image tile.
        Random r = new Random();
        choice = r.nextInt(numCols*numRows);

    // This is the main thing I can't figure out - what do I need to replace "DoSomethingToFindItem" with?
    chosenItem = DoSomethingToFindItem(choice);
        // change the image of the chosen tile.
        chosenItem.setBackgroundResource(R.drawable.newImage);


    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {

        // turns out I don't need this as onTouch in adapter collects touch event
        return false;

    }


    public class ImageAdapter extends BaseAdapter {
        private Context mContext;

    //not really sure what mConext is?
        public ImageAdapter(Context c) {
            mContext = c;
        }

        public int getCount() { return numCols*numRows; }

        public Object getItem(int position) {
        // Is this right? All of the examples on the net use "return null" claiming they it's not needed (for their example)
            return this;
        }

        public long getItemId(int position) {
            // I know I should return something other than position here, but don't know what?
            // again every example doesn't feel the need for this function.
            return position;
        }

        // create a new TextView for each item referenced by the Adapter
        public View getView(int position, View convertView, ViewGroup parent) {
            TextView textView;

            if (convertView == null) {  // if it's not recycled, initialize some attributes
                textView = new TextView(mContext);

            } else {
                textView = (TextView) convertView;
            }

            textView.setBackgroundResource(R.drawable.blankcell);
            textView.setText("" + (position + 1));
            textView.setTextColor(getResources().getColor(android.R.color.transparent));
            textView.setId(position);
            textView.setMaxHeight(parent.getHeight() / numRows);
            textView.setMinimumHeight(parent.getHeight() / numRows);


            textView.setOnTouchListener(new View.OnTouchListener() {
                public boolean onTouch(View v, MotionEvent event) {
                    int position;
                    position = v.getId();

                    // looking to get the first touch of any finger - this part works.
                    if ((event.getAction() == MotionEvent.ACTION_DOWN) || (event.getAction() == MotionEvent.ACTION_POINTER_DOWN)) {
                        TextView textView;
                        if (v == null) {  // if it's not recycled, initialize some attributes
                            textView = new TextView(mContext);

                        } else {
                            textView = (TextView) v;
                        }

                        // I can set a specific image by clicking on it.
                        textView.setBackgroundResource(R.drawable.clickedImage);

                        return true;
                    } else return false;
                }

                ;});
            return textView;
        }

    }
}

好的,就像经常发生的情况一样,我最初面临着几个问题。一个是访问GridView中的项目,Rami的回答(来自:)是正确的:

// newChoice is an int set to something in the range 0...myGridView.getChildCount()

v = (TextView) myGridView.getChildAt(newChoice);
v.setBackgroundResource(themeImages[ACTIVE1]);
第二个我一开始没有意识到的问题是,我试图从视图中获取的信息中的逻辑在绘制视图后会起作用,但因为这段代码在视图全部绘制完成之前执行,值不是我期望的值,这意味着标记为可见的项目的高度为0等。我发现此代码有帮助:


谢谢你的帮助和建议!(我还按照您的建议,将直接引用图像文件改为使用数组)。

试试这个答案:谢谢,我试过了,得到了一个空指针异常。我尝试添加一条toast消息,指示numVisibleChildren和firstVisiblePosition的值,它们都返回0,这是我没有预料到的-我已经初始化了所有内容,如果不包括这段代码,除此之外,不会调用任何其他功能,但视图会显示在屏幕上-是否在上次初始化完成并绘制所有内容之前运行了此代码?解决了您的问题?抱歉-我发现在编写回复时无法按ENTER键-请参阅回复时的编辑:)GridView对象列表的存储位置?
final View theParent = parent;
final TextView theText = textView;
textView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
    @Override
    public void onGlobalLayout() {
        theText.post(new Runnable() {
            public void run() {
                // Now height is ready
                theText.setLayoutParams(new GridView.LayoutParams(GridView.AUTO_FIT, (theParent.getHeight() / numRows)));
            }
        });
    }
});