12

我試圖讓我的疊加圖像做以下的事情:創建覆蓋ImageView的動畫谷歌地圖

  • 的onClick /地圖ondrag當在地圖 中間的作爲銷
  • 顯示恆定的圖像
  • onTouchUp,將標記圖像更改爲加載標記和一次數據加載完成將圖像加載到帶有文本的新圖像。

這裏是一個非常相似的解決我的問題:

animatedMarker

什麼我迄今做了什麼?

  • 放置在imageview的在我的谷歌地圖在中間,並得到了 loacation使用mMap.getCameraPosition().target 是ImageView的哪個給出了使用 setOnCameraChanged,我知道這是過時大約中間的位置座標,以及有更好的 的解決方案?
  • 其餘的部分我無法弄清楚,雖然我已經讀過幾個SO問題,聲稱他們已經實現了將framelayout包裝到谷歌地圖的片段上,並在onTouch上應用,但是也找不到真實的答案。 。

我這裏這一切正在發生片段的XML看起來是這樣的:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 
    xmlns:app="http://schemas.android.com/apk/res-auto" 
    xmlns:tools="http://schemas.android.com/tools" 
    android:layout_width="match_parent" 
    android:layout_height="match_parent" 
    tools:context=".fragments.MovableMapFragment"> 

    <fragment 
     android:id="@+id/map_frag_fmm" 
     android:name="com.google.android.gms.maps.SupportMapFragment" 
     android:layout_width="match_parent" 
     android:layout_height="wrap_content" 
     android:layout_above="@+id/tablayout_global_tabs" 
     android:layout_alignParentTop="true" /> 
<! -- long xml ahead --> 

有人知道如何實現這種行爲?

+0

我認爲你應該執行從(x,y)座標轉換,你可以從你的imageView(或只是一個地圖容器的中心,因爲在你的情況下圖像是固定的)接收到lat/lng座標。檢查[這篇文章](http://stackoverflow.com/questions/25219346/how-to-convert-from-x-y-screen-coordinates-to-latlng-google-maps) – Beloo

回答

5

Android Custom Pin

最好的解決辦法是使用RxJava/RxAndroid做後臺任務用它,但使用RX我不能發佈一個解決方案沒有看到你的代碼,並且已經有一個@ user27799的例子@Manas Chaudhari也提供了關於邏輯的一個很好的解釋(下面)。在屏幕的中心與銷

//bunch of imports 
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; 

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback 
{ 

    private GoogleMap mGoogleMap; 
    private FrameLayout frameLayout, circleFrameLayout; 
    private ProgressBar progress; 
    private TextView textView; 
    private int circleRadius; 
    private boolean isMoving = false; 
    private SupportMapFragment mapFragment; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_maps); 
    initViews(); 
    } 

    private void initViews() { 

    frameLayout = (FrameLayout) findViewById(R.id.map_container); 

    circleFrameLayout = (FrameLayout) frameLayout.findViewById(R.id.pin_view_circle); 
    textView = (TextView) circleFrameLayout.findViewById(R.id.textView); 
    progress = (ProgressBar) circleFrameLayout.findViewById(R.id.profile_loader); 

    mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); 
    mapFragment.getMapAsync(this); 

} 

    private void moveMapCamera() { 
    if (mGoogleMap == null) { 
     return; 
    } 

    CameraUpdate center = CameraUpdateFactory 
      .newLatLng(new LatLng(40.76793169992044, -73.98180484771729)); 
    CameraUpdate zoom = CameraUpdateFactory.zoomTo(15); 

    mGoogleMap.moveCamera(center); 
    mGoogleMap.animateCamera(zoom); 
} 

    @Override 
    public void onMapReady(GoogleMap googleMap) { 
    mGoogleMap = googleMap; 

    mGoogleMap.setOnCameraMoveStartedListener(new GoogleMap.OnCameraMoveStartedListener() { 

     /* User starts moving map - change your pin's image here 
     */ 
     @Override 
     public void onCameraMoveStarted(int i) { 
      isMoving = true; 
      textView.setVisibility(View.GONE); 
      progress.setVisibility(View.GONE); 
      Drawable mDrawable; 
      if (Build.VERSION.SDK_INT >= 21) 
       mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background_moving, null); 
      else 
       mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background_moving); 

      circleFrameLayout.setBackground(mDrawable); 
      resizeLayout(false); 
     } 
    }); 

    /*User stoped moving map -> retrieve location and do your background task */ 
    mGoogleMap.setOnCameraIdleListener(new GoogleMap.OnCameraIdleListener() { 
     @Override 
     public void onCameraIdle() { 

      isMoving = false; 
      textView.setVisibility(View.INVISIBLE); 
      progress.setVisibility(View.VISIBLE); 
      resizeLayout(true); 

      /* this is just an example that simulates data loading 
       you shoud substitute it with your logic 
      */ 
      new Handler().postDelayed(new Runnable() { 
       public void run() { 

        Drawable mDrawable; 
        if (Build.VERSION.SDK_INT >= 21) 
         mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background, null); 
        else 
         mDrawable = getApplicationContext().getResources().getDrawable(R.drawable.circle_background); 

        if (!isMoving) { 
         circleFrameLayout.setBackground(mDrawable); 
         textView.setVisibility(View.VISIBLE); 
         progress.setVisibility(View.GONE); 
        } 
       } 
      }, 1500); 
     } 
    }); 

    MapsInitializer.initialize(this); 
    moveMapCamera(); 
    } 

    //resing circle pin 
    private void resizeLayout(boolean backToNormalSize){ 
    FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) circleFrameLayout.getLayoutParams(); 

    ViewTreeObserver vto = circleFrameLayout.getViewTreeObserver(); 
    vto.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { 
     @Override 
     public void onGlobalLayout() { 
      circleFrameLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this); 
      circleRadius = circleFrameLayout.getMeasuredWidth(); 
     } 
    }); 

    if (backToNormalSize) { 
     params.width = WRAP_CONTENT; 
     params.height = WRAP_CONTENT; 
     params.topMargin = 0; 

    } else { 
     params.topMargin = (int) (circleRadius * 0.3); 
     params.height = circleRadius - circleRadius/3; 
     params.width = circleRadius - circleRadius/3; 
    } 

    circleFrameLayout.setLayoutParams(params); 
    } 

} 

佈局文件:

<?xml version="1.0" encoding="utf-8"?> 
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" 
     android:id="@+id/map_container" 
     android:layout_width="match_parent" 
     android:layout_height="match_parent"> 

<fragment xmlns:tools="http://schemas.android.com/tools" 
      android:id="@+id/map" 
      android:name="com.google.android.gms.maps.SupportMapFragment" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      tools:context="com.example.mapstest.MapsActivity" /> 

<FrameLayout 
    android:id="@+id/pin_view_line" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:layout_gravity="center" 
    android:layout_marginTop="@dimen/line_top_margin" 
    android:background="@drawable/line_background"/> 

<FrameLayout 
    android:id="@+id/pin_view_circle" 
    android:layout_gravity="center" 
    android:layout_width="wrap_content" 
    android:layout_height="wrap_content" 
    android:background="@drawable/circle_background"> 

    <TextView 
     android:id="@+id/textView" 
     android:layout_margin="@dimen/inner_circle_margin" 
     android:layout_width="@dimen/inner_circle_radius" 
     android:layout_height="@dimen/inner_circle_radius" 
     android:layout_gravity="top|center_horizontal" 
     android:gravity="center" 
     android:text="12 min" 
     android:textSize="@dimen/text_size" 
     android:textColor="@android:color/white"/> 

    <ProgressBar 
     android:id="@+id/profile_loader" 
     android:layout_margin="@dimen/inner_circle_margin" 
     android:layout_width="@dimen/inner_circle_radius" 
     android:layout_height="@dimen/inner_circle_radius" 
     android:indeterminate="true" 
     android:layout_gravity="top|center_horizontal" 
     android:visibility="gone" 
     android:contentDescription="@null"/> 

</FrameLayout> 

圈背景不移動時:當MAP移動

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval">  
<solid android:color="@android:color/holo_green_dark"/> 
<stroke 
    android:width="@dimen/stroke_width" 
    android:color="@android:color/black"/> 
<size 
    android:width="@dimen/circle_radius" 
    android:height="@dimen/circle_radius"/> 
</shape> 

圈背景:

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="oval">  
<solid android:color="@android:color/black"/> 
<size 
    android:width="@dimen/circle_radius" 
    android:height="@dimen/circle_radius"/> 
</shape> 

行背景文件:

<?xml version="1.0" encoding="utf-8"?> 
<shape xmlns:android="http://schemas.android.com/apk/res/android" 
    android:shape="rectangle">  
<solid android:color="@android:color/black"/> 
<size 
    android:width="@dimen/line_width" 
    android:height="@dimen/line_height"/> 
</shape> 

尺寸:

<?xml version="1.0" encoding="utf-8"?> 
<resources> 
    <dimen name="circle_radius">48dp</dimen> 
    <dimen name="line_width">4dp</dimen> 
    <dimen name="line_height">40dp</dimen> 
    <dimen name="stroke_width">4dp</dimen> 
    <dimen name="text_size">10sp</dimen> 
    <dimen name="inner_circle_radius">40dp</dimen> 
    <dimen name="inner_circle_margin">4dp</dimen> 
    <dimen name="line_top_margin">20dp</dimen> 
</resources> 

我希望它可以幫助你,但如果你有任何問題隨時問,或者如果你看到這方面你會改善 - 編輯我的解決方案。

乾杯。

1

佈局

標記是指定位在地圖上的特定座標。因此,他們在您更改地圖時移動。

由於您的引腳始終位於地圖的中間,因此不適合使用Marker來創建它。相反,您可以將它放在地圖容器中心的地圖片段之外。所以,你應該XML如下所示:

<RelativeLayout> 
    <fragment 
    android:id="@+id/map_fragment" /> 

    <RelativeLayout 
    android:id="@+id/pin_view" 
    android:centerInParent="true" /> 
</RelativeLayout> 

可孩子添加到pin_view實現動畫按照您的要求。

引腳狀態

根據您所提供的GIF,可以有用於銷三種狀態。

  • 加載
  • 加載

聽衆

您可以通過設置這些聽衆觸發動畫:

  • setOnCameraMoveStartedListener
    • 以前的值需要失效。更改PIN的狀態Empty
    • 取消正在進行的任何請求
  • setOnCameraIdleListener
    • 使用map.getCameraPosition()
    • 更改PIN的狀態設置爲 '正在載入'
    • 觸發網絡電話來獲取數據獲取座標。在回調
      • 更改PIN的狀態設置爲「加載」,並顯示該值 注意回調將不會執行,如果用戶移動之前完成的API,我們將盡快取消該請求爲用戶移動。所以,這種情況下也將採取的
4

小心把你的FrameLayout佈局和圖片繪製了地圖。 當GoogleMap的準備(我的代碼使用RxJava):

Observable.<Void>create(subscriber -> { 
     mMap.setOnCameraIdleListener(() -> subscriber.onNext(null)); 
    }) 
      .debounce(1, TimeUnit.SECONDS) 
      .subscribeOn(AndroidSchedulers.mainThread()) 
      .observeOn(AndroidSchedulers.mainThread()) 
      .subscribe(aVoid -> { 
       LatLng newPos = mMap.getProjection().fromScreenLocation(new Point(mBinding.googleMap.getWidth()/2, mBinding.googleMap.getHeight()/2)); 

       makeServerRequest(newPos); 
      });