36071

Android listactivity scrolling with accelerometer issue

Question:

I have a ListActivity in my android application that works perfectly. Until I decided to add scrolling capabilities by using the accelerometer.

Here's my code:

package be.pxl.minecraftguide; import android.app.ListActivity; import android.content.ContentResolver; import android.database.Cursor; import android.hardware.Sensor; import android.hardware.SensorEvent; import android.hardware.SensorEventListener; import android.hardware.SensorManager; import android.os.Bundle; import android.support.v4.widget.SimpleCursorAdapter; import android.widget.ListView; import be.pxl.minecraftguide.providers.RecipeCategoryProvider; public class Crafting extends ListActivity implements SensorEventListener { private SimpleCursorAdapter adapter; private SensorManager sensorManager; private Sensor acceleroMeter; private float[] history = new float[2]; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.categorylist); ContentResolver cr = getContentResolver(); Cursor cursor = cr.query(RecipeCategoryProvider.CONTENT_URI, null, null, null, null); String[] from = {RecipeCategoryProvider.COL_CATID, RecipeCategoryProvider.COL_CATIMG, RecipeCategoryProvider.COL_CATDESC}; int[] to = { R.id.txtCatID, R.id.imgCatImage, R.id.txtCatDescription }; adapter = new SimpleCursorAdapter(getApplicationContext(), R.layout.categoryrow, cursor, from, to, 0); /*SimpleCursorAdapter.ViewBinder viewBinder = new SimpleCursorAdapter.ViewBinder() { @Override public boolean setViewValue(View view, Cursor cursor, int arg2) { if(view.getId() == R.id.imgCatImage) { ImageView image = (ImageView)findViewById(R.id.imgCatImage); image.setImageResource(R.drawable.ic_launcher); } return false; } };*/ setListAdapter(adapter); //__________BRON/ http://stackoverflow.com/questions/18751878/android-using-the-accelerometer-to-create-a-simple-maraca-app_____________ sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE); acceleroMeter = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER); sensorManager.registerListener(this, acceleroMeter, 1000000); /*recipeListView.setOnClickListener(new OnItemClickListener(){ public void onItemClick(AdapterView<?> parent, View row, int position, long id) { TextView txtId = (TextView)row.findViewById(R.id.txtRecipeID); int recipeID = Integer.parseInt(txtId.getText().toString()); String description = ((TextView)row.findViewById(R.id.txtRecipeDescription)).getText().toString(); // Launching new Activity on selecting single List Item // Intent craftingDetailIntent = new Intent(getApplicationContext(), craftingdetail.class); // sending data to new activity //craftingDetailIntent.putExtra("Category", item); //startActivity(craftingDetailIntent); } });*/ } /*@Override protected void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub super.onListItemClick(l, v, position, id); int recipeID = Integer.parseInt(v.getTag().toString()); }*/ @Override protected void onPause() { // TODO Auto-generated method stub super.onPause(); sensorManager.unregisterListener(this); //De accelerometer afzetten } @Override protected void onResume() { // TODO Auto-generated method stub super.onResume(); sensorManager.registerListener(this, acceleroMeter, SensorManager.SENSOR_DELAY_UI); //De accelerometer opnieuw starten } @Override public void onAccuracyChanged(Sensor sensor, int accuracy) { // TODO Auto-generated method stub } @Override public void onSensorChanged(SensorEvent event) { if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) { float xChange = history[0] - event.values[0]; float yChange = history[1] - event.values[1]; //Verschil tussen nieuwe en oude positie ophalen. history[0] = event.values[0]; history[1] = event.values[1]; //Nieuwe waarden bewaren voor volgende event trigger if (xChange > 2){ //Links } else if (xChange < -2){ //Rechts } if (yChange > 2){ getListView().smoothScrollBy(getListView().getHeight() * adapter.getCount(), 2000); getListView().postDelayed(new Runnable() { @Override public void run() { getListView().smoothScrollBy(0, 0); //Geanimeerd scrollen naar laatste positie getListView().setSelection(adapter.getCount() - 1); } }, 1000); } else if (yChange < -2){ getListView().smoothScrollBy(getListView().getHeight() * adapter.getCount(), 2000); getListView().postDelayed(new Runnable() { @Override public void run() { getListView().smoothScrollBy(0, 0); //Geanimeerd scrollen naar eerste positie positie getListView().setSelection(0); } }, 1000); } } } }

The problem is, when I make an upward movement, the list should scroll down ad stay at the bottom. But my list scrolls down and then back up occasionally. Same goes for downward movements.

<?xml version="1.0" encoding="utf-8"?> <ListView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/list" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@drawable/minecraft_portrait" android:transcriptMode="alwaysScroll" > </ListView>

And not really relevant, but here's my row xml

<?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/recipeRow" android:layout_width="match_parent" android:layout_height="65sp" android:background="@drawable/listview_selector" > <TextView android:id="@+id/txtCatID" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="5dp" android:layout_marginTop="5dp" android:textColor="@android:color/black" /> <ImageView android:id="@+id/imgCatImage" android:layout_width="wrap_content" android:layout_height="55sp" android:layout_centerVertical="true" android:layout_alignParentLeft="true" android:src="@drawable/ic_launcher" android:contentDescription="@string/recipecategory" /> <TextView android:id="@+id/txtCatDescription" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_centerVertical="true" android:layout_toRightOf="@id/imgCatImage" android:gravity="center" android:background="#99FFFFFF" android:textSize="20sp" android:textColor="@android:color/black" android:text="test" /> </RelativeLayout>

How can I fix this?

Answer1:

I was looking for the same solution for scrolling a ListActivity using sensors (in context of Google Glass), and the other answer didn't work for me (scrolling was erratic).

I was able to get another version working though, based just on the ListView (mList, in the example below). Note that this also assumes a fixed number of items on the screen at one time (since all Glass displays are the same size), but this could be changed to check how many items are on the screen for a more general Android solution. This solution also uses the <a href="http://developer.android.com/reference/android/hardware/Sensor.html#TYPE_ROTATION_VECTOR" rel="nofollow">Sensor.TYPE_ROTATION_VECTOR</a>, which does some sensor fusion on supported devices, and therefore has a less noisy output (resulting in less unwanted up/down movement).

Register the listener:

mSensorManager = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE); mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR), SensorManager.SENSOR_DELAY_UI);

...and here's the onSensorChanged() method:

@Override public void onSensorChanged(SensorEvent event) { if (mList == null) { return; } if (event.sensor.getType() == Sensor.TYPE_ROTATION_VECTOR) { SensorManager.getRotationMatrixFromVector(mRotationMatrix, event.values); // Only uncomment the below two lines if you're running on Google Glass //SensorManager.remapCoordinateSystem(mRotationMatrix, SensorManager.AXIS_X, // SensorManager.AXIS_Z, mRotationMatrix); SensorManager.getOrientation(mRotationMatrix, mOrientation); mHeading = (float) Math.toDegrees(mOrientation[0]); mPitch = (float) Math.toDegrees(mOrientation[1]); float xDelta = history[0] - mHeading; // Currently unused float yDelta = history[1] - mPitch; history[0] = mHeading; history[1] = mPitch; float Y_DELTA_THRESHOLD = 0.10f; //Log.d(TAG, "Y Delta = " + yDelta); int scrollHeight = mList.getHeight() / 19; // 4 items per page, scroll almost 1/5 an item //Log.d(TAG, "ScrollHeight = " + scrollHeight); if (yDelta > Y_DELTA_THRESHOLD) { //Log.d(TAG, "Detected change in pitch up..."); mList.smoothScrollBy(-scrollHeight, 0); } else if (yDelta < -Y_DELTA_THRESHOLD) { //Log.d(TAG, "Detected change in pitch down..."); mList.smoothScrollBy(scrollHeight, 0); } } }

Additional details are in this answer: <a href="https://stackoverflow.com/a/23298377/937715" rel="nofollow">https://stackoverflow.com/a/23298377/937715</a>

For code that remaps the sensor coordinate system to handle all possible orientation changes on Android devices, see: <a href="https://stackoverflow.com/a/22138449/937715" rel="nofollow">https://stackoverflow.com/a/22138449/937715</a>

Answer2:

Alright, I fixed this problem a few days ago.

If someone else is experiencing this, it might help to increase the change in the Y-axis.

if (yChange > 12){ listView.smoothScrollBy(listView.getHeight() * adaptor.getCount(), 1000); listView.postDelayed(new Runnable() { @Override public void run() { listView.smoothScrollBy(0, 0); //Geanimeerd scrollen naar laatste positie listView.setSelection(adaptor.getCount() - 1); } }, 500); } else if (yChange < -12){ listView.smoothScrollBy(listView.getHeight() * adaptor.getCount(), 1000); listView.postDelayed(new Runnable() { @Override public void run() { listView.smoothScrollBy(0, 0); //Geanimeerd scrollen naar eerste positie positie listView.setSelection(0); } }, 500); }

Recommend

  • Delete sms from another activity Android
  • How to replace gridView to RecyclerView
  • Android Gallery with first thumbnail as coverpage
  • Android OnItemClickListener long id parameter is not giving field id
  • List most frequently selected items(3 items) at top of the adapter using android list fragments?
  • When I search listview item and then click desire item, it does open first position of List View
  • NullPointerException when setImageDrawable and setImageResource in an ImageSwitcher
  • Android listactivity scrolling with accelerometer issue
  • trying not to repeat myself (android/java)
  • Display video files in listview from sdcard folder
  • Refresh ListView with ArrayAdapter after editing an Item
  • setOnItemClickListener not getting called
  • How to get text in a selected row in ListView, if ListView got item and subitem
  • Android ListView Multi-Choice don't show highlight after chlicking
  • Spinner Items Not Clickable
  • null pointer exception on set on click listener in list view on android
  • How to set prompt value on setSelection() on Spinner in Android
  • How to get Custom Gird child item click event?
  • Eclipse Juno/Android broken, the debug is wrong and gen folder not created (R error)
  • If OnItemClickListener is an interface in Android, how can we create an object based on it?
  • Android setOnItemClickListener
  • openOptionsMenu() not working
  • JSON Array to ImageView in GridView
  • Open new Activity after click item in navigation drawer menu
  • Do I need to set Internet permission for opening a website in Android?
  • Error inflating class ir.noghteh.JustifiedTextView
  • Force Down error in MapView
  • Error inflating class ImageButton
  • Eventbus onMessageEvent not getting called
  • Remove item from the listview in Android
  • Android: How do you create an EditText field in java class
  • How to associate .mp3 files in Android Studio
  • Retrofit SocketTimeoutException (and/or http 500 error) on http-POST
  • embed rChart in Markdown
  • How to get Windows thread pool to call class member function?
  • IndexOutOfRangeException on multidimensional array despite using GetLength check
  • costura.fody for a dll that references another dll
  • Observable and ngFor in Angular 2
  • UserPrincipal.Current returns apppool on IIS
  • java string with new operator and a literal