Navigation Google Maps Material Design

0

Does anyone know reference material to develop an Android app similar to the new Google Maps animation and navigation format?

The idea is to position the Marker InfoWindow in the lower region of the screen. And as soon as the user touches, or swipe up, this displays the full details of the location.

I did not find anything specific in the Google Developer documentation. Any ideas?

Thanks for the help!

    
asked by anonymous 04.04.2015 / 22:47

1 answer

2

I think you're looking for AndroidSlidingUpPanel , it's a library that provides Widget with functionality you are looking for.

Integrating with Google Maps is simple, in my example I accessed Google Places API for Android. Where I searched for places and created Markers , synchronized with SlidingUpPanelLayout .

My layout is:

<?xml version="1.0" encoding="utf-8"?>
<com.sothree.slidinguppanel.SlidingUpPanelLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:sothree="http://schemas.android.com/apk/res-auto"
    android:id="@+id/sliding_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="bottom"
    sothree:umanoPanelHeight="72dp"
    sothree:umanoShadowHeight="4dp"
    sothree:umanoAnchorPoint="0.5"
    tools:context=".MapsActivity">

    <fragment
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/map"
        android:name="com.google.android.gms.maps.SupportMapFragment" />

    <include layout="@layout/sliding_panel" />
</com.sothree.slidinguppanel.SlidingUpPanelLayout>

My activity has been:

public class MapsActivity extends FragmentActivity implements GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener, ViewPager.OnPageChangeListener,
    PlacesListAdapter.ListCallback, GoogleMap.OnMarkerClickListener {

    private GoogleMap mMap; // Might be null if Google Play services APK is not available.
    private GoogleApiClient mGoogleApiClient;

    private RecyclerView mRecyclerView;
    private ViewPager mPager;

    private PlacesListAdapter mAdapter;
    private PlacesPagerAdater mPagerAdapter;
    private PlacesInfoWindowAdapter mInfoWindowAdapter;

    private List<PlaceLikelihood> mPlaces;
    private List<Marker> mMarkers;

    private GoogleMap.OnMyLocationChangeListener mListener = new GoogleMap.OnMyLocationChangeListener(){
        @Override
        public void onMyLocationChange(Location location) {
            moveToLocationOneShot(location);
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.activity_maps);
        setUpMapIfNeeded();

        mGoogleApiClient = new GoogleApiClient.Builder(this)
                .addApi(Places.GEO_DATA_API)
                .addApi(Places.PLACE_DETECTION_API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        configureViewPager();
        configureRecyclerView();
        queryForNearbyPlaces();
    }

    @Override
    protected void onResume() {
        super.onResume();
        setUpMapIfNeeded();

        mGoogleApiClient.connect();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mGoogleApiClient.disconnect();
    }

    private void setUpMapIfNeeded() {
        // Do a null check to confirm that we have not already instantiated the map.
        if (mMap == null) {
            // Try to obtain the map from the SupportMapFragment.
            mMap = ((SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map)).getMap();
            // Check if we were successful in obtaining the map.
            if (mMap != null) {
                setUpMap();
            }
        }
    }

    private void configureViewPager() {
        mPager = (ViewPager) findViewById(R.id.view_pager);
        mPager.setAdapter(mPagerAdapter = new PlacesPagerAdater(this));

        mPager.setOnPageChangeListener(this);
    }

    private void configureRecyclerView() {
        mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        mRecyclerView.setAdapter(mAdapter = new PlacesListAdapter(this).setListCallback(this));
        mRecyclerView.setHasFixedSize(true);
    }

    private void queryForNearbyPlaces() {
        PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi.getCurrentPlace(mGoogleApiClient, null);

        result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() {
            @Override
            public void onResult(PlaceLikelihoodBuffer likelyPlaces) {
                mPlaces = new ArrayList<>(likelyPlaces.getCount());
                mMarkers = new ArrayList<>(likelyPlaces.getCount());
                mInfoWindowAdapter = new PlacesInfoWindowAdapter(MapsActivity.this);

                int i = 0;

                for (PlaceLikelihood placeLikelihood : likelyPlaces) {
                    mPlaces.add(placeLikelihood.freeze());
                    mMarkers.add(mMap.addMarker(buildMarkerForPlace(placeLikelihood.getPlace(), i++)));
                }

                mAdapter.setData(mPlaces);
                mPagerAdapter.setData(mPlaces);
                mInfoWindowAdapter.setData(mPlaces);

                likelyPlaces.release();

                mMap.setInfoWindowAdapter(mInfoWindowAdapter);
            }
        });
    }

    MarkerOptions buildMarkerForPlace(Place place, int position) {
        MarkerOptions mo = new MarkerOptions();

        mo.position(place.getLatLng());
        mo.title(place.getName().toString());
        mo.snippet(Integer.toString(position));

        return mo;
    }

    private void setUpMap() {
        mMap.setMyLocationEnabled(true);
        mMap.setBuildingsEnabled(true);
        mMap.setOnMyLocationChangeListener(mListener);
        mMap.setInfoWindowAdapter(mInfoWindowAdapter);
        mMap.setOnMarkerClickListener(this);
    }

    private void moveToLocationOneShot(Location location) {
        moveToLocation(location);
        mMap.setOnMyLocationChangeListener(null);
    }

    private void moveToLocation(Location location) {
        moveToLocation(getLatLng(location));
    }

    private void moveToLocation(LatLng latLng) {
        mMap.animateCamera(CameraUpdateFactory.newCameraPosition(new CameraPosition(latLng, 16f, 0f, 0f)));
    }

    private LatLng getLatLng(Location loc) {
        return new LatLng(loc.getLatitude(), loc.getLongitude());
    }

    @Override
    public void onConnected(Bundle bundle) {
        Log.d("TAG", "onConnected");
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d("TAG", "onConnectionSuspended");
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d("TAG", "onConnectionFailed");
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

    @Override
    public void onPageSelected(int position) {
        mRecyclerView.smoothScrollToPosition(position);
        showMarker(mMarkers.get(position));
    }

    void showMarker(Marker marker) {
        moveToLocation(marker.getPosition());
        marker.showInfoWindow();
    }

    @Override
    public void onPageScrollStateChanged(int state) {}

    @Override
    public void onItemSelected(View item) {
        int position = mRecyclerView.getChildLayoutPosition(item);

        mPager.setCurrentItem(position, true);
        showMarker(mMarkers.get(position));
    }

    @Override
    public boolean onMarkerClick(Marker marker) {
        int position = mMarkers.indexOf(marker);

        mPager.setCurrentItem(position, true);
        mRecyclerView.smoothScrollToPosition(position);

        return false;
    }
}

And not forgetting the dependencies:

repositories {
    mavenCentral()
}

compile 'com.android.support:support-v4:22.0.0'
compile 'com.android.support:appcompat-v7:22.0.0'

compile 'com.google.android.gms:play-services-maps:7.0.0'
compile 'com.google.android.gms:play-services-location:7.0.0'
compile 'com.android.support:recyclerview-v7:22.0.0'

compile 'com.sothree.slidinguppanel:library:3.0.0'

Of course, some details are missing, but you have a good code to get started.

Other artifacts, such as% w_that were used, are in code repository .

    
20.04.2015 / 01:54