12

Tôi cố gắng để làm cho hình ảnh lớp phủ của tôi để làm những việc sau đây:Tạo Overlay ImageView Animation Google Map

  • onClick/onDrag của bản đồ, hiển thị một hình ảnh liên tục ở giữa bản đồ mà là một pin
  • onTouchUp, thay đổi hình ảnh đánh dấu thành Đang tải điểm đánh dấu và một lần dữ liệu tải hình ảnh tải thay đổi hoàn toàn về hình ảnh mới bằng văn bản.

Dưới đây là một giải pháp khá tương tự như vấn đề của tôi:

animatedMarker

gì tôi đã làm cho đến nay?

  • Đặt một ImageView trên bản đồ google của tôi ở giữa, và có loacation của IMAGExem rằng việc sử dụng mMap.getCameraPosition().target mang đến cho vị trí khoảng giữa tọa độ sử dụng setOnCameraChanged, tôi biết đó là bị phản đối, cũng có một giải pháp tốt hơn ?.
  • Phần còn lại của phần tôi không thể tìm ra, mặc dù tôi đã đọc một số câu hỏi SO tuyên bố họ đã thực hiện nó gói framelayout trên mảnh của bản đồ google, và áp dụng onTouch trên đó, nhưng không thể tìm thấy một câu trả lời đích thực cho rằng một quá .

xml của tôi về mảnh nơi tất cả điều này đang xảy ra trông như thế này:

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

Có người biết làm thế nào để đạt được loại hành vi?

+0

Tôi nghĩ bạn nên thực hiện chuyển đổi từ tọa độ (x, y), mà bạn có thể nhận được từ imageView của bạn (hoặc chỉ là trung tâm của vùng chứa bản đồ, vì trong trường hợp hình ảnh của bạn được cố định) với tọa độ lat/lng. Kiểm tra [bài đăng này] (http://stackoverflow.com/questions/25219346/how-to-convert-from-x-y-screen-coordinates-to-latlng-google-maps) – Beloo

Trả lời

5

Android Custom Pin

Giải pháp tốt nhất là nên sử dụng RxJava/RxAndroid và làm nhiệm vụ nền với nó, nhưng tôi không thể gửi một giải pháp sử dụng rx mà không nhìn thấy mã của bạn và đã có một ví dụ từ @ user27799 cũng @Manas Chaudhari cung cấp một lời giải thích tuyệt vời về logic (xuống dưới).

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

} 

tập tin Layout với pin ở trung tâm của màn hình:

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

Vòng nền khi không di chuyển:

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

Vòng nền khi bản đồ được di chuyển:

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

dòng tập tin nền:

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

Kích thước:

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

Tôi hy vọng nó giúp bạn, nhưng nếu bạn có thắc mắc đừng ngần ngại hỏi hoặc nếu bạn thấy khu vực mà bạn muốn cải thiện - chỉnh sửa giải pháp của tôi.

Chúc mừng.

1

Bố cục

Các điểm đánh dấu được định vị ở các tọa độ cụ thể trên Bản đồ. Do đó, chúng di chuyển khi bạn thay đổi Bản đồ.

Khi ghim của bạn luôn ở giữa bản đồ, nó không phù hợp để tạo ra nó bằng cách sử dụng Marker. Thay vào đó, bạn có thể đặt nó bên ngoài mảnh bản đồ ở giữa vùng chứa bản đồ. Vì vậy, XML của bạn sẽ trông giống như sau:

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

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

Bạn có thể thêm trẻ em vào pin_view để triển khai hoạt ảnh theo yêu cầu của bạn.

Pin Hoa

Dựa trên gif do bạn cung cấp, có thể có ba trạng thái cho ghim.

  • Rỗng
  • tải
  • Loaded

Listeners

Bạn có thể kích hoạt các hình ảnh động bằng cách thiết lập những thính giả:

  • setOnCameraMoveStartedListener
    • Giá trị trước đó cần phải được vô hiệu. Thay đổi trạng thái pin để Empty
    • Hủy bỏ bất kỳ yêu cầu liên tục
  • setOnCameraIdleListener
    • Nhận phối sử dụng trạng thái map.getCameraPosition()
    • thay đổi pin để 'Loading'
    • kích hoạt một cuộc gọi mạng để lấy dữ liệu. Trong gọi lại
      • Thay đổi trạng thái của pin thành 'Đã tải' và hiển thị giá trị Lưu ý rằng gọi lại sẽ không được thực thi, nếu chúng tôi sẽ hủy yêu cầu ngay sau khi người dùng di chuyển. Vì vậy, kịch bản này cũng sẽ được đưa về chăm sóc
4

Đặt bạn bố trí trong FrameLayout và vẽ hình ảnh trên bản đồ. Khi googlemap sẵn sàng (Mỹ sử dụng RxJava code):

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