12

staram się zrobić mój obraz nakładki zrobić następujące rzeczy:Tworzenie nakładek ImageView Animation Google Map

  • onClick/onDrag mapy, wykazują stały obraz na środku mapy który jest pin
  • onTouchUp, zmień obraz znacznika na Ładowanie znacznika i po załadowaniu danych ładowanie zakończone ładowanie obrazu do nowego obrazu z tekstem.

Tu jest całkiem podobny do rozwiązania mojego problemu:

animatedMarker

co zrobiłem do tej pory?

  • umieścił ImageView nad moim mapie google w środku i dostał loacation tego ImageView wykorzystaniem mMap.getCameraPosition().target co daje współrzędne położenia ok średnim użyciu setOnCameraChanged, wiem, że to przestarzałe, dobrze mieć lepsze rozwiązanie ?.
  • Reszta części nie mogę rozgryźć, chociaż przeczytałem kilka pytań SO twierdzących, że zaimplementowały to zawijanie framelayout nad fragmentem mapy google i zastosowanie w tym celu, ale nie mogę znaleźć autentycznej odpowiedzi na to też .

mój xml fragmentu, gdzie to wszystko się dzieje wygląda następująco:

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

Ktoś wie, jak osiągnąć ten rodzaj zachowania?

+0

Myślę, że powinieneś wykonać konwersję ze współrzędnych (x, y), które możesz otrzymać z obrazu (lub tylko środka kontenera mapy, ponieważ w twoim przypadku ten obraz jest stały) na współrzędne lat/lng. Sprawdź [ten post] (http://stackoverflow.com/questions/25219346/how-to-convert-from-x-y-screen-coordinates-to-latlng-google-maps) – Beloo

Odpowiedz

5

Android Custom Pin

Najlepszym rozwiązaniem byłoby wykorzystanie RxJava/RxAndroid i wykonać zadania w tle z nim, ale nie mogę zakładać rozwiązanie za pomocą RX bez zobaczenia kodu i już jest przykład z @ user27799 również @Manas Chaudhari dostarczył wielkiego wyjaśnienia logiki (poniżej).

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

} 

plik Układ z kołkiem w środku ekranu:

<?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> 

okrąg tła, gdy nie jest w ruchu:

<?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> 

Koło tło kiedy mapa jest w ruchu:

<?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> 

Linia plików background:

<?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> 

Wymiary:

<?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> 

Mam nadzieję, że pomaga, ale jeśli masz jakiekolwiek pytania, nie wahaj się zapytać czy widać obszary, które chcesz poprawić - edytuj moje rozwiązanie.

Pozdrawiam.

1

Układ

Znaczniki mają być ustawione na określonych współrzędnych na mapie. Tak więc poruszają się po zmianie mapy.

Ponieważ pinezka znajduje się zawsze pośrodku mapy, nie można jej utworzyć za pomocą Marker. Zamiast tego możesz umieścić go poza fragmentem mapy w środku kontenera mapy. Więc XML powinien wyglądać następująco:

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

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

Możesz dodać dzieciom pin_view wdrożyć animacji jak na swoje wymagania.

Pin Zjednoczone

Na podstawie dostarczonych przez ciebie gif, nie może być trzy stany na kołku.

  • Puste
  • Ładowanie
  • Loaded

Słuchaczy

Można wywołać animacji poprzez ustawienie tych słuchaczy:

  • setOnCameraMoveStartedListener
    • Poprzednia wartość musi zostać unieważniona. Zmień PIN state do Empty
    • Anuluj żadnych bieżących żądań
  • setOnCameraIdleListener
    • współrzędne Get użyciu stan map.getCameraPosition()
    • Zmień PIN do 'Ładowanie'
    • wywołać połączenia sieciowego do pobierania danych. W zwrotnego stan
      • Zmień PIN do „Loaded” i wyświetli wartość Informacja zwrotna że nie zostaną wykonane, jeśli użytkownik porusza się przed api uzupełnia, jak będziemy anulować prośbę jak najszybciej ruchów użytkownika. Tak, ten scenariusz zostanie również załatwione
4

można umieścić układ w FrameLayout i narysować obraz nad mapą. Kiedy GoogleMap gotowy (Mój kod użycie 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); 
      });