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 .