Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problems changing the position of an ImageView in Android

I cannot seem to change the position of an ImageView in my android application. It happens when I place my code in a specific method as explained below.

I am using the IndoorAtlas library in my android project. I downloaded the sample application and got it running on my phone. Works great.

This library has an onServiceUpdate method which is used to handle the location updates. My aim is to move an ImageView whenever the location is updated. Pretty simple.

Here is the original method as provided by the example (works fine for me):

/* IndoorAtlasListener interface */

/**
* This is where you will handle location updates.
*/
public void onServiceUpdate(ServiceState state) {
    mSharedBuilder.setLength(0);
    mSharedBuilder.append("Location: ")
            .append("\n\troundtrip : ").append(state.getRoundtrip()).append("ms")
            .append("\n\tlat : ").append(state.getGeoPoint().getLatitude())
            .append("\n\tlon : ").append(state.getGeoPoint().getLongitude())
            .append("\n\tX [meter] : ").append(state.getMetricPoint().getX())
            .append("\n\tY [meter] : ").append(state.getMetricPoint().getY())
            .append("\n\tI [pixel] : ").append(state.getImagePoint().getI())
            .append("\n\tJ [pixel] : ").append(state.getImagePoint().getJ())
            .append("\n\theading : ").append(state.getHeadingDegrees())
            .append("\n\tuncertainty: ").append(state.getUncertainty());
    log(mSharedBuilder.toString());
}

Below is the code which I use to update my ImageView's location:

ImageView imgPoint = (ImageView) findViewById(R.id.imagePoint);
imgPoint.setX(250);
imgPoint.setY(200);

If I add these lines to the onServiceUpdate method above, the method doesn't work. Nothing in the onServiceUpdate method runs.

However, if I place these 3 lines in onCreate or any other method, it works great. The ImageView is able to move successfully.

I have also noticed that if I add a Toast or Alert in onServiceUpdate, the same thing happens. The onServiceUpdate method doesn't fire at all.

Toast.makeText(getApplicationContext(), "Hello!",
      Toast.LENGTH_LONG).show();

This is my activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="300dp"
        android:layout_weight="1">

        <ImageView
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:id="@+id/imageView"
            android:layout_weight="1" />

        <RelativeLayout
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_weight="1">

            <ImageView
                android:layout_width="20dp"
                android:layout_height="20dp"
                android:layout_marginTop="1dp"
                android:layout_marginLeft="1dp"
                android:id="@+id/imagePoint"
                android:layout_weight="1" />

        </RelativeLayout>

        </RelativeLayout>

    <ListView
        android:id="@+id/list"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>
like image 912
wiseindy Avatar asked Dec 20 '22 05:12

wiseindy


2 Answers

yummy kind of has a point. I downloaded the SDK and looked at the example application. Please pay attention to the log() function you're referring to in your code snippet whose impl. in the example app is this:

    private void log(final String msg) {
    Log.d(TAG, msg);
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mLogAdapter.add(msg);
            mLogAdapter.notifyDataSetChanged();
        }
    });
}

This means that the onServiceUpdate is not running on the UI thread which means that if it crashes you might not get any log or access to breakpoints.

What i suggest is to add your 3 lines to the log method

        private void log(final String msg) {
    Log.d(TAG, msg);
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            mLogAdapter.add(msg);
            mLogAdapter.notifyDataSetChanged();
            ImageView imgPoint = (ImageView)findViewById(R.id.imagePoint);
            imgPoint.setX(250);
            imgPoint.setY(200);
        }
    });
}

And see if it runs, if it does simply make the image view a private member along with the X and Y parameters; update X and Y on the onServiceUpdate and set their value to the ImageView in log on the UI thread.

(some refactoring will have to be made afterwards if it works obviously but it will give you a good and quick test).

like image 94
Royi Benyossef Avatar answered Jan 23 '23 05:01

Royi Benyossef


From onServiceUpdate(...) is callback method from IndoorAtlas in background thread, so if you want to communicate with main UI thread, then you need runOnUIThread(...):

public void onServiceUpdate(ServiceState state) {
     mSharedBuilder.setLength(0);
     mSharedBuilder.append("Location: ")
        .append("\n\troundtrip : ").append(state.getRoundtrip()).append("ms")
        .append("\n\tlat : ").append(state.getGeoPoint().getLatitude())
        .append("\n\tlon : ").append(state.getGeoPoint().getLongitude())
        .append("\n\tX [meter] : ").append(state.getMetricPoint().getX())
        .append("\n\tY [meter] : ").append(state.getMetricPoint().getY())
        .append("\n\tI [pixel] : ").append(state.getImagePoint().getI())
        .append("\n\tJ [pixel] : ").append(state.getImagePoint().getJ())
        .append("\n\theading : ").append(state.getHeadingDegrees())
        .append("\n\tuncertainty: ").append(state.getUncertainty());

     log(mSharedBuilder.toString());

     setImagePoint(state.getImagePoint());    

}


private void setImagePoint(final ImagePoint imgPt) {

    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            ImageView imgPoint = (ImageView) findViewById(R.id.imagePoint);  
            imageMan.setX(imgPt.getI());
            imageMan.setY(imgPt.getJ());
        }
    });
}

Hope this help!

like image 30
Xcihnegn Avatar answered Jan 23 '23 06:01

Xcihnegn