Problems changing the position of an ImageView in Android

主宰稳场 提交于 2019-12-10 16:09:14

问题


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>

回答1:


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).




回答2:


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!




回答3:


Is the method onServiceUpdate invoked on non-UI thread but ignored error by try-catch? then try Handle.

private Handler mUpdateHandler = new Handler() {
    public void handleMessage(Message msg){
        if (msg.obj instanceof ServiceState) {
            ServiceState state = (ServiceState) msg.obj;
            ImageView imgPoint = (ImageView) findViewById(R.id.imagePoint);
            imgPoint.setX(state.getMetricPoint().getX());
            imgPoint.setY(state.getMetricPoint().getY());
        }
    }
}

public void onServiceUpdate(ServiceState state) {
    mUpdateHandler.obtainMessage(0, state).sendToTarget();
    //....
}


来源:https://stackoverflow.com/questions/29433468/problems-changing-the-position-of-an-imageview-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!