如何访问 GridView / 数组中的特定项目(在 Android 应用程序中)
How to access a specific item within a GridView / array (in an Android app)
在 Android Studio 中编写一个 Android 应用程序,我有一个 GridView 来显示一组图像/文本,但我无法弄清楚如何访问其中的特定项目列表。
如果我点击一个项目,我可以对它做一些事情(在下面的代码中我改变了显示的图像),但我不知道如何访问一个特定的项目(例如改变显示的图像) 以编程方式。
最初我使用了一个示例中的 ImageAdapter,但后来我发现如果我将它更改为使用 TextView,我可以为每个文本和图像分配文本,并且它与 Talkback 一起工作(Android 屏幕 reader).
我最初也将 OnTouchListener 添加到 activity,但我认为我现在不需要它,因为我只需要在适配器中实现它。
最后,我对我需要尝试访问的内容感到有点困惑 - 我是想从 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 的回答(来自 How to find element inside a gridview in Android? 的回答)是正确的:
// newChoice is an int set to something in the range 0...myGridView.getChildCount()
v = (TextView) myGridView.getChildAt(newChoice);
v.setBackgroundResource(themeImages[ACTIVE1]);
我一开始没有意识到的第二个问题是,一旦绘制了视图,我试图从视图中获取的信息中的逻辑就会起作用,但是因为这段代码设法在视图都已完成绘制,值不是我预期的值,这意味着标记为可见的项目的高度为 0 等。我发现这段代码有帮助:getWidth() and getHeight() of View returns 0
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)));
}
});
}
});
感谢拉米的帮助和建议! (我也按照您的建议将直接引用图像文件更改为使用数组)。
在 Android Studio 中编写一个 Android 应用程序,我有一个 GridView 来显示一组图像/文本,但我无法弄清楚如何访问其中的特定项目列表。
如果我点击一个项目,我可以对它做一些事情(在下面的代码中我改变了显示的图像),但我不知道如何访问一个特定的项目(例如改变显示的图像) 以编程方式。
最初我使用了一个示例中的 ImageAdapter,但后来我发现如果我将它更改为使用 TextView,我可以为每个文本和图像分配文本,并且它与 Talkback 一起工作(Android 屏幕 reader).
我最初也将 OnTouchListener 添加到 activity,但我认为我现在不需要它,因为我只需要在适配器中实现它。
最后,我对我需要尝试访问的内容感到有点困惑 - 我是想从 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 的回答(来自 How to find element inside a gridview in Android? 的回答)是正确的:
// newChoice is an int set to something in the range 0...myGridView.getChildCount()
v = (TextView) myGridView.getChildAt(newChoice);
v.setBackgroundResource(themeImages[ACTIVE1]);
我一开始没有意识到的第二个问题是,一旦绘制了视图,我试图从视图中获取的信息中的逻辑就会起作用,但是因为这段代码设法在视图都已完成绘制,值不是我预期的值,这意味着标记为可见的项目的高度为 0 等。我发现这段代码有帮助:getWidth() and getHeight() of View returns 0
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)));
}
});
}
});
感谢拉米的帮助和建议! (我也按照您的建议将直接引用图像文件更改为使用数组)。