Swipen in einer Listview

B

Blender4Me

Neues Mitglied
0
Moin, ich habe mich mittlerweile durch sämtliche Foren gelesen, aber nie eine wirklich passende Antwort gefunden.

Ich würde gerne eine Erkennung haben, welche TextView ich "geswiped" habe in einer ListView. Ich habe einen Code gefunden, aber der erkennt angeblich nur die gesammte ListView, und nicht die einzelnen Elemente (Außerdem bin ich mir nichtmal sicher wie genau ich den Code einbaue):


Gefundener Code:
Code:
static final int DELTA = 50;
enum Direction {LEFT, RIGHT;}
...
ListView lvSimple = (ListView) findViewById(R.id.linLayout);
...
lvSimple.setOnTouchListener(new OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) 
    {
        // TODO Auto-generated method stub
        switch (event.getAction()) 
        {
            case MotionEvent.ACTION_DOWN:
            historicX = event.getX();
            historicY = event.getY();
            break;

            case MotionEvent.ACTION_UP:
            if (event.getX() - historicX < -DELTA) 
            {
                FunctionDeleteRowWhenSlidingLeft();
                return true;
            }
            else if (event.getX() - historicX > DELTA)  
            {
                FunctionDeleteRowWhenSlidingRight();
                return true;
            } break;
            default: return false;
        }
        return false;
    }
});

Meine Mainactivity:
Code:
public class MainActivity extends Activity {

	//Widgets
	private Button addItem;
	private Button refreshItem;
	private Button loginMenu;
	
	//Strings
	private String addValue;
	private String removeValue;
	private String username;
	private String password;
	
	//Benutzername/Passwort speichern
	private SharedPreferences saveLogin;
	
	    @Override
	    protected void onCreate(Bundle savedInstanceState) {
	        super.onCreate(savedInstanceState);
	        setContentView(R.layout.activity_main);
	        
			//SharedPreferences laden
			saveLogin = getApplicationContext().getSharedPreferences("login", 0);
			loadPreferences();
	        
	        //listView updaten/erstellen
	        readValues lo = new readValues();
	        lo.execute();
	        
	        //removeItem
	        registerClickCallback();
	        
	        //addItem
	        addItem = (Button) findViewById(R.id.addItem);
	        addItem.setOnClickListener(new View.OnClickListener() {
				@Override
				public void onClick(View v) {
					openDialog();
				}
			});
	        
	      //loginMenu
	        loginMenu = (Button) findViewById(R.id.loginMenu);
	        loginMenu.setOnClickListener(new View.OnClickListener() {
				
				@Override
				public void onClick(View v) {
					Intent i = new Intent(getApplicationContext(), LoginActivity.class);
					startActivity(i);
				}
			});
	        
	        //refresh
	        refreshItem = (Button) findViewById(R.id.ButtonRefresh);
	        refreshItem.setOnClickListener(new View.OnClickListener() {
				
				@Override
				public void onClick(View v) {
					loadPreferences();
					
					readValues lo = new readValues();
					lo.execute();
					
					Toast.makeText(MainActivity.this, "Einträge neugeladen!", Toast.LENGTH_LONG).show();
				}
			});
	    }

    
    //getAddValue
    private void openDialog(){
    	AlertDialog.Builder alert = new AlertDialog.Builder(this);

    	alert.setTitle("Zur Einkaufsliste hinzufügen");
    	alert.setMessage(" ");

    	// Set an EditText view to get user input 
    	final EditText input = new EditText(this);
    	alert.setView(input);

    	alert.setPositiveButton("Bestätigen", new DialogInterface.OnClickListener() {
    	public void onClick(DialogInterface dialog, int whichButton) {
    	  
    	//Input verarbeiten
    		String addValueRaw = input.getText().toString();
    	  	try {
    	  		addValue = URLEncoder.encode(addValueRaw,"UTF-8");
			} catch (UnsupportedEncodingException e) {
				addValue = "";
			}
    	  addValue = addValue.replace(";", ":");
    	  
    	  //addValues aufrufen
    	  addValues lo = new addValues();
    	  lo.execute();
    		}
    	});

    	alert.setNegativeButton("Abbrechen", new DialogInterface.OnClickListener() {
    	  public void onClick(DialogInterface dialog, int whichButton) {
    	    // Canceled.
    	  }
    	});

    	alert.show();
    }
    
    //getRememoveValue
    private void registerClickCallback(){
    	ListView list = (ListView) findViewById(R.id.listView);
    	list.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {

			@Override
			public boolean onItemLongClick(AdapterView<?> parent, View viewClicked,
					int position, long id) {
				
					TextView textView = (TextView) viewClicked;
					final String removeValueRaw = textView.getText().toString();
			    	try {
			    		removeValue = URLEncoder.encode(removeValueRaw,"UTF-8");
					} catch (UnsupportedEncodingException e) {
						removeValue = "";
					}
			    	removeValue = removeValue.replace(';', ':');
						
			    	  //Alert erstellen
						AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
						builder.setMessage(removeValue+" entfernen?")
						       .setCancelable(false)
						       .setPositiveButton("Ja", new DialogInterface.OnClickListener() {
						           public void onClick(DialogInterface dialog, int id) {
						        	   removeValues lo = new removeValues();
						   	           lo.execute();
						   	           
						   	           Toast.makeText(MainActivity.this, removeValueRaw + " entfernt!", Toast.LENGTH_LONG).show();
						   	           
						           }
						       });
						builder.setNegativeButton("Nein", new DialogInterface.OnClickListener() {
					    	  public void onClick(DialogInterface dialog, int whichButton) {
					    	  }
					    	});
						
						AlertDialog alert = builder.create();
						alert.show();
				return false;
			}
		});
    }
    
    //listView updaten
    private class readValues extends AsyncTask<Void, Void, String> {

    	private String[] values = null;
    	
        @Override
        protected String doInBackground(Void... params) {
            internetHandler ih = new internetHandler();
            values = ih.getList(username,password,"","");
			return null;
        }

        @Override
        protected void onPostExecute(String result) {
            //Liste konvertieren
            ArrayAdapter<String> adapter = new ArrayAdapter<String>(MainActivity.this, 
                R.layout.listview_item, //Genutztes Layout
                values); //Genutzter Array

            //listView einstellen
            ListView list = (ListView) findViewById(R.id.listView);
            list.setAdapter(adapter);
        }

        @Override
        protected void onPreExecute() {}

        @Override
        protected void onProgressUpdate(Void... values) {}
    }
    
    //addValues - InternetHandler
    private class addValues extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... params) {
            internetHandler ih = new internetHandler();
            ih.getList(username,password,addValue,"");
            
            readValues lo = new readValues();
	        lo.execute();
			return null;
        }
    }
    
    //removeValues - InternetHandler
    private class removeValues extends AsyncTask<Void, Void, String> {

        @Override
        protected String doInBackground(Void... params) {
            internetHandler ih = new internetHandler();
            ih.getList(username,password,"",removeValue);
            
            readValues lo = new readValues();
	        lo.execute();
			return null;
        }
    }

    //Username/Passwort auslesen
    private void loadPreferences(){
    	if(saveLogin.getString("username", null)!=null && saveLogin.getString("password", null)!=null){
    		username = saveLogin.getString("username", null);
    		password = saveLogin.getString("password", null);
    	}else{
    		Intent i = new Intent(getApplicationContext(), LoginActivity.class);
			startActivity(i);
    	}
    }
}

Was ich eigentlich möchte:
Ich möchte den onLongClick mit dem Swipe ersetzeten/Beide sollen erhalten sein, da das ganze dann ordenlicher ist. Es wäre also sehr nett wenn mir einer eine gut erklärte Anleitung postet, oder mir hier direkt helfen könnte :thumbsup:
(Ich bin momentan noch Einsteiger in Android, habe mich eher mit Java direkt befasst)
 
Kann mir hier auch keiner helfen? :ohmy:
 
Ich würde mir einen Customadapter schreiben - abgeleitet von BaseAdapter.

Im getView klemmst du auf Hauptview noch den onTouch Listener und speicherst
dir View + Position in einer Hashtable. Es reicht ein onTouch Listener.

Wird der ausgelöst, so hast du ja den View und über die Hashtabelle kannst du
invers die Position abfragen.

Geht vielleicht einfacher. Aber ich hab beim Baseadapter ein getPositionByView
leider nicht gefunden.

Der ursprüngliche Beitrag von 19:39 Uhr wurde um 19:40 Uhr ergänzt:

Ich hab das bei mir anders gelöst. Aber ich verwende android binding.
 
Erstmal Danke das du mir helfen wolltest, aber ich verstehe nur die Hälfte von dem was du geschrieben hast :confused2:. Ich könnte natürlich das ganze umschreiben, wenn das dann halt noch genauso funktionieren würde, aber ich wüsste nicht wie. (Würde sowas mit einer RecyclerView einfacher gehen?) Wie gesagt: Ein Tutorial, direkte Hilfe oder so was ähnliches wäre ganz nett :D
 
@Blender - dreh es wie du es willst ... swipe im ListView ist kein Androidpattern.

Das "versteht" nicht jeder User.
 
Best way to detect fling gesture on ListView item

Aber ich weiss nicht so wirklich was ich damit anfangen soll, da ich mithilfe der Codebeispiele trotzdem keine Ahnung habe wie ich das momentan geswipte Item rausbekomme.

Und die Library von tim habe ich schon längst gefunden, aber da steht das sie nicht empfohlen ist.
 
Zuletzt bearbeitet:
Du kannst an jede Textview, die du in die ListView steckst theoretisch programmtisch in einen GestureDetector verwandeln und darauf das Fling-Event abfangen (Fling == Swipe).
Dann kannst du das Event Textview-spezifisch verarbeiten und musst dich dann darum kümmern das an die ListView weiter zu reichen. Dann kannst du aber nicht mehr über die ganze Liste Swipen und Beschleunigen; also eher uncool.

Alternative:
Du registrierst den GestureDetector auf der ListView und fängst das Fling-Event ab. Der Methoden-Callback hat 4 Funktionsparameter. Die ersten beiden sind MotionEvents die die X und Y Koordinate des Startpunkts und des Endpunkts des Events enthalten. Parameter 3 und 4 hier unwichtig sind die Velocity auf der X bzw. Y-Achse.
Die Idee ist: Anhand von Scroll-Position der Listview und einer Höhen-Tabelle für die Textviews (oder einem statischen Wert, falls alle Textviews gleich hoch sind) kannst du die relativen Positionen der sichtbaren Textviews berechnen und einen Hit-Test auf die Koordinaten des Fling Event Parameters ausführen. Dann hast du die Textview auf welcher der Swipe begonnen wurde.

Darf ich fragen wozu man sowas brauchen könnte?
 
bl1b schrieb:
Darf ich fragen wozu man sowas brauchen könnte?

Ich möchte damit eine ListView machen, bei der man mit einem Button einen Eintrag hinzufügt, und mit einen Swipe ihn wieder raus schieben kann. Das ist einfach eleganter und einfacher zu bedienen als ein ClickListener.
Aber ich bin wie gesagt relativ neu in Android, ich kann zwar schon einiges aber die List-/RecyclerView verstehe ich nicht so ganz.
 
Zuletzt bearbeitet:
Du kannst das Löschen mit einem ContextMenü lösen.

Das ist dafür eigentlich das Android-ische Pattern.
 
monsti schrieb:
Du kannst das Löschen mit einem ContextMenü lösen.

Das wäre dann ja noch schlimmer als meine alte Lösung ^^ Ich will es ja möglichst einfach zu bedienen haben, und das es modern wirkt.

Kann einer einfach einen Code posten? Oder hat da auch keiner sonst noch eine Idee?
 

Ähnliche Themen

A
Antworten
10
Aufrufe
1.021
swa00
swa00
D
  • Data2006
Antworten
14
Aufrufe
487
jogimuc
J
OnkelLon
Antworten
13
Aufrufe
1.986
OnkelLon
OnkelLon
Zurück
Oben Unten