如何为Android制作自定义地方选择器

时间:2016-04-06 11:33:05

标签: android google-maps user-interface google-places-api

据我所知Google不允许开发人员自定义地方选择器布局,

所以我想制作一个如下图所示的地方选择器。

它来自deliveroo app,我使用的是地图api,但它并不完全像这张照片。

这个选择器就像定位选择器api一样。

这是我的代码:

public class Map extends AppCompatActivity implements OnMapReadyCallback {

private GoogleMap mMap;
private LatLng markerLatLong;
private static final int REQUEST_CODE_LOCATION_ENABLE = 1;
private static final int PLACE_AUTOCOMPLETE_REQUEST_CODE = 2;
private static String TAG = Map.class.getSimpleName();

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.map);
    setToolbar();
    setFragment();
}

public void setFragment() {
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
}

public void setToolbar() {

    Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
    setSupportActionBar(toolbar);
    if (getSupportActionBar() != null) {
        getSupportActionBar().setDisplayShowTitleEnabled(false);
        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
    }
    onSearchPlacesClicked(toolbar);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQUEST_CODE_LOCATION_ENABLE) {
        if (resultCode == RESULT_OK) {
            Log.e(TAG, "location enabled");
            setLocation();
        }
    }else if (requestCode == PLACE_AUTOCOMPLETE_REQUEST_CODE) {
            if (resultCode == RESULT_OK) {
                Place place = PlaceAutocomplete.getPlace(this, data);
                Log.e(TAG, "Place: " + place.getName());
                setPlace(place.getLatLng());

            } else if (resultCode == PlaceAutocomplete.RESULT_ERROR) {
                Status status = PlaceAutocomplete.getStatus(this, data);
                // TODO: Handle the error.
                Log.i(TAG, status.getStatusMessage());

            } else if (resultCode == RESULT_CANCELED) {
                // The user canceled the operation.
            }
        }
}


/**
 * Manipulates the map once available.
 * This callback is triggered when the map is ready to be used.
 * This is where we can add markers or lines, add listeners or move the camera. In this case,
 * we just add a marker near Sydney, Australia.
 * If Google Play services is not installed on the device, the user will be prompted to install
 * it inside the SupportMapFragment. This method will only be triggered once the user has
 * installed Google Play services and returned to the app.
 */
@Override
public void onMapReady(GoogleMap googleMap) {
    mMap = googleMap;
    mMap.setMyLocationEnabled(true);
    mMap.getUiSettings().setMyLocationButtonEnabled(true);
    mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
        @Override
        public void onMapClick(LatLng latLng) {
            setPlace(latLng);
        }
    });
    Button b = (Button) findViewById(R.id.pick_place);
    b.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            if (markerLatLong != null) {
                addAddressToPref(-1, markerLatLong.latitude, markerLatLong.longitude);
                startActivity(new Intent(Map.this, StoreList.class));
                Map.this.finish();
            } else {
                Toast.makeText(Map.this, R.string.no_place_selected, Toast.LENGTH_SHORT).show();
            }
        }
    });
    setLocation();

}

public void addAddressToPref(long id, double latitude, double longitude) {
    Singleton.getInstance().setAddressPref(id, latitude, longitude);
}

public void setPlace(final LatLng latLng) {

    mMap.setOnCameraChangeListener(new GoogleMap.OnCameraChangeListener() {

        @Override
        public void onCameraChange(CameraPosition arg0) {
          mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 15));

            // Remove listener to prevent position reset on camera move.
            mMap.setOnCameraChangeListener(null);
        }
    });
    markerLatLong = latLng;
    mMap.clear();
    mMap.addMarker(new MarkerOptions().position(latLng).title(getString(R.string.my_location)));



}

public void setLocation() {
    AppLocationService gps = new AppLocationService(this);

    // check if GPS enabled
    if (gps.canGetLocation()) {

        double latitude = gps.getLatitude();
        double longitude = gps.getLongitude();

        getLocation(latitude, longitude);
        // \n is for new line
    } else {
        // can't get location
        // GPS or Network is not enabled
        // Ask user to enable GPS/network in settings
        buildAlertMessageNoGps();
    }
}

public void getLocation(double latitude, double longitude) {
    final CoordinatorLayout rootLayout = (CoordinatorLayout) findViewById(R.id.root_view);
    if (latitude != 0 && longitude != 0) {
        LatLng latLng = new LatLng(latitude, longitude);
        CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngZoom(latLng, 15);
        mMap.animateCamera(cameraUpdate);
    } else {
        Snackbar.make(rootLayout, getResources().getString(R.string.location_problem),
                Snackbar.LENGTH_INDEFINITE).setAction("سعی دوباره", new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setLocation();
            }
        }).show();
    }
}

private void buildAlertMessageNoGps() {
    final AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setMessage(getString(R.string.turn_on_location_text))
            .setCancelable(false)
            .setPositiveButton(getString(R.string.ok), new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, final int id) {
                    Intent intent = new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                    startActivityForResult(intent, REQUEST_CODE_LOCATION_ENABLE);
                }
            })
            .setNegativeButton(getString(R.string.exit), new DialogInterface.OnClickListener() {
                public void onClick(final DialogInterface dialog, final int id) {
                    dialog.cancel();
                    Map.this.finish();
                }
            });
    final AlertDialog alert = builder.create();
    alert.show();

}

public void onSearchPlacesClicked(Toolbar toolbar) {
    ImageView searchPlace = (ImageView) toolbar.findViewById(R.id.search_place);
    searchPlace.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View view) {
            autoCompleteMethod();
        }
    });
}

public void autoCompleteMethod() {
    try {
        Intent intent =
                new PlaceAutocomplete.IntentBuilder(PlaceAutocomplete.MODE_OVERLAY)
                        .build(this);
        startActivityForResult(intent, PLACE_AUTOCOMPLETE_REQUEST_CODE);
    } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException e) {
        // TODO: Handle the error.
    }
}

@Override
protected void onResume() {
    super.onResume();
    if (mMap != null) {
        setLocation();
    }
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) {
        case android.R.id.home:
            onBackPressed();
            break;
    }
    return true;
}

@Override
public void onBackPressed() {
    startActivity(new Intent(Map.this, StoreList.class));
    Map.this.finish();
}
}

enter image description here

2 个答案:

答案 0 :(得分:9)

为地图制作活动并拨打您想要位置的地方:

<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context=".Activity.InsertMapsActivity">

<Button
    android:layout_width="wrap_content"
    android:id="@+id/btn_set_garage_location"
    android:text="set location"
    android:layout_height="wrap_content"/>
<fragment
    android:id="@+id/map"
    android:name="com.google.android.gms.maps.SupportMapFragment"
    android:layout_width="match_parent"
    android:layout_height="match_parent"/>

java代码:

public class InsertMapsActivity extends FragmentActivity implements LocationListener
{

private GoogleMap googleMap;
private LatLng garageLocation;
Button btnSetGarageLocation;

@Override
protected void onCreate(Bundle savedInstanceState)
{
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_insert_maps);
    btnSetGarageLocation = (Button) findViewById(R.id.btn_set_garage_location);
    int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());
    // Obtain the SupportMapFragment and get notified when the map is ready to be used.

    if (status != ConnectionResult.SUCCESS)
    { // Google Play Services are not available

        int requestCode = 10;
        Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode);
        dialog.show();

    }
    else
    { // Google Play Services are available

        // Getting reference to the SupportMapFragment of activity_main.xml
        SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);

        // Getting GoogleMap object from the fragment
        googleMap = fm.getMap();

        // Enabling MyLocation Layer of Google Map
        googleMap.setMyLocationEnabled(true);

        // Getting LocationManager object from System Service LOCATION_SERVICE
        LocationManager locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);

        // Creating a criteria object to retrieve provider
        Criteria criteria = new Criteria();

        // Getting the name of the best provider
        String provider = locationManager.getBestProvider(criteria, true);

        // Getting Current Location
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
        {
            // TODO: Consider calling

            return;
        }
        Location location = locationManager.getLastKnownLocation(provider);

        if(location!=null){
            onLocationChanged(location);
        }
        locationManager.requestLocationUpdates(provider, 100, 0, this);

        btnSetGarageLocation.setOnClickListener(new View.OnClickListener()
        {
            @Override
            public void onClick(View v)
            {
                Intent intent = getIntent();
                intent.putExtra("location_lat",garageLocation.latitude);
                intent.putExtra("location_lng",garageLocation.longitude);
                setResult(RESULT_OK,intent);
                finish();
            }
        });
    }

    googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener()
    {
        @Override
        public void onMapClick(LatLng latLng)
        {
            googleMap.clear();
            googleMap.addMarker(new MarkerOptions().position(latLng).title("Custom location").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
            garageLocation = latLng;
        }
    });


}

@Override
public void onLocationChanged(Location location)
{

    // Getting latitude of the current location
    double latitude = location.getLatitude();

    // Getting longitude of the current location
    double longitude = location.getLongitude();

    // Creating a LatLng object for the current location
    LatLng latLng = new LatLng(latitude, longitude);

    // Showing the current location in Google Map
    googleMap.moveCamera(CameraUpdateFactory.newLatLng(latLng));

    // Zoom in the Google Map
    googleMap.animateCamera(CameraUpdateFactory.zoomTo(15));

    googleMap.getMaxZoomLevel();

    // Setting latitude and longitude in the TextView tv_location

}

@Override
public void onStatusChanged(String provider, int status, Bundle extras)
{

}

@Override
public void onProviderEnabled(String provider)
{

}

@Override
public void onProviderDisabled(String provider)
{

}
}

活动:

private int MAP = 2;

Intent intent = new Intent(getApplicationContext(),InsertMapsActivity.class);
                startActivityForResult(intent, MAP);

活动结束:

@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
    super.onActivityResult(requestCode, resultCode, data);

    ImageView garageImage = new ImageView(this);
    if (resultCode == Activity.RESULT_OK)
    {

    }

    if(requestCode == MAP)
    {
        double lat = (double) data.getExtras().get("location_lat");
        double lng = (double) data.getExtras().get("location_lng");


    }
}

答案 1 :(得分:0)

此代码的作用就像一个超级魅力。但是,随着Google发布新版本,似乎对此有了新的更新。关键区别如下:

  1. OnMapReadyCallback必须实现:

    公共类InsertMapsActivity扩展FragmentActivity实现LocationListener,OnMapReadyCallback

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

    }

  2. 此代码将不再起作用:

    // Getting reference to the SupportMapFragment of activity_main.xml
    SupportMapFragment fm = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map);
    
    // Getting GoogleMap object from the fragment
    googleMap = fm.getMap();
    

请改为使用此方法,它会在#1中调用回调。

    // Obtain the SupportMapFragment and get notified when the map is ready to be used.
    SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager()
            .findFragmentById(R.id.map);
    mapFragment.getMapAsync(this);
  1. 需要将对googleMap对象的引用放在OnMapReady回调中,以确保最初分配了该对象,否则会发生空指针错误:

    @Override 
    public void onMapReady(GoogleMap googleMap) {
            this.googleMap = googleMap;
            // Enabling MyLocation Layer of Google Map
            this.googleMap.setMyLocationEnabled(true);
    googleMap.setOnMapClickListener(new GoogleMap.OnMapClickListener()
    {
        @Override
        public void onMapClick(LatLng latLng)
        {
            googleMap.clear();
            googleMap.addMarker(new MarkerOptions().position(latLng).title("Custom location").icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_BLUE)));
            garageLocation = latLng;
        }
    });
    }