https://fyprojects.com/detail/Android%20Create%20Bottom%20Sheet%20Map%20Like%20Google%20Maps/5
Android How To Create Bottom Sheet Map Like Google Maps
1. Project Structure
Package name : map.bottomsheet.fyprojects.com.bottomsheetmap
2. Gradle
apply plugin: 'com.android.application' android { compileSdkVersion 28 defaultConfig { applicationId "map.bottomsheet.fyprojects.com.bottomsheetmap" minSdkVersion 16 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'com.android.support:appcompat-v7:28.0.0' implementation 'com.android.support.constraint:constraint-layout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation 'com.android.support:design:28.0.0' implementation 'com.android.support:support-v13:28.0.0' implementation 'com.android.support:recyclerview-v7:28.0.0' implementation 'com.github.bumptech.glide:glide:3.7.0' implementation 'com.balysv:material-ripple:1.0.2' implementation 'com.google.android.gms:play-services-maps:16.1.0' }
3. Res Folder Dtructure
activity_main.xml <?xml version="1.0" encoding="utf-8"?> <android.support.design.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="match_parent"> <fragment android:id="@+id/map" android:name="com.google.android.gms.maps.SupportMapFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> <!-- search bar layout --> <include android:id="@+id/search_bar" layout="@layout/include_card_view_search_bar" /> <!--bottom sheet container--> <include layout="@layout/sheet_map" /> <android.support.design.widget.FloatingActionButton android:id="@+id/fab_directions" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_margin="@dimen/spacing_smlarge" android:clickable="true" android:tint="@android:color/white" app:fabSize="normal" app:layout_anchor="@id/bottom_sheet" app:layout_anchorGravity="top|end" app:rippleColor="@android:color/white" app:srcCompat="@drawable/ic_pin_drop" /> </android.support.design.widget.CoordinatorLayout>
include_card_view_search_bar.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true" android:orientation="vertical"> <android.support.v7.widget.CardView android:id="@+id/search_bar" android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/spacing_middle" android:layout_marginLeft="@dimen/spacing_middle" android:layout_marginRight="@dimen/spacing_middle" android:layout_marginTop="@dimen/spacing_large" android:clipToPadding="false" app:cardBackgroundColor="@android:color/white" app:cardCornerRadius="3dp" app:cardElevation="3dp" app:cardUseCompatPadding="false" app:layout_collapseMode="parallax"> <LinearLayout android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="horizontal"> <ImageButton android:id="@+id/bt_menu" android:layout_width="?attr/actionBarSize" android:layout_height="?attr/actionBarSize" android:background="?attr/selectableItemBackgroundBorderless" android:tint="@color/grey_60" app:srcCompat="@drawable/ic_stack_menu" /> <TextView android:id="@+id/search_text" android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:gravity="center_vertical" android:text="Search" android:textAppearance="@style/Base.TextAppearance.AppCompat.Subhead" android:textColor="@color/grey_40" /> <ImageButton android:layout_width="?attr/actionBarSize" android:layout_height="?attr/actionBarSize" android:background="?attr/selectableItemBackgroundBorderless" android:tint="@color/grey_60" app:srcCompat="@drawable/ic_mic" /> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout>
sheet_map.xml <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" android:id="@+id/bottom_sheet" android:layout_width="match_parent" android:layout_height="wrap_content" android:background="@android:color/transparent" android:orientation="vertical" app:behavior_hideable="true" app:behavior_peekHeight="85dp" app:layout_behavior="android.support.design.widget.BottomSheetBehavior"> <android.support.v7.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="5dp" app:cardCornerRadius="1dp" app:cardElevation="20dp"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical"> <View android:layout_width="30dp" android:layout_height="5dp" android:layout_gravity="center" android:layout_marginTop="10dp" android:background="@drawable/swipe_up_handle" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginLeft="@dimen/spacing_xxlarge" android:layout_marginStart="@dimen/spacing_xxlarge" android:gravity="center_vertical" android:minHeight="50dp" android:paddingEnd="@dimen/spacing_large" android:paddingLeft="@dimen/spacing_large" android:paddingRight="@dimen/spacing_large" android:paddingStart="@dimen/spacing_large" android:text="Dandelion Chocolate" android:textAppearance="@style/TextAppearance.AppCompat.Headline" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" android:padding="@dimen/spacing_large"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="@dimen/spacing_middle" android:layout_marginLeft="@dimen/spacing_xxlarge" android:layout_marginStart="@dimen/spacing_xxlarge" android:gravity="center_vertical" android:orientation="horizontal"> <android.support.v7.widget.AppCompatRatingBar style="@style/Yellow.Small.AppCompatRatingBar" android:layout_width="wrap_content" android:layout_height="wrap_content" android:numStars="5" android:rating="3.5" android:stepSize="0.5" android:theme="@style/Yellow.Small.AppCompatRatingBar" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="4.7 (51)" android:textAppearance="@style/TextAppearance.AppCompat.Medium" /> </LinearLayout> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginLeft="@dimen/spacing_xxlarge" android:layout_marginStart="@dimen/spacing_xxlarge" android:background="@color/grey_10" /> <TextView android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:layout_marginLeft="@dimen/spacing_xxlarge" android:layout_marginStart="@dimen/spacing_xxlarge" android:gravity="center_vertical" android:text="12 min away" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textColor="@color/colorPrimary" /> <View android:layout_width="match_parent" android:layout_height="1dp" android:layout_marginLeft="@dimen/spacing_xxlarge" android:layout_marginStart="@dimen/spacing_xxlarge" android:background="@color/grey_10" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_middle" android:orientation="vertical"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <ImageButton android:layout_width="wrap_content" android:layout_height="?attr/actionBarSize" android:background="@android:color/transparent" android:tint="@color/grey_20" app:srcCompat="@drawable/ic_location" /> <View android:layout_width="@dimen/spacing_mxlarge" android:layout_height="0dp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:text="740 Valencia St, San Francisco, CA" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textColor="@color/grey_90" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <ImageButton android:layout_width="wrap_content" android:layout_height="?attr/actionBarSize" android:background="@android:color/transparent" android:tint="@color/grey_20" app:srcCompat="@drawable/ic_phone" /> <View android:layout_width="@dimen/spacing_mxlarge" android:layout_height="0dp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:text="(415) 349-0942" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textColor="@color/grey_90" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:orientation="horizontal"> <ImageButton android:layout_width="wrap_content" android:layout_height="?attr/actionBarSize" android:background="@android:color/transparent" android:tint="@color/grey_20" app:srcCompat="@drawable/ic_schedule" /> <View android:layout_width="@dimen/spacing_mxlarge" android:layout_height="0dp" /> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:gravity="center_vertical" android:text="Wed, 10 AM - 9 PM" android:textAppearance="@style/TextAppearance.AppCompat.Medium" android:textColor="@color/grey_90" /> </LinearLayout> </LinearLayout> </LinearLayout> </LinearLayout> </android.support.v7.widget.CardView> </LinearLayout>
colors.xml <?xml version="1.0" encoding="utf-8"?> <resources> <color name="colorPrimary">#1976D2</color> <color name="colorPrimaryDark">#1565C0</color> <color name="colorPrimaryLight">#1E88E5</color> <color name="colorAccent">#FF4081</color> <color name="colorAccentDark">#F50057</color> <color name="colorAccentLight">#FF80AB</color> <color name="grey_3">#f7f7f7</color> <color name="grey_5">#f2f2f2</color> <color name="grey_10">#e6e6e6</color> <color name="grey_20">#cccccc</color> <color name="grey_40">#999999</color> <color name="grey_60">#666666</color> <color name="grey_80">#37474F</color> <color name="grey_90">#263238</color> <color name="grey_95">#1a1a1a</color> <color name="grey_100_">#0d0d0d</color> <color name="yellow_50">#FFFDE7</color> <color name="yellow_100">#FFF9C4</color> <color name="yellow_200">#FFF59D</color> <color name="yellow_300">#FFF176</color> <color name="yellow_400">#FFEE58</color> <color name="yellow_500">#FFEB3B</color> <color name="yellow_600">#FDD835</color> <color name="yellow_700">#FBC02D</color> <color name="yellow_800">#F9A825</color> <color name="yellow_900">#F57F17</color> <color name="yellow_A100">#FFFF8D</color> <color name="yellow_A200">#FFFF00</color> <color name="yellow_A400">#FFEA00</color> <color name="yellow_A700">#FFD600</color> </resources>
dimen.xml <resources> <!--genaral spacing--> <dimen name="spacing_xsmall">2dp</dimen> <dimen name="spacing_small">3dp</dimen> <dimen name="spacing_medium">5dp</dimen> <dimen name="spacing_xmedium">7dp</dimen> <dimen name="spacing_middle">10dp</dimen> <dimen name="spacing_large">15dp</dimen> <dimen name="spacing_smlarge">18dp</dimen> <dimen name="spacing_mlarge">20dp</dimen> <dimen name="spacing_mxlarge">25dp</dimen> <dimen name="spacing_xlarge">35dp</dimen> <dimen name="spacing_xmlarge">40dp</dimen> <dimen name="spacing_xxlarge">50dp</dimen> <dimen name="spacing_xxxlarge">55dp</dimen> <dimen name="appbar_padding_top">8dp</dimen> </resources>
strings.xml <resources> <string name="app_name">BottomSheetMap</string> <string name="bottom_sheet_behavior" translatable="false">android.support.design.widget.BottomSheetBehavior</string> <string name="google_maps_key" templateMergeStrategy="preserve" translatable="false"> AIzaSyC3SrcUtXXXXXXXXXXXXXXXXXXXXXX </string> </resources>
styles.xml <resources> <!-- Base application theme. --> <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar"> <!-- Customize your theme here. --> <item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorAccent">@color/colorAccent</item> </style> <!--style for ripple library--> <style name="RippleStyleWhite"> <item name="mrl_rippleOverlay">true</item> <item name="mrl_rippleColor">#80FFFFFF</item> <item name="mrl_rippleHover">true</item> <item name="mrl_rippleAlpha">0.2</item> </style> <style name="RippleStyleBlack" parent="RippleStyleWhite"> <item name="mrl_rippleColor">#8096989A</item> </style> <style name="Button.Primary" parent="@style/Widget.AppCompat.Button.Colored"> <item name="colorButtonNormal">@color/colorPrimary</item> <item name="android:textColor">@android:color/white</item> </style> <style name="Yellow.Small.AppCompatRatingBar" parent="Base.Widget.AppCompat.RatingBar.Small"> <item name="colorControlNormal">@color/grey_60</item> <item name="colorControlActivated">@color/yellow_600</item> </style> </resources>
4. Utils
Tools package map.bottomsheet.fyprojects.com.bottomsheetmap.utils; import android.app.Activity; import android.content.Context; import android.graphics.Bitmap; import android.os.Build; import android.support.annotation.DrawableRes; import android.support.v4.graphics.drawable.RoundedBitmapDrawable; import android.support.v4.graphics.drawable.RoundedBitmapDrawableFactory; import android.view.Window; import android.view.WindowManager; import android.widget.ImageView; import com.bumptech.glide.Glide; import com.bumptech.glide.request.target.BitmapImageViewTarget; import com.google.android.gms.maps.GoogleMap; import map.bottomsheet.fyprojects.com.bottomsheetmap.R; public class Tools { public static GoogleMap configActivityMaps(GoogleMap googleMap) { // set map type googleMap.setMapType(GoogleMap.MAP_TYPE_NORMAL); // Enable / Disable zooming controls googleMap.getUiSettings().setZoomControlsEnabled(false); // Enable / Disable Compass icon googleMap.getUiSettings().setCompassEnabled(true); // Enable / Disable Rotate gesture googleMap.getUiSettings().setRotateGesturesEnabled(true); // Enable / Disable zooming functionality googleMap.getUiSettings().setZoomGesturesEnabled(true); googleMap.getUiSettings().setScrollGesturesEnabled(true); googleMap.getUiSettings().setMapToolbarEnabled(true); return googleMap; } }
5. Activity
MainActivity package map.bottomsheet.fyprojects.com.bottomsheetmap; import android.content.DialogInterface; import android.os.Build; import android.support.annotation.NonNull; import android.support.design.widget.BottomSheetBehavior; import android.support.design.widget.BottomSheetDialog; import android.support.design.widget.FloatingActionButton; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.WindowManager; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import com.google.android.gms.maps.CameraUpdate; import com.google.android.gms.maps.CameraUpdateFactory; import com.google.android.gms.maps.GoogleMap; import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.SupportMapFragment; import com.google.android.gms.maps.model.LatLng; import com.google.android.gms.maps.model.Marker; import com.google.android.gms.maps.model.MarkerOptions; import map.bottomsheet.fyprojects.com.bottomsheetmap.utils.Tools; public class MainActivity extends AppCompatActivity { private GoogleMap mMap; private BottomSheetBehavior bottomSheetBehavior; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initMapFragment(); initComponent(); Toast.makeText(this, "Swipe up bottom sheet", Toast.LENGTH_SHORT).show(); } private void initComponent() { // get the bottom sheet view LinearLayout llBottomSheet = (LinearLayout) findViewById(R.id.bottom_sheet); // init the bottom sheet behavior bottomSheetBehavior = BottomSheetBehavior.from(llBottomSheet); // change the state of the bottom sheet bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); // set callback for changes bottomSheetBehavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() { @Override public void onStateChanged(@NonNull View bottomSheet, int newState) { } @Override public void onSlide(@NonNull View bottomSheet, float slideOffset) { } }); ((FloatingActionButton) findViewById(R.id.fab_directions)).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); try { mMap.animateCamera(zoomingLocation()); } catch (Exception e) { } } }); } private void initMapFragment() { SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); mapFragment.getMapAsync(new OnMapReadyCallback() { @Override public void onMapReady(GoogleMap googleMap) { mMap = Tools.configActivityMaps(googleMap); MarkerOptions markerOptions = new MarkerOptions().position(new LatLng(37.7610237, -122.4217785)); mMap.addMarker(markerOptions); mMap.moveCamera(zoomingLocation()); mMap.setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() { @Override public boolean onMarkerClick(Marker marker) { bottomSheetBehavior.setState(BottomSheetBehavior.STATE_COLLAPSED); try { mMap.animateCamera(zoomingLocation()); } catch (Exception e) { } return true; } }); } }); } private CameraUpdate zoomingLocation() { return CameraUpdateFactory.newLatLngZoom(new LatLng(37.76496792, -122.42206407), 13); } }
6.Manifest
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="map.bottomsheet.fyprojects.com.bottomsheetmap"> <application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <!-- Add Google Map Library --> <uses-library android:name="com.google.android.maps" /> <!-- Google API Key --> <meta-data android:name="com.google.android.geo.API_KEY" android:value="@string/google_maps_key" /> <activity android:name="map.bottomsheet.fyprojects.com.bottomsheetmap.MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
Nhận xét
Đăng nhận xét