2015-04-03 81 views
4

我似乎無法在我的android應用程序中更改ImageView的位置。如下所述,我將代碼放入特定方法時發生。更改Android中ImageView位置的問題

我在我的android項目中使用了IndoorAtlas庫。我下載了示例應用程序,並讓它在我的手機上運行。很棒。

此庫有一個用於處理位置更新的方法onServiceUpdate。我的目標是每當位置更新時移動ImageView。很簡單。

這裏是由例如提供的原始方法(對我來說工作正常):

/* 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()); 
} 

下面是我用它來更新代碼我ImageView的位置:

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

如果我將這些行添加到上面的onServiceUpdate方法中,該方法不起作用。 onServiceUpdate方法沒有運行。

但是,如果我將這3行放在onCreate或其他任何方法中,它的效果很好。 ImageView能夠成功移動。

我也注意到,如果我在onServiceUpdate中添加ToastAlert,也會發生同樣的情況。 onServiceUpdate方法根本不會觸發。

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

這是我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> 
+0

我認爲這是因爲你把它放在一個relativeLayout中,並且這個佈局在另一個佈局中。您可以更改圖像的位置,但佈局會將其放回到其邊框內。您還沒有在imageview應該在的相對性中定義任何屬性。左/右/上/下其他組件。 – Remi 2015-04-08 11:48:39

+0

@wiseindy已經更新了我的答案,它應該適合你。我用我的應用測試過,工作正常 – Xcihnegn 2015-04-13 09:06:24

回答

2

是方法onServiceUpdate調用非UI線程,而是由try-catch代碼忽略了錯誤?然後嘗試處理。

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(); 
    //.... 
} 
6

好吃的一種有一點。 我下載了SDK並查看了示例應用程序。 請注意您在您的代碼片段中引用的log()函數,它的impl。在示例應用程序是這樣的:

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

這意味着onServiceUpdate不是UI線程,這意味着如果它崩潰你可能無法得到任何日誌或訪問斷點上運行。

我的建議是你的3行添加到日誌方法

 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); 
     } 
    }); 
} 

,看看它是否運行,如果它只是使圖像與X和Y參數一起查看私有成員;更新onServiceUpdate上的X和Y,並將其值設置爲在UI線程上登錄的ImageView。

(如果它明顯工作,必須重做一些重構,但它會給你一個很好和快速的測試)。

3

onServiceUpdate(...)是回調方法從IndoorAtlas在後臺線程,因此,如果你想與主UI線程進行通信,那麼你需要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()); 
     } 
    }); 
} 

希望這有助於!