# Standard Gallery Activity?



## Warrior7777 (16. Feb 2012)

Hallo miteinander

ich habe da eine kleine Frage: gibt es für Android eine Standard-Activity, um Bilder auszuwählen? Wahrscheinlich ja; wie heisst sie? Ich müsste eben ein Zusatzfeld im Resultat-Intent zurückliefern. Das geht doch nur, indem ich diese Activity überschreibe, oder?


----------



## eRaaaa (16. Feb 2012)

Ich habe leider nicht ganz verstanden was du mit deinem letzten Satz meintest, aber suchst du evtl. das hier: Gallery | Android Developers ???:L


----------



## Warrior7777 (16. Feb 2012)

Sofern man das per Intent starten kann, habe ich das gesucht. Sonst könnte ich ja eine Activity drum herum bauen. Vielen Dank!


----------



## schlingel (17. Feb 2012)

Für Picker gibt es in Android fix fertig etwas. Hier auf Stackoverflow wird erklärt wie das im Falle von Bildern funktioniert.

Wie's halt so ist mit Default-Funktionalität schaut das von Anbieter zu Anbieter anders aus. Also auf meinem HTC bekomme ich dann etwas anderes als jemand mit einem Samsung oder einem gerooteten Gerät.


----------



## Warrior7777 (17. Feb 2012)

Auch hier wieder vielen Dank. Hatte gehofft, dass es eine Activity in der Standard-Android-Bibliothek dazu gibt. Dann muss ich eben selbst eine Activity basteln.


----------



## schlingel (17. Feb 2012)

Doch, doch das gibt es. Aber die sieht auf jedem System anders aus. Du kannst dich allerdings darauf verlassen, das es so eine Picker-Activity gibt.


----------



## Warrior7777 (17. Feb 2012)

D. h. Aber, dass ich sie nicht überschreiben kann, oder? Oder bezieht sich das nur auf das Layout?


----------



## schlingel (17. Feb 2012)

Was möchtest du überschreiben?

Wenn du einen Picker haben möchtest, damit der Benutzer ein Image auswählt, sollst du sogar nichts überschreiben. Es geht ja bei den Intents darum, dass sich der Benutzer seine Lieblings-App dafür aussuchen kann.


----------



## Warrior7777 (17. Feb 2012)

Hier geht es um meine App aus dem Thread http://www.java-forum.org/mobile-geraete/131816-imageview-angezeigt.html. Beim Anklicken des "Change" bzw. des "Add new" Buttons sollte eine Gallery geöffnet werden, aus der der Benutzer ein Bild auswählt. Ist das erledigt, muss meine Activity wissen, welcher Eintrag das Intent abgeschickt hat. Da hätte ich eine Nummer als Extra-Feld angehängt. Damit dieses Extra-Feld auch in onActivityResult() ausgewertet werden kann, müsste ich doch die Gallery Activity überschreiben und im Resultat-Intent wieder zurückliefern...
Ich weiss, dass ich das ziemlich kompliziert und unsystematisch löse, hab aber keine Erfahrung im Programmieren und keine bessere Idee, das Problem zu lösen.
Vielen Dank schon im Voraus!


----------



## schlingel (17. Feb 2012)

Dann schau dir doch den Stackoverflow-Thread an den ich dir oben gepostet habe: Ein Benutzer zeigt wie man den Intent abschickt, der nächste zeigt dir wie man das Resultat auswertet.


----------



## Warrior7777 (17. Feb 2012)

Sorry aber der Thread beantwortet meine Frage nicht. Meine Buttons sind Items einer ListView. Ich muss onActivityResult() irgendwie mitteilen, welcher Button gedrückt wurde, damit diese Methode die entsprechende ImageView befüllen kann.


----------



## schlingel (17. Feb 2012)

Du musst dir in der Activity die deine Listview enthält merken welches Item den Intent abschickt und gut ist. Dann weißt du auch im onActivityResult welches Item neu zu befüllen ist.


----------



## Warrior7777 (17. Feb 2012)

Das sollte doch so machbar sein: Jeder Button erhält eine Id (=die Position des Listenelements). Wenn ein Knopf gedrückt wird, setzt er ein Klassenfeld der ListActivity auf den Wert der Id. Danke für die Hilfe!  Übrigens: Ich hab immer noch das Problem, dass bei einem Klick auf Delete zwar das standardmässig (d. h. : der Benutzer hat noch nichts gespeichert) einzige Listenelement gelöscht wird, aber nicht neu gezeichnet... Wenn ich ein Screen-Video-Capture-Programm hätte, könnte ich es Euch zeigen.


----------



## schlingel (17. Feb 2012)

Rufst du nach dem Löschen deinAdapter.notifyDataSetChanged() auf?


----------



## Warrior7777 (17. Feb 2012)

Nein, aber ich rufe meineListActivity.onContentChanged() auf. Was ist der Unterschied zwischen den beiden?


----------



## schlingel (17. Feb 2012)

Prinzipiell der, dass bei onContentChanged alle Views innerhalb der Activity neu gezeichnet werden und bei onDataSetChanged nur die ListView neu gezeichnet wird.

Speziell in deinem Fall ist das aber egal, das Element sollte verschwinden. Zeig mal deinen Code her mit dem du das Element löscht und dann onContentChanged aufruft.


----------



## Warrior7777 (17. Feb 2012)

```
Button buttond=(Button) convertView.findViewById(R.id.change2);
			buttond.setOnClickListener(new OnClickDataListener(data, context, position, listactivity, OnClickDataListener.count){
				
				public void onClick(View v){
					//delete this image
					Log.d(TAG, "delete image");
		
					WallpaperSelection removed=data.remove(this.position);
					listactivity.save(data);
					listactivity.onContentChanged();
					notifyDataSetChanged();
					Log.d(TAG, removed+" deleted.");
				}
			});
```
Sorry hab grad keine Zeit. Ich meld mich morgen wieder! Danke nochmals!


----------



## schlingel (17. Feb 2012)

Hallo, ich kenne die OnClickDataListener-Klasse/Interface nicht und wenn ich bei Google suche finde ich nur diesen Forumseintrag 

Aber ich einfach mal davon aus, dass das Ding funktioniert. Zeig einmal deine Adapter-Klasse her. Möglicherweise verwendest du für das Anzeigen der Views eine andere Collection als die Klasse für das remove verwendet.


----------



## Warrior7777 (18. Feb 2012)

Ok hier kommt die gesamte Adapter Klasse:

```
package renato.bellotti.wallpaperchanger;

import java.util.ArrayList;

import android.app.ListActivity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.provider.MediaStore;
import android.util.Log;
import android.view.*;
import android.view.View.OnClickListener;
import android.widget.*;

public class WallpaperChangerAdapter extends BaseAdapter{

	public final static String TAG="Adapter";
	
	public ArrayList<WallpaperSelection> data;
	private LayoutInflater inflator;
	Context context;
	WallpaperChangerActivity listactivity;
	
	public WallpaperChangerAdapter(Context context, ArrayList<WallpaperSelection> data, WallpaperChangerActivity listactivity){
		this.data=data;
		inflator=LayoutInflater.from(context);
		this.context=context;
		this.listactivity=listactivity;
		Log.d(TAG, "WallpaperChangerAdapter()");
	}
	
	public int getCount() {
		Log.d(TAG, "getCount()");
		if(data!=null){
			return data.size();
		}else{
			return 1;
		}
	}

	public Object getItem(int position) {
		Log.d(TAG, "getItem("+position+")");
		if(position!=0){
			return data.get(position);
		}else{
			return null;
		}
	}

	public long getItemId(int pos) {
		Log.d(TAG, "getItemId("+pos+")");
		if(data!=null){
			return data.indexOf(pos);
		}else{
			return 0;
		}
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		//Build View
		Log.d(TAG, "getView(" + position + ", " + convertView + ", " + parent +")");
		if(convertView==null){
			convertView=inflator.inflate(R.layout.selection, null);
		}
		
		if(data!=null){
			//setText
			Log.d(TAG,  "data!=null");
			TextView textview=(TextView) convertView.findViewById(R.id.textview);
			String text=context.getString(R.string.img_name, ((Integer)(position+1)).toString());
			
			Log.d(TAG, "textview.setText()");
			textview.setText(text);
			
			//getImage
			Bitmap img=null;
			if(getItem(position)!=null){
				img=((WallpaperSelection)getItem(position)).getImg();
				Log.d(TAG, "img geladen.");
			}
			
			//setImage
			if(img!=null){
				ImageView imageview=(ImageView) convertView.findViewById(R.id.img);
				imageview.setImageBitmap(img);
				Log.d(TAG, "imageview.setImageBitmap(img)");
			}else{
				ImageView imageview=(ImageView) convertView.findViewById(R.id.img);
				imageview.setImageResource(R.drawable.ic_launcher);
				Log.d(TAG, "imageview.setImageResource(R.drawable.ic_launcher)");
			}
			
			//set Listeners
			Log.d(TAG, "Change Button");
			Button buttonc=(Button) convertView.findViewById(R.id.change1);
			buttonc.setOnClickListener(new OnClickDataListener(data, context, position, listactivity, OnClickDataListener.count){
				public void onClick(View v){
					//change image
					Log.d(TAG, "change image");
					Intent intent=new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
					WallpaperChangerActivity.sender=this.id;
					this.listactivity.startActivityForResult(intent, RQ_CHANGE);
				}
			});
			
			Log.d(TAG, "Delete Button");
			Button buttond=(Button) convertView.findViewById(R.id.change2);
			buttond.setOnClickListener(new OnClickDataListener(data, context, position, listactivity, OnClickDataListener.count){
				
				public void onClick(View v){
					//delete this image
					Log.d(TAG, "delete image");
		
					WallpaperSelection removed=data.remove(this.position);
					listactivity.save(data);
					listactivity.onContentChanged();
					notifyDataSetChanged();
					Log.d(TAG, removed+" deleted.");
				}
			});
			
			Log.d(TAG, "New Button");
			Button buttonn=(Button) convertView.findViewById(R.id.select);
			buttonn.setOnClickListener(new OnClickDataListener(data, context, position, listactivity, OnClickDataListener.count){
				
				public void onClick(View v){
					//insert new image after this one
					Log.d(TAG, "new image");
					Intent intent=new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.INTERNAL_CONTENT_URI);
					this.listactivity.startActivityForResult(intent, RQ_ADD);
				}
			});
			
			OnClickDataListener.count=OnClickDataListener.count+1;
			
			
			//return the view
			Log.d(TAG, "return convertView");
			return convertView;
		}else{
			//not possible
			return null;
		}
	}
}
```
Und hier die Listener-Klasse:

```
package renato.bellotti.wallpaperchanger;

import java.util.ArrayList;

import android.app.ListActivity;
import android.content.Context;
import android.view.View;
import android.view.View.OnClickListener;

public class OnClickDataListener implements OnClickListener{
	
	//make 3 classes with static counters to set the id's for delivering onActivityResult() results
	
	
	
	public static final int RQ_ADD=1;
	public static final int RQ_CHANGE=2;
	
	public static int count=1;
	
	public int id;
	
	ArrayList<WallpaperSelection> data;
	Context context;
	int position;
	WallpaperChangerActivity listactivity;
	
	public OnClickDataListener(ArrayList<WallpaperSelection> data, Context context, int position, WallpaperChangerActivity listactivity, int id){
		super();
		this.data=data;
		this.context=context;
		this.position=position;
		this.listactivity=listactivity;
		this.id=id;
	}
	
	public void onClick(View v){
		
	}
}
```
Ich weiss, das ist ziemlich unordentlich und unsystematisch gelöst. Darüber hab ich schon einen Thread geschrieben: http://www.java-forum.org/buecher-tutorials-links/132090-systematisches-programmieren-buch.html


----------



## schlingel (18. Feb 2012)

Ha!, ich wusste es.

Die Adapter-Klasse verfügt intern schon über eine Collection, diese wird auch verwendet wenn du *remove *aufrufst. Allerdings verwendet ja dein getView die Collection *data*, die nie mitbekommen hat, das sie jetzt um ein Element kleiner sein sollte. Implementier die remove-Methode direkt in deinem Adapter und ruf diese in deinem OnClick-Handler auf, dann sollte das schon hinhauen.
Deine Klasse finde ich jetzt eigentlich nicht nötig da du ja dann doch wieder die getView-Methode in einer anonymen Klasse überschreibst.

So einen verfluchten Fehler hab ich einmal 3h gesucht! Wenn man das erste mal mit solchen Adapter-Klassen arbeitet passiert so etwas gerne. Solche Anfängerfehler hab ich schnell in den Griff bekommen als ich mit einem Studienkollegen gemeinsam ein Projekt aufgezogen habe.

Wir haben uns dann immer zum coden getroffen und 2 bis 3h konzentriert gearbeitet. Es ist unglaublich, was das für den Output bedeutet hat. Findet man mal einen Fehler hat man gleich einen Ansprechpartner und der gegenüber ist nicht "Code-Blind", was heißt er übersieht solche Sachen nicht weil er den Code ja nicht selber geschrieben hat.

Wenn sich die Gelegenheit bei dir bietet probier das mal aus. Das hilft unglaublich viel. Ich hab in einem anderen Thread auch gesehen, das du bzgl. Praxis nachgefragt hast: In meinem ersten Unternehmen hatte ich eine Art Mentor den ich wegen solchen Einsteigerfragen anhauen konnte, das half ungemein.


----------



## Warrior7777 (18. Feb 2012)

Vielen Dank (schon wieder)! Du hast Recht, sobald man ein Paar Fehler gemacht und aus ihnen gelernt hat, geht alles sehr viel schneller. Was das mit dem Ansprechpartner betrifft: Ich bring mir Java als Hobby bei, kenne aber niemanden, der das ebenfalls tut.  Das Forum hat mir schon ein paar Mal die Augen geöffnet, nicht zuletzt auch Du! Deshalb - ich kann es gar nicht oft genug sagen- vielen Dank!


----------



## Warrior7777 (19. Feb 2012)

Irgendwie steh ich immer noch auf der Leitung: Bei Objekten werden doch Referenzen übergeben. Wenn man bei einer Variable etwas macht, verändert das das Objekt und die anderen Referenzen (also die anderen Variablen) sollten das "sehen". Was hab ich falsch verstanden?


----------



## Warrior7777 (21. Feb 2012)

Ok ich habs geschafft. Alles funktioniert jetzt, soweit ich das testen kann (siehe folgenden Thread: http://www.java-forum.org/mobile-geraete/132142-internes-bilderverzeichnis.html). Ich habe die data Felder aktualisiert. Noch eine kleine Frage zu Objektorientierung: Wenn Objekte an Methoden übergeben werden, werden sie dann kopiert? Ansonsten würde doch eine Änderung, die durch eine Referenz (also eine Variable) bewirkt wurde, auch für andere Variablen sichtbar.
Nochmals vielen Dank!


----------

