J'ai un GridView qui est assez similaire au tutoriel de Google, sauf que je veux ajouter ImageViews au moment de l'exécution (via une sous-activité). Les résultats sont corrects, mais la présentation de la vue est perturbée: le GridView ne remplit pas le contenu de son parent, que dois-je faire pour le concevoir correctement?
Voici le code pour ajouter les enfants:
public void initializeWorkbench(GridView gv, Vector<String> items) {
Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height());
Prototype.workbench.activateWorkbench();
// this measures the workbench correctly
Log.d(Prototype.TAG, "workbench width: "+Prototype.workbench.getMeasuredWidth());
// 320
Log.d(Prototype.TAG, "workbench height: "+Prototype.workbench.getMeasuredHeight());
// 30
ImageAdapter imgAdapter = new ImageAdapter(this.getContext(), items);
gv.setAdapter(imgAdapter);
gv.measure(screenWidth, screenHeight);
gv.requestLayout();
gv.forceLayout();
Log.d(Prototype.TAG, "gv width: "+gv.getMeasuredWidth());
// 22
Log.d(Prototype.TAG, "gv height: "+gv.getMeasuredHeight());
// 119
Prototype.workbench.setDimension(screenWidth, divider.height()+workbenchArea.height());
}
}
activateWorkbench, setDimension et measure dans le workbench (LinearLayout au-dessus du GridView):
public void activateWorkbench() {
if(this.equals(Prototype.workbench)) {
this.setOrientation(VERTICAL);
show = true;
measure();
}
}
public void setDimension(int w, int h) {
width = w;
height = h;
this.setLayoutParams(new LinearLayout.LayoutParams(width, height));
this.invalidate();
}
private void measure() {
if (this.getOrientation() == LinearLayout.VERTICAL) {
int h = 0;
int w = 0;
this.measureChildren(0, 0);
for (int i = 0; i < this.getChildCount(); i++) {
View v = this.getChildAt(i);
h += v.getMeasuredHeight();
w = (w < v.getMeasuredWidth()) ? v.getMeasuredWidth() : w;
}
if (this.equals(Prototype.tagarea))
height = (h < height) ? height : h;
if (this.equals(Prototype.tagarea))
width = (w < width) ? width : w;
}
this.setMeasuredDimension(width, height);
}
Le constructeur ImageAdapter:
public ImageAdapter(Context c, Vector<String> items) {
mContext = c;
boolean mExternalStorageAvailable = false;
boolean mExternalStorageWriteable = false;
String state = Environment.getExternalStorageState();
if (Environment.MEDIA_MOUNTED.equals(state)) {
// We can read and write the media
mExternalStorageAvailable = mExternalStorageWriteable = true;
} else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
// We can only read the media
mExternalStorageAvailable = true;
mExternalStorageWriteable = false;
} else {
// Something else is wrong. It may be one of many other states, but
// all we need
// to know is we can neither read nor write
mExternalStorageAvailable = mExternalStorageWriteable = false;
}
if (mExternalStorageAvailable && mExternalStorageWriteable) {
for (String item : items) {
File f = new File(item);
if (f.exists()) {
try {
FileInputStream fis = new FileInputStream(f);
Bitmap b = BitmapFactory.decodeStream(fis);
bitmaps.add(b);
files.add(f);
} catch (FileNotFoundException e) {
Log.e(Prototype.TAG, "", e);
}
}
}
}
}
Et la mise en page XML:
<LinearLayout xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:orientation="vertical"
Android:gravity="bottom"
Android:paddingLeft="0px"
Android:paddingTop="0px"
Android:paddingRight="0px">
<com.unimelb.pt3.ui.TransparentPanel
Android:id="@+id/workbench"
Android:layout_width="fill_parent"
Android:layout_height="10px"
Android:paddingTop="0px"
Android:paddingLeft="0px"
Android:paddingBottom="0px"
Android:paddingRight="0px">
<GridView xmlns:Android="http://schemas.Android.com/apk/res/Android"
Android:id="@+id/gridview"
Android:layout_width="fill_parent"
Android:layout_height="fill_parent"
Android:columnWidth="90dp"
Android:numColumns="auto_fit"
Android:verticalSpacing="10dp"
Android:horizontalSpacing="10dp"
Android:stretchMode="columnWidth"
Android:gravity="center" />
</com.unimelb.pt3.ui.TransparentPanel>
</LinearLayout>
le GridView a une méthode invalidateViews ().
lorsque vous appelez cette méthode: "toutes les vues à reconstruire et à redessiner". http://developer.Android.com/reference/Android/widget/GridView.html }
je pense que c'est ce dont vous avez besoin :)
Vous devez d'abord demander à l'adaptateur de vous informer que les données ont été modifiées, puis définissez à nouveau l'adaptateur sur la grille.
adapter.notifyDataChanged();
grid.setAdapter(adapter);
Cela peut être utile . J'actualise une grille d'images miniatures de livre après la suppression d'un élément . Using adapter.notifyDataChanged (); comme mentionné ci-dessus n'a pas fonctionné pour moi comme il est appelé dans mon adaptateur.
//this is a call that retrieves cached data.
//your constructor can be designed and used without it.
final Object data = getLastNonConfigurationInstance();
Je ne fais que recharger l’adaptateur et le lier à la même vue.
//reload the adapter
adapter = new BooksAdapter(MyBooks.this, MyBooks.this, data, show_collection );
grid.invalidateViews();
grid.setAdapter(adapter);
@flyerz @snagnever
Ensemble, vous l'avez compris. CA devrait etre:
adapter.notifyDataChanged();
grid.invalidateViews();
Cela indiquera à l'adaptateur que ses données ont été modifiées, ce qui sera ensuite propagé à la grille après l'appel de la méthode invalidateViews ().
Je suis content d'avoir trouvé cette question, car je ne savais pas comment ajouter des éléments à la grille après son rendu.
Aucune de ces réponses n'a réellement fonctionné pour moi et j'ai dû les écraser toutes ensemble. Pour que le GridView soit mis à jour, procédez comme suit:
adapter.notifyDataChanged();
grid.invalidateViews();
grid.setAdapter(adapter);
J'espère que cela aide tous ceux qui ne peuvent pas utiliser les autres solutions.
Vous ne devez pas appeler invalidateViews
et setAdapter
pour actualiser votre grid view
. Ce n’est pas une bonne idée de garder votre grid view
mis à jour, si vous mettez à jour de cette façon, cela coûterait beaucoup de temps et de mémoire.
Si vous avez une chance de regarder la méthode getView
, vous verrez que convertView
est créé une seule fois. Lorsque vous appelez notifyDataChanged
, cette vue sera mise à jour. Considérant que si vous appelez invalidateViews
, les vues créées précédemment seront recréées. Ce n'est pas une bonne solution.
Votre méthode getView
est appelée lorsque vous appelez notifyDataChanged
. Donc, votre méthode getView devrait ressembler au code ci-dessous.
public List list;
public class SimpleItemViewHolder extends Object
{
public TextView textView;
public ImageView imageView;
}
public View getView(int position, View convertView, ViewGroup parent){
View itemView = convertView;
SimpleItemViewHolder viewHolder;
if(convertView==null)
{
viewHolder = (SimpleItemViewHolder)itemView.getTag();
}else{
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
itemView = inflater.inflate(R.layout.layout_name, null);
TextView labelField = (TextView) itemView.findViewById(R.id.label_field);
labelField.setText(list.get(position).Name);
//Typeface boldFont = Typeface.createFromAsset(context.getAssets(), "fonts/Font-Bold.ttf");
//labelField.setTypeface(boldFont);
ImageView imageView = (ImageView) itemView.findViewById(R.id.image_view);
//Bitmap bitmap = init your bitmap here;
//imageView.setImageBitmap(bitmap);
viewHolder = new SimpleItemViewHolder();
viewHolder.imageView = imageView;
viewHolder.textView = labelField;
itemView.setTag(viewHolder);
}
//don't create new views, instead use previous ones and update them.
viewHolder.textView.setText(list.get(position).Name);
//viewHolder.imageView.setImageBitmap(your_bitmap);
return itemView;
}
adapter.notifyDataChanged();
peut ne pas fonctionner simplement parce que les données de l'adaptateur sont obsolètes (si Activity ou un fragment n'a pas été détruit et s'est assis dans la pile arrière, par exemple).
Donc, si tout d’abord actualise les données, alors après cela fonctionnera.
Dans votre adaptateur:
class MAdapter extends BaseAdapter{
List<Objects> mObjects;
...
public void clearAdapter(){
mObjects.clear();
}
public void addNewValues(List<Objects> mObjects){
this.mObjects = mObjects;
}
...
}
adapter.clearAdapter(); // clear old values
adapter.addNewValues(MObjects);
adapter.notifyDataChanged();
Vous placez la GridView
dans com.unimelb.pt3.ui.TransparentPanel
qui est 10px
haut.
px
, vous devriez utiliser dp
.com.unimelb.pt3.ui.TransparentPanel
de Android:layout_height="10px"
par Android:layout_height="fill_parent"