Android 1?
Android
Android
Notes for Professionals Android™
Notes for Professionals
1000+ pages
of professional hints and tricks
Contents
About ................................................................................................................................................................................... 1
Chapter 1: Getting started with Android ........................................................................................................... 2
Section 1.1: Creating a New Project .............................................................................................................................. 2
Section 1.2: Setting up Android Studio ....................................................................................................................... 13
Section 1.3: Android programming without an IDE .................................................................................................. 14
Section 1.4: Application Fundamentals ...................................................................................................................... 18
Section 1.5: Setting up an AVD (Android Virtual Device) ......................................................................................... 19
Chapter 2: Android Studio ...................................................................................................................................... 23
Section 2.1: Setup Android Studio .............................................................................................................................. 23
Section 2.2: View And Add Shortcuts in Android Studio .......................................................................................... 23
Section 2.3: Android Studio useful shortcuts ............................................................................................................ 24
Section 2.4: Android Studio Improve performance tip ............................................................................................ 25
Section 2.5: Gradle build project takes forever ........................................................................................................ 26
Section 2.6: Enable/Disable blank line copy ............................................................................................................ 26
Section 2.7: Custom colors of logcat message based on message importance ................................................. 27
Section 2.8: Filter logs from UI ................................................................................................................................... 28
Section 2.9: Create filters configuration ................................................................................................................... 29
Section 2.10: Create assets folder .............................................................................................................................. 30
Chapter 3: Instant Run in Android Studio ....................................................................................................... 32
Section 3.1: Enabling or disabling Instant Run .......................................................................................................... 32
Section 3.2: Types of code Swaps in Instant Run .................................................................................................... 32
Section 3.3: Unsupported code changes when using Instant Run ......................................................................... 33
Chapter 4: TextView ................................................................................................................................................. 34
Section 4.1: Spannable TextView ................................................................................................................................ 34
Section 4.2: Strikethrough TextView .......................................................................................................................... 35
Section 4.3: TextView with image .............................................................................................................................. 36
Section 4.4: Make RelativeSizeSpan align to top ..................................................................................................... 36
Section 4.5: Pinchzoom on TextView ......................................................................................................................... 38
Section 4.6: Textview with dierent Textsize ............................................................................................................ 39
Section 4.7: Theme and Style customization ............................................................................................................ 39
Section 4.8: TextView customization ......................................................................................................................... 41
Section 4.9: Single TextView with two dierent colors ............................................................................................ 44
Chapter 5: AutoCompleteTextView ................................................................................................................... 46
Section 5.1: AutoComplete with CustomAdapter, ClickListener and Filter ............................................................. 46
Section 5.2: Simple, hard-coded AutoCompleteTextView ....................................................................................... 49
Chapter 6: Autosizing TextViews ......................................................................................................................... 50
Section 6.1: Granularity ............................................................................................................................................... 50
Section 6.2: Preset Sizes ............................................................................................................................................. 50
Chapter 7: ListView .................................................................................................................................................... 52
Section 7.1: Custom ArrayAdapter ............................................................................................................................. 52
Section 7.2: A basic ListView with an ArrayAdapter ................................................................................................ 53
Section 7.3: Filtering with CursorAdapter .................................................................................................................. 53
Chapter 8: Layouts .................................................................................................................................................... 55
Section 8.1: LayoutParams ......................................................................................................................................... 55
Section 8.2: Gravity and layout gravity .................................................................................................................... 58
Section 8.3: CoordinatorLayout Scrolling Behavior ................................................................................................. 60
Section 8.4: Percent Layouts ...................................................................................................................................... 62
Section 8.5: View Weight ............................................................................................................................................ 63
Section 8.6: Creating LinearLayout programmatically ........................................................................................... 64
Section 8.7: LinearLayout ........................................................................................................................................... 65
Section 8.8: RelativeLayout ........................................................................................................................................ 66
Section 8.9: FrameLayout .......................................................................................................................................... 68
Section 8.10: GridLayout ............................................................................................................................................. 69
Section 8.11: CoordinatorLayout ................................................................................................................................. 71
Chapter 9: ConstraintLayout ................................................................................................................................ 73
Section 9.1: Adding ConstraintLayout to your project ............................................................................................. 73
Section 9.2: Chains ...................................................................................................................................................... 74
Chapter 10: TextInputLayout ................................................................................................................................ 75
Section 10.1: Basic usage ............................................................................................................................................ 75
Section 10.2: Password Visibility Toggles .................................................................................................................. 75
Section 10.3: Adding Character Counting ................................................................................................................. 75
Section 10.4: Handling Errors ..................................................................................................................................... 76
Section 10.5: Customizing the appearance of the TextInputLayout ...................................................................... 76
Section 10.6: TextInputEditText .................................................................................................................................. 77
Chapter 11: CoordinatorLayout and Behaviors ........................................................................................... 79
Section 11.1: Creating a simple Behavior ................................................................................................................... 79
Section 11.2: Using the SwipeDismissBehavior .......................................................................................................... 80
Section 11.3: Create dependencies between Views .................................................................................................. 80
Chapter 12: TabLayout ............................................................................................................................................. 82
Section 12.1: Using a TabLayout without a ViewPager ............................................................................................ 82
Chapter 13: ViewPager ............................................................................................................................................. 83
Section 13.1: ViewPager with a dots indicator ........................................................................................................... 83
Section 13.2: Basic ViewPager usage with fragments ............................................................................................. 85
Section 13.3: ViewPager with PreferenceFragment ................................................................................................. 86
Section 13.4: Adding a ViewPager .............................................................................................................................. 87
Section 13.5: Setup OnPageChangeListener ............................................................................................................. 88
Section 13.6: ViewPager with TabLayout .................................................................................................................. 89
Chapter 14: CardView ............................................................................................................................................... 92
Section 14.1: Getting Started with CardView ............................................................................................................. 92
Section 14.2: Adding Ripple animation ...................................................................................................................... 93
Section 14.3: Customizing the CardView ................................................................................................................... 93
Section 14.4: Using Images as Background in CardView (Pre-Lollipop device issues) ........................................ 94
Section 14.5: Animate CardView background color with TransitionDrawable ...................................................... 96
Chapter 15: NavigationView .................................................................................................................................. 97
Section 15.1: How to add the NavigationView ........................................................................................................... 97
Section 15.2: Add underline in menu elements ....................................................................................................... 101
Section 15.3: Add seperators to menu ..................................................................................................................... 102
Section 15.4: Add menu Divider using default DividerItemDecoration ................................................................ 103
Chapter 16: RecyclerView ..................................................................................................................................... 105
Section 16.1: Adding a RecyclerView ........................................................................................................................ 105
Section 16.2: Smoother loading of items ................................................................................................................. 106
Section 16.3: RecyclerView with DataBinding ......................................................................................................... 107
Section 16.4: Animate data change ......................................................................................................................... 108
Section 16.5: Popup menu with recyclerView ......................................................................................................... 112
Section 16.6: Using several ViewHolders with ItemViewType ............................................................................... 114
Section 16.7: Filter items inside RecyclerView with a SearchView ........................................................................ 115
Section 16.8: Drag&Drop and Swipe with RecyclerView ....................................................................................... 116
Section 16.9: Show default view till items load or when data is not available .................................................... 117
Section 16.10: Add header/footer to a RecyclerView ............................................................................................ 119
Section 16.11: Endless Scrolling in Recycleview ....................................................................................................... 122
Section 16.12: Add divider lines to RecyclerView items .......................................................................................... 122
Chapter 17: RecyclerView Decorations ......................................................................................................... 125
Section 17.1: Add divider to RecyclerView ............................................................................................................... 125
Section 17.2: Drawing a Separator .......................................................................................................................... 127
Section 17.3: How to add dividers using and DividerItemDecoration .................................................................. 128
Section 17.4: Per-item margins with ItemDecoration ............................................................................................. 128
Section 17.5: ItemOsetDecoration for GridLayoutManager in RecycleView .................................................... 129
Chapter 18: RecyclerView onClickListeners ................................................................................................. 131
Section 18.1: Kotlin and RxJava example ................................................................................................................ 131
Section 18.2: RecyclerView Click listener ................................................................................................................. 132
Section 18.3: Another way to implement Item Click Listener ................................................................................ 133
Section 18.4: New Example ....................................................................................................................................... 135
Section 18.5: Easy OnLongClick and OnClick Example .......................................................................................... 136
Section 18.6: Item Click Listeners ............................................................................................................................. 139
Chapter 19: RecyclerView and LayoutManagers ..................................................................................... 141
Section 19.1: Adding header view to recyclerview with gridlayout manager ...................................................... 141
Section 19.2: GridLayoutManager with dynamic span count ............................................................................... 142
Section 19.3: Simple list with LinearLayoutManager .............................................................................................. 144
Section 19.4: StaggeredGridLayoutManager ......................................................................................................... 148
Chapter 20: Pagination in RecyclerView ...................................................................................................... 151
Section 20.1: MainActivity.java ................................................................................................................................. 151
Chapter 21: ImageView .......................................................................................................................................... 156
Section 21.1: Set tint ................................................................................................................................................... 156
Section 21.2: Set alpha .............................................................................................................................................. 157
Section 21.3: Set Scale Type ..................................................................................................................................... 157
Section 21.4: ImageView ScaleType - Center ......................................................................................................... 162
Section 21.5: ImageView ScaleType - CenterCrop ................................................................................................. 164
Section 21.6: ImageView ScaleType - CenterInside ............................................................................................... 166
Section 21.7: ImageView ScaleType - FitStart and FitEnd ..................................................................................... 168
Section 21.8: ImageView ScaleType - FitCenter ..................................................................................................... 172
Section 21.9: Set Image Resource ............................................................................................................................ 174
Section 21.10: ImageView ScaleType - FitXy ........................................................................................................... 175
Section 21.11: MLRoundedImageView.java .............................................................................................................. 177
Chapter 22: VideoView ........................................................................................................................................... 180
Section 22.1: Play video from URL with using VideoView ..................................................................................... 180
Section 22.2: VideoView Create ............................................................................................................................... 180
Chapter 23: Optimized VideoView .................................................................................................................... 181
Section 23.1: Optimized VideoView in ListView ....................................................................................................... 181
Chapter 24: WebView ............................................................................................................................................. 193
Section 24.1: Troubleshooting WebView by printing console messages or by remote debugging ................. 193
Section 24.2: Communication from Javascript to Java (Android) ...................................................................... 194
Section 24.3: Communication from Java to Javascript ........................................................................................ 195
Section 24.4: Open dialer example .......................................................................................................................... 195
Section 24.5: Open Local File / Create dynamic content in Webview ................................................................ 196
Section 24.6: JavaScript alert dialogs in WebView - How to make them work ................................................. 196
Chapter 25: SearchView ........................................................................................................................................ 198
Section 25.1: Setting Theme for SearchView .......................................................................................................... 198
Section 25.2: SearchView in Toolbar with Fragment ............................................................................................. 198
Section 25.3: Appcompat SearchView with RxBindings watcher ......................................................................... 200
Chapter 26: BottomNavigationView ............................................................................................................... 203
Section 26.1: Basic implemetation ........................................................................................................................... 203
Section 26.2: Customization of BottomNavigationView ....................................................................................... 204
Section 26.3: Handling Enabled / Disabled states ................................................................................................. 204
Section 26.4: Allowing more than 3 menus ............................................................................................................ 205
Chapter 27: Canvas drawing using SurfaceView ..................................................................................... 207
Section 27.1: SurfaceView with drawing thread ..................................................................................................... 207
Chapter 28: Creating Custom Views ............................................................................................................... 212
Section 28.1: Creating Custom Views ...................................................................................................................... 212
Section 28.2: Adding attributes to views ................................................................................................................. 214
Section 28.3: CustomView performance tips ......................................................................................................... 216
Section 28.4: Creating a compound view ............................................................................................................... 217
Section 28.5: Compound view for SVG/VectorDrawable as drawableRight ...................................................... 220
Section 28.6: Responding to Touch Events ............................................................................................................ 223
Chapter 29: Getting Calculated View Dimensions .................................................................................... 224
Section 29.1: Calculating initial View dimensions in an Activity ............................................................................ 224
Chapter 30: Adding a FuseView to an Android Project ......................................................................... 225
Section 30.1: hikr app, just another android.view.View .......................................................................................... 225
Chapter 31: Supporting Screens With Dierent Resolutions, Sizes ................................................ 232
Section 31.1: Using configuration qualifiers ............................................................................................................. 232
Section 31.2: Converting dp and sp to pixels .......................................................................................................... 232
Section 31.3: Text size and dierent android screen sizes .................................................................................... 233
Chapter 32: ViewFlipper ........................................................................................................................................ 234
Section 32.1: ViewFlipper with image sliding .......................................................................................................... 234
Chapter 33: Design Patterns ............................................................................................................................... 235
Section 33.1: Observer pattern ................................................................................................................................. 235
Section 33.2: Singleton Class Example .................................................................................................................... 235
Chapter 34: Activity ................................................................................................................................................ 237
Section 34.1: Activity launchMode ............................................................................................................................ 237
Section 34.2: Exclude an activity from back-stack history ................................................................................... 238
Section 34.3: Android Activity LifeCycle Explained ................................................................................................ 238
Section 34.4: End Application with exclude from Recents .................................................................................... 241
Section 34.5: Presenting UI with setContentView ................................................................................................... 242
Section 34.6: Up Navigation for Activities ............................................................................................................... 243
Section 34.7: Clear your current Activity stack and launch a new Activity ......................................................... 244
Chapter 35: Activity Recognition ...................................................................................................................... 246
Section 35.1: Google Play ActivityRecognitionAPI .................................................................................................. 246
Section 35.2: PathSense Activity Recognition ........................................................................................................ 248
Chapter 36: Split Screen / Multi-Screen Activities ................................................................................... 250
Section 36.1: Split Screen introduced in Android Nougat implemented .............................................................. 250
Chapter 37: Material Design ............................................................................................................................... 251
Section 37.1: Adding a Toolbar ................................................................................................................................. 251
Section 37.2: Buttons styled with Material Design ................................................................................................. 252
Section 37.3: Adding a FloatingActionButton (FAB) .............................................................................................. 253
Section 37.4: RippleDrawable .................................................................................................................................. 254
Section 37.5: Adding a TabLayout ........................................................................................................................... 259
Section 37.6: Bottom Sheets in Design Support Library ........................................................................................ 261
Section 37.7: Apply an AppCompat theme ............................................................................................................. 264
Section 37.8: Add a Snackbar .................................................................................................................................. 265
Section 37.9: Add a Navigation Drawer .................................................................................................................. 266
Section 37.10: How to use TextInputLayout ............................................................................................................ 269
Chapter 38: Resources ........................................................................................................................................... 270
Section 38.1: Define colors ........................................................................................................................................ 270
Section 38.2: Color Transparency(Alpha) Level .................................................................................................... 271
Section 38.3: Define String Plurals ........................................................................................................................... 271
Section 38.4: Define strings ...................................................................................................................................... 272
Section 38.5: Define dimensions .............................................................................................................................. 273
Section 38.6: String formatting in strings.xml ......................................................................................................... 273
Section 38.7: Define integer array ........................................................................................................................... 274
Section 38.8: Define a color state list ...................................................................................................................... 274
Section 38.9: 9 Patches ............................................................................................................................................. 275
Section 38.10: Getting resources without "deprecated" warnings ....................................................................... 278
Section 38.11: Working with strings.xml file ............................................................................................................. 278
Section 38.12: Define string array ............................................................................................................................ 279
Section 38.13: Define integers .................................................................................................................................. 280
Section 38.14: Define a menu resource and use it inside Activity/Fragment ..................................................... 280
Chapter 39: Data Binding Library .................................................................................................................... 282
Section 39.1: Basic text field binding ........................................................................................................................ 282
Section 39.2: Built-in two-way Data Binding .......................................................................................................... 283
Section 39.3: Custom event using lambda expression .......................................................................................... 284
Section 39.4: Default value in Data Binding ........................................................................................................... 286
Section 39.5: Databinding in Dialog ........................................................................................................................ 286
Section 39.6: Binding with an accessor method .................................................................................................... 286
Section 39.7: Pass widget as reference in BindingAdapter .................................................................................. 287
Section 39.8: Click listener with Binding .................................................................................................................. 288
Section 39.9: Data binding in RecyclerView Adapter ............................................................................................ 289
Section 39.10: Databinding in Fragment ................................................................................................................. 290
Section 39.11: DataBinding with custom variables(int,boolean) ........................................................................... 291
Section 39.12: Referencing classes .......................................................................................................................... 291
Chapter 40: SharedPreferences ....................................................................................................................... 293
Section 40.1: Implementing a Settings screen using SharedPreferences ............................................................ 293
Section 40.2: Commit vs. Apply ............................................................................................................................... 295
Section 40.3: Read and write values to SharedPreferences ................................................................................. 295
Section 40.4: Retrieve all stored entries from a particular SharedPreferences file ........................................... 296
Section 40.5: Reading and writing data to SharedPreferences with Singleton .................................................. 297
Section 40.6: getPreferences(int) VS getSharedPreferences(String, int) ............................................................ 301
Section 40.7: Listening for SharedPreferences changes ...................................................................................... 301
Section 40.8: Store, Retrieve, Remove and Clear Data from SharedPreferences ............................................. 302
Section 40.9: Add filter for EditTextPreference ...................................................................................................... 302
Section 40.10: Supported data types in SharedPreferences ................................................................................ 303
Section 40.11: Dierent ways of instantiating an object of SharedPreferences ................................................. 303
Section 40.12: Removing keys .................................................................................................................................. 304
Section 40.13: Support pre-Honeycomb with StringSet ........................................................................................ 304
Chapter 41: Intent .................................................................................................................................................... 306
Section 41.1: Getting a result from another Activity ............................................................................................... 306
Section 41.2: Passing data between activities ........................................................................................................ 308
Section 41.3: Open a URL in a browser ................................................................................................................... 309
Section 41.4: Starter Pattern ..................................................................................................................................... 310
Section 41.5: Clearing an activity stack ................................................................................................................... 311
Section 41.6: Start an activity ................................................................................................................................... 311
Section 41.7: Sending emails .................................................................................................................................... 312
Section 41.8: CustomTabsIntent for Chrome Custom Tabs .................................................................................. 312
Section 41.9: Intent URI ............................................................................................................................................. 313
Section 41.10: Start the dialer ................................................................................................................................... 314
Section 41.11: Broadcasting Messages to Other Components .............................................................................. 314
Section 41.12: Passing custom object between activities ...................................................................................... 315
Section 41.13: Open Google map with specified latitude, longitude ..................................................................... 317
Section 41.14: Passing dierent data through Intent in Activity ............................................................................ 317
Section 41.15: Share intent ........................................................................................................................................ 319
Section 41.16: Showing a File Chooser and Reading the Result ............................................................................ 319
Section 41.17: Sharing Multiple Files through Intent ............................................................................................... 321
Section 41.18: Start Unbound Service using an Intent ............................................................................................ 321
Section 41.19: Getting a result from Activity to Fragment ..................................................................................... 322
Chapter 42: Fragments ......................................................................................................................................... 324
Section 42.1: Pass data from Activity to Fragment using Bundle ........................................................................ 324
Section 42.2: The newInstance() pattern ................................................................................................................ 324
Section 42.3: Navigation between fragments using backstack and static fabric pattern ................................ 325
Section 42.4: Sending events back to an activity with callback interface .......................................................... 326
Section 42.5: Animate the transition between fragments .................................................................................... 327
Section 42.6: Communication between Fragments ............................................................................................... 328
Chapter 43: Button .................................................................................................................................................. 333
Section 43.1: Using the same click event for one or more Views in the XML ...................................................... 333
Section 43.2: Defining external Listener .................................................................................................................. 333
Section 43.3: inline onClickListener .......................................................................................................................... 334
Section 43.4: Customizing Button style ................................................................................................................... 334
Section 43.5: Custom Click Listener to prevent multiple fast clicks ..................................................................... 338
Section 43.6: Using the layout to define a click action .......................................................................................... 338
Section 43.7: Listening to the long click events ...................................................................................................... 339
Chapter 44: Emulator ............................................................................................................................................ 340
Section 44.1: Taking screenshots ............................................................................................................................. 340
Section 44.2: Simulate call ........................................................................................................................................ 345
Section 44.3: Open the AVD Manager .................................................................................................................... 345
Section 44.4: Resolving Errors while starting emulator ........................................................................................ 345
Chapter 45: Service ................................................................................................................................................. 347
Section 45.1: Lifecycle of a Service .......................................................................................................................... 347
Section 45.2: Defining the process of a service ..................................................................................................... 348
Section 45.3: Creating an unbound service ............................................................................................................ 348
Section 45.4: Starting a Service ............................................................................................................................... 351
Section 45.5: Creating Bound Service with help of Binder .................................................................................... 351
Section 45.6: Creating Remote Service (via AIDL) ................................................................................................. 352
Chapter 46: The Manifest File ............................................................................................................................ 354
Section 46.1: Declaring Components ....................................................................................................................... 354
Section 46.2: Declaring permissions in your manifest file .................................................................................... 354
Chapter 47: Gradle for Android ........................................................................................................................ 356
Section 47.1: A basic build.gradle file ....................................................................................................................... 356
Section 47.2: Define and use Build Configuration Fields ....................................................................................... 358
Section 47.3: Centralizing dependencies via "dependencies.gradle" file ............................................................ 361
Section 47.4: Sign APK without exposing keystore password .............................................................................. 362
Section 47.5: Adding product flavor-specific dependencies ................................................................................ 364
Section 47.6: Specifying dierent application IDs for build types and product flavors .................................... 364
Section 47.7: Versioning your builds via "version.properties" file ......................................................................... 365
Section 47.8: Defining product flavors .................................................................................................................... 366
Section 47.9: Changing output apk name and add version name: ..................................................................... 366
Section 47.10: Adding product flavor-specific resources ...................................................................................... 367
Section 47.11: Why are there two build.gradle files in an Android Studio project? ............................................. 367
Section 47.12: Directory structure for flavor-specific resources .......................................................................... 368
Section 47.13: Enable Proguard using gradle ......................................................................................................... 368
Section 47.14: Ignoring build variant ....................................................................................................................... 369
Section 47.15: Enable experimental NDK plugin support for Gradle and AndroidStudio .................................. 369
Section 47.16: Display signing information ............................................................................................................. 371
Section 47.17: Seeing dependency tree ................................................................................................................... 372
Section 47.18: Disable image compression for a smaller APK file size ................................................................ 373
Section 47.19: Delete "unaligned" apk automatically ............................................................................................ 373
Section 47.20: Executing a shell script from gradle ............................................................................................... 373
Section 47.21: Show all gradle project tasks ........................................................................................................... 374
Section 47.22: Debugging your Gradle errors ....................................................................................................... 375
Section 47.23: Use gradle.properties for central versionnumber/buildconfigurations ..................................... 376
Section 47.24: Defining build types ......................................................................................................................... 377
Chapter 48: FileIO with Android ........................................................................................................................ 378
Section 48.1: Obtaining the working folder ............................................................................................................. 378
Section 48.2: Writing raw array of bytes ................................................................................................................ 378
Section 48.3: Serializing the object .......................................................................................................................... 378
Section 48.4: Writing to external storage (SD card) .............................................................................................. 379
Section 48.5: Solving "Invisible MTP files" problem ............................................................................................... 379
Section 48.6: Working with big files ......................................................................................................................... 379
Chapter 49: FileProvider ....................................................................................................................................... 381
Section 49.1: Sharing a file ........................................................................................................................................ 381
Chapter 50: Storing Files in Internal & External Storage .................................................................... 383
Section 50.1: Android: Internal and External Storage - Terminology Clarification ............................................. 383
Section 50.2: Using External Storage ...................................................................................................................... 387
Section 50.3: Using Internal Storage ....................................................................................................................... 388
Section 50.4: Fetch Device Directory : .................................................................................................................... 388
Section 50.5: Save Database on SD Card (Backup DB on SD) ............................................................................ 390
Chapter 51: Zip file in android ............................................................................................................................ 392
Section 51.1: Zip file on android ................................................................................................................................ 392
Chapter 52: Unzip File in Android ..................................................................................................................... 393
Section 52.1: Unzip file ............................................................................................................................................... 393
Chapter 53: Camera and Gallery ...................................................................................................................... 394
Section 53.1: Take photo ........................................................................................................................................... 394
Section 53.2: Taking full-sized photo from camera .............................................................................................. 396
Section 53.3: Decode bitmap correctly rotated from the uri fetched with the intent ........................................ 399
Section 53.4: Set camera resolution ........................................................................................................................ 401
Section 53.5: How to start camera or gallery and save camera result to storage ........................................... 401
Chapter 54: Camera 2 API ................................................................................................................................... 405
Section 54.1: Preview the main camera in a TextureView ..................................................................................... 405
Chapter 55: Fingerprint API in android .......................................................................................................... 414
Section 55.1: How to use Android Fingerprint API to save user passwords ........................................................ 414
Section 55.2: Adding the Fingerprint Scanner in Android application ................................................................. 421
Chapter 56: Bluetooth and Bluetooth LE API ............................................................................................. 424
Section 56.1: Permissions .......................................................................................................................................... 424
Section 56.2: Check if bluetooth is enabled ............................................................................................................ 424
Section 56.3: Find nearby Bluetooth Low Energy devices .................................................................................... 424
Section 56.4: Make device discoverable ................................................................................................................. 429
Section 56.5: Connect to Bluetooth device ............................................................................................................. 429
Section 56.6: Find nearby bluetooth devices .......................................................................................................... 431
Chapter 57: Runtime Permissions in API-23 + ............................................................................................. 432
Section 57.1: Android 6.0 multiple permissions ....................................................................................................... 432
Section 57.2: Multiple Runtime Permissions From Same Permission Groups ..................................................... 433
Section 57.3: Using PermissionUtil ........................................................................................................................... 434
Section 57.4: Include all permission-related code to an abstract base class and extend the activity of this
base class to achieve cleaner/reusable code ............................................................................................... 435
Section 57.5: Enforcing Permissions in Broadcasts, URI ....................................................................................... 437
Chapter 58: Android Places API ......................................................................................................................... 439
Section 58.1: Getting Current Places by Using Places API ..................................................................................... 439
Section 58.2: Place Autocomplete Integration ....................................................................................................... 440
Section 58.3: Place Picker Usage Example ............................................................................................................. 441
Section 58.4: Setting place type filters for PlaceAutocomplete ........................................................................... 442
Section 58.5: Adding more than one google auto complete activity .................................................................. 443
Chapter 59: Android NDK ..................................................................................................................................... 445
Section 59.1: How to log in ndk ................................................................................................................................ 445
Section 59.2: Building native executables for Android .......................................................................................... 445
Section 59.3: How to clean the build ....................................................................................................................... 446
Section 59.4: How to use a makefile other than Android.mk ............................................................................... 446
Chapter 60: DayNight Theme (AppCompat v23.2 / API 14+) ............................................................. 447
Section 60.1: Adding the DayNight theme to an app ............................................................................................ 447
Chapter 61: Glide ....................................................................................................................................................... 448
Section 61.1: Loading an image ................................................................................................................................ 448
Section 61.2: Add Glide to your project ................................................................................................................... 449
Section 61.3: Glide circle transformation (Load image in a circular ImageView) ............................................... 449
Section 61.4: Default transformations ..................................................................................................................... 450
Section 61.5: Glide rounded corners image with custom Glide target ................................................................. 451
Section 61.6: Placeholder and Error handling ......................................................................................................... 451
Section 61.7: Preloading images .............................................................................................................................. 452
Section 61.8: Handling Glide image load failed ...................................................................................................... 452
Section 61.9: Load image in a circular ImageView without custom transformations ........................................ 453
Chapter 62: Dialog ................................................................................................................................................... 454
Section 62.1: Adding Material Design AlertDialog to your app using Appcompat ............................................. 454
Section 62.2: A Basic Alert Dialog ............................................................................................................................ 454
Section 62.3: ListView in AlertDialog ....................................................................................................................... 455
Section 62.4: Custom Alert Dialog with EditText .................................................................................................... 456
Section 62.5: DatePickerDialog ................................................................................................................................ 457
Section 62.6: DatePicker ........................................................................................................................................... 457
Section 62.7: Alert Dialog ......................................................................................................................................... 458
Section 62.8: Alert Dialog with Multi-line Title ........................................................................................................ 459
Section 62.9: Date Picker within DialogFragment ................................................................................................. 461
Section 62.10: Fullscreen Custom Dialog with no background and no title ........................................................ 463
Chapter 63: Enhancing Alert Dialogs .............................................................................................................. 465
Section 63.1: Alert dialog containing a clickable link ............................................................................................. 465
Chapter 64: Animated AlertDialog Box ......................................................................................................... 466
Section 64.1: Put Below code for Animated dialog.. ............................................................................................... 466
Chapter 65: GreenDAO ........................................................................................................................................... 469
Section 65.1: Helper methods for SELECT, INSERT, DELETE, UPDATE queries ................................................... 469
Section 65.2: Creating an Entity with GreenDAO 3.X that has a Composite Primary Key ................................ 471
Section 65.3: Getting started with GreenDao v3.X ................................................................................................. 472
Chapter 66: Tools Attributes ............................................................................................................................... 474
Section 66.1: Designtime Layout Attributes ............................................................................................................ 474
Chapter 67: Formatting Strings ........................................................................................................................ 475
Section 67.1: Format a string resource .................................................................................................................... 475
Section 67.2: Formatting data types to String and vise versa ............................................................................. 475
Section 67.3: Format a timestamp to string ........................................................................................................... 475
Chapter 68: SpannableString ............................................................................................................................. 476
Section 68.1: Add styles to a TextView .................................................................................................................... 476
Section 68.2: Multi string , with multi color .............................................................................................................. 478
Chapter 69: Notifications ...................................................................................................................................... 480
Section 69.1: Heads Up Notification with Ticker for older devices ....................................................................... 480
Section 69.2: Creating a simple Notification .......................................................................................................... 484
Section 69.3: Set custom notification - show full content text .............................................................................. 484
Section 69.4: Dynamically getting the correct pixel size for the large icon ........................................................ 485
Section 69.5: Ongoing notification with Action button .......................................................................................... 485
Section 69.6: Setting Dierent priorities in notification ......................................................................................... 486
Section 69.7: Set custom notification icon using `Picasso` library ........................................................................ 487
Section 69.8: Scheduling notifications ..................................................................................................................... 488
Chapter 70: AlarmManager ................................................................................................................................ 490
Section 70.1: How to Cancel an Alarm .................................................................................................................... 490
Section 70.2: Creating exact alarms on all Android versions ............................................................................... 490
Section 70.3: API23+ Doze mode interferes with AlarmManager ........................................................................ 491
Section 70.4: Run an intent at a later time ............................................................................................................. 491
Chapter 71: Handler ................................................................................................................................................. 492
Section 71.1: HandlerThreads and communication between Threads ................................................................. 492
Section 71.2: Use Handler to create a Timer (similar to javax.swing.Timer) ....................................................... 492
Section 71.3: Using a Handler to execute code after a delayed amount of time ............................................... 493
Section 71.4: Stop handler from execution ............................................................................................................. 494
Chapter 72: BroadcastReceiver ........................................................................................................................ 495
Section 72.1: Using LocalBroadcastManager ......................................................................................................... 495
Section 72.2: BroadcastReceiver Basics ................................................................................................................. 495
Section 72.3: Introduction to Broadcast receiver ................................................................................................... 496
Section 72.4: Using ordered broadcasts ................................................................................................................. 496
Section 72.5: Sticky Broadcast ................................................................................................................................. 497
Section 72.6: Enabling and disabling a Broadcast Receiver programmatically ................................................ 497
Section 72.7: Example of a LocalBroadcastManager ........................................................................................... 498
Section 72.8: Android stopped state ....................................................................................................................... 499
Section 72.9: Communicate two activities through custom Broadcast receiver ................................................ 499
Section 72.10: BroadcastReceiver to handle BOOT_COMPLETED events .......................................................... 500
Section 72.11: Bluetooth Broadcast receiver ........................................................................................................... 501
Chapter 73: UI Lifecycle ........................................................................................................................................ 502
Section 73.1: Saving data on memory trimming .................................................................................................... 502
Chapter 74: HttpURLConnection ...................................................................................................................... 503
Section 74.1: Creating an HttpURLConnection ....................................................................................................... 503
Section 74.2: Sending an HTTP GET request .......................................................................................................... 503
Section 74.3: Reading the body of an HTTP GET request .................................................................................... 504
Section 74.4: Sending an HTTP POST request with parameters .......................................................................... 504
Section 74.5: A multi-purpose HttpURLConnection class to handle all types of HTTP requests ..................... 506
Section 74.6: Use HttpURLConnection for multipart/form-data ......................................................................... 508
Section 74.7: Upload (POST) file using HttpURLConnection ................................................................................ 511
Chapter 75: Callback URL .................................................................................................................................... 513
Section 75.1: Callback URL example with Instagram OAuth ................................................................................. 513
Chapter 76: Snackbar ............................................................................................................................................. 514
Section 76.1: Creating a simple Snackbar ............................................................................................................... 514
Section 76.2: Custom Snack Bar .............................................................................................................................. 514
Section 76.3: Custom Snackbar (no need view) ..................................................................................................... 515
Section 76.4: Snackbar with Callback ..................................................................................................................... 516
Section 76.5: Snackbar vs Toasts: Which one should I use? ................................................................................. 516
Section 76.6: Custom Snackbar ............................................................................................................................... 517
Chapter 77: Widgets ............................................................................................................................................... 518
Section 77.1: Manifest Declaration - ........................................................................................................................ 518
Section 77.2: Metadata ............................................................................................................................................. 518
Section 77.3: AppWidgetProvider Class .................................................................................................................. 518
Section 77.4: Create/Integrate Basic Widget using Android Studio .................................................................... 519
Section 77.5: Two widgets with dierent layouts declaration .............................................................................. 520
Chapter 78: Toast ..................................................................................................................................................... 522
Section 78.1: Creating a custom Toast .................................................................................................................... 522
Section 78.2: Set position of a Toast ....................................................................................................................... 523
Section 78.3: Showing a Toast Message ................................................................................................................. 523
Section 78.4: Show Toast Message Above Soft Keyboard ................................................................................... 524
Section 78.5: Thread safe way of displaying Toast (Application Wide) ............................................................. 524
Section 78.6: Thread safe way of displaying a Toast Message (For AsyncTask) ............................................. 525
Chapter 79: Create Singleton Class for Toast Message ....................................................................... 526
Section 79.1: Create own singleton class for toast massages .............................................................................. 526
Chapter 80: Interfaces ........................................................................................................................................... 528
Section 80.1: Custom Listener .................................................................................................................................. 528
Section 80.2: Basic Listener ...................................................................................................................................... 529
Chapter 81: Animators ............................................................................................................................................ 531
Section 81.1: TransitionDrawable animation ........................................................................................................... 531
Section 81.2: Fade in/out animation ........................................................................................................................ 531
Section 81.3: ValueAnimator ..................................................................................................................................... 532
Section 81.4: Expand and Collapse animation of View .......................................................................................... 533
Section 81.5: ObjectAnimator ................................................................................................................................... 534
Section 81.6: ViewPropertyAnimator ....................................................................................................................... 534
Section 81.7: Shake animation of an ImageView ................................................................................................... 535
Chapter 82: Location .............................................................................................................................................. 537
Section 82.1: Fused location API ............................................................................................................................... 537
Section 82.2: Get Address From Location using Geocoder .................................................................................. 541
Section 82.3: Requesting location updates using LocationManager .................................................................. 542
Section 82.4: Requesting location updates on a separate thread using LocationManager ............................. 543
Section 82.5: Getting location updates in a BroadcastReceiver .......................................................................... 544
Section 82.6: Register geofence .............................................................................................................................. 545
Chapter 83: Theme, Style, Attribute ............................................................................................................... 549
Section 83.1: Define primary, primary dark, and accent colors ........................................................................... 549
Section 83.2: Multiple Themes in one App .............................................................................................................. 549
Section 83.3: Navigation Bar Color (API 21+) .......................................................................................................... 551
Section 83.4: Use Custom Theme Per Activity ....................................................................................................... 551
Section 83.5: Light Status Bar (API 23+) .................................................................................................................. 552
Section 83.6: Use Custom Theme Globally ............................................................................................................. 552
Section 83.7: Overscroll Color (API 21+) .................................................................................................................. 552
Section 83.8: Ripple Color (API 21+) ......................................................................................................................... 552
Section 83.9: Translucent Navigation and Status Bars (API 19+) ......................................................................... 553
Section 83.10: Theme inheritance ............................................................................................................................ 553
Chapter 84: MediaPlayer ..................................................................................................................................... 554
Section 84.1: Basic creation and playing ................................................................................................................ 554
Section 84.2: Media Player with Buer progress and play position .................................................................... 554
Section 84.3: Getting system ringtones .................................................................................................................. 556
Section 84.4: Asynchronous prepare ...................................................................................................................... 557
Section 84.5: Import audio into androidstudio and play it ................................................................................... 557
Section 84.6: Getting and setting system volume ................................................................................................. 559
Chapter 85: Android Sound and Media ......................................................................................................... 561
Section 85.1: How to pick image and video for api >19 ......................................................................................... 561
Section 85.2: Play sounds via SoundPool ............................................................................................................... 562
Chapter 86: MediaSession .................................................................................................................................... 563
Section 86.1: Receiving and handling button events ............................................................................................. 563
Chapter 87: MediaStore ........................................................................................................................................ 566
Section 87.1: Fetch Audio/MP3 files from specific folder of device or fetch all files .......................................... 566
Chapter 88: Multidex and the Dex Method Limit ...................................................................................... 569
Section 88.1: Enabling Multidex ................................................................................................................................ 569
Section 88.2: Multidex by extending Application ................................................................................................... 570
Section 88.3: Multidex by extending MultiDexApplication ..................................................................................... 570
Section 88.4: Multidex by using MultiDexApplication directly ............................................................................... 571
Section 88.5: Counting Method References On Every Build (Dexcount Gradle Plugin) ..................................... 571
Chapter 89: Data Synchronization with Sync Adapter ......................................................................... 573
Section 89.1: Dummy Sync Adapter with Stub Provider ........................................................................................ 573
Chapter 90: PorterDu Mode ............................................................................................................................ 579
Section 90.1: Creating a PorterDu ColorFilter ...................................................................................................... 579
Section 90.2: Creating a PorterDu XferMode ...................................................................................................... 579
Section 90.3: Apply a radial mask (vignette) to a bitmap using PorterDuXfermode ..................................... 579
Chapter 91: Menu ...................................................................................................................................................... 581
Section 91.1: Options menu with dividers ................................................................................................................. 581
Section 91.2: Apply custom font to Menu ................................................................................................................ 581
Section 91.3: Creating a Menu in an Activity ........................................................................................................... 582
Chapter 92: Picasso ................................................................................................................................................. 585
Section 92.1: Adding Picasso Library to your Android Project ............................................................................. 585
Section 92.2: Circular Avatars with Picasso ............................................................................................................ 585
Section 92.3: Placeholder and Error Handling ....................................................................................................... 587
Section 92.4: Re-sizing and Rotating ...................................................................................................................... 587
Section 92.5: Disable cache in Picasso ................................................................................................................... 588
Section 92.6: Using Picasso as ImageGetter for Html.fromHtml ......................................................................... 588
Section 92.7: Cancelling Image Requests using Picasso ....................................................................................... 589
Section 92.8: Loading Image from external Storage ............................................................................................ 590
Section 92.9: Downloading image as Bitmap using Picasso ................................................................................ 590
Section 92.10: Try oine disk cache first, then go online and fetch the image ................................................. 590
Chapter 93: RoboGuice .......................................................................................................................................... 592
Section 93.1: Simple example ................................................................................................................................... 592
Section 93.2: Installation for Gradle Projects ......................................................................................................... 592
Section 93.3: @ContentView annotation ................................................................................................................ 592
Section 93.4: @InjectResource annotation ............................................................................................................. 592
Section 93.5: @InjectView annotation ..................................................................................................................... 593
Section 93.6: Introduction to RoboGuice ................................................................................................................. 593
Chapter 94: ACRA ..................................................................................................................................................... 596
Section 94.1: ACRAHandler ....................................................................................................................................... 596
Section 94.2: Example manifest ............................................................................................................................... 596
Section 94.3: Installation ........................................................................................................................................... 597
Chapter 95: Parcelable .......................................................................................................................................... 598
Section 95.1: Making a custom object Parcelable .................................................................................................. 598
Section 95.2: Parcelable object containing another Parcelable object ............................................................... 599
Section 95.3: Using Enums with Parcelable ............................................................................................................ 600
Chapter 96: Retrofit2 .............................................................................................................................................. 602
Section 96.1: A Simple GET Request ........................................................................................................................ 602
Section 96.2: Debugging with Stetho ...................................................................................................................... 604
Section 96.3: Add logging to Retrofit2 .................................................................................................................... 605
Section 96.4: A simple POST request with GSON ................................................................................................... 605
Section 96.5: Download a file from Server using Retrofit2 ................................................................................... 607
Section 96.6: Upload multiple file using Retrofit as multipart .............................................................................. 609
Section 96.7: Retrofit with OkHttp interceptor ....................................................................................................... 612
Section 96.8: Header and Body: an Authentication Example ............................................................................... 612
Section 96.9: Uploading a file via Multipart ............................................................................................................ 613
Section 96.10: Retrofit 2 Custom Xml Converter .................................................................................................... 613
Section 96.11: Reading XML form URL with Retrofit 2 ............................................................................................ 615
Chapter 97: ButterKnife ........................................................................................................................................ 618
Section 97.1: Configuring ButterKnife in your project ............................................................................................ 618
Section 97.2: Unbinding views in ButterKnife ......................................................................................................... 620
Section 97.3: Binding Listeners using ButterKnife .................................................................................................. 620
Section 97.4: Android Studio ButterKnife Plugin .................................................................................................... 621
Section 97.5: Binding Views using ButterKnife ....................................................................................................... 622
Chapter 98: Volley .................................................................................................................................................... 625
Section 98.1: Using Volley for HTTP requests ......................................................................................................... 625
Section 98.2: Basic StringRequest using GET method .......................................................................................... 626
Section 98.3: Adding custom design time attributes to NetworkImageView ...................................................... 627
Section 98.4: Adding custom headers to your requests [e.g. for basic auth] .................................................... 628
Section 98.5: Remote server authentication using StringRequest through POST method ............................... 629
Section 98.6: Cancel a request ................................................................................................................................. 631
Section 98.7: Request JSON ..................................................................................................................................... 631
Section 98.8: Use JSONArray as request body ..................................................................................................... 631
Section 98.9: Boolean variable response from server with json request in volley ............................................. 632
Section 98.10: Helper Class for Handling Volley Errors ......................................................................................... 633
Chapter 99: Date and Time Pickers ................................................................................................................. 635
Section 99.1: Date Picker Dialog .............................................................................................................................. 635
Section 99.2: Material DatePicker ............................................................................................................................ 635
Chapter 100: Localized Date/Time in Android .......................................................................................... 638
Section 100.1: Custom localized date format with DateUtils.formatDateTime() ................................................ 638
Section 100.2: Standard date/time formatting in Android ................................................................................... 638
Section 100.3: Fully customized date/time ............................................................................................................. 638
Chapter 101: Time Utils ........................................................................................................................................... 639
Section 101.1: To check within a period .................................................................................................................... 639
Section 101.2: Convert Date Format into Milliseconds ........................................................................................... 639
Section 101.3: GetCurrentRealTime .......................................................................................................................... 640
Chapter 102: In-app Billing ................................................................................................................................... 641
Section 102.1: Consumable In-app Purchases ........................................................................................................ 641
Section 102.2: (Third party) In-App v3 Library ....................................................................................................... 645
Chapter 103: FloatingActionButton ................................................................................................................. 647
Section 103.1: How to add the FAB to the layout .................................................................................................... 647
Section 103.2: Show and Hide FloatingActionButton on Swipe ............................................................................ 648
Section 103.3: Show and Hide FloatingActionButton on Scroll ............................................................................. 650
Section 103.4: Setting behaviour of FloatingActionButton .................................................................................... 652
Chapter 104: Touch Events .................................................................................................................................. 653
Section 104.1: How to vary between child and parent view group touch events ............................................... 653
Chapter 105: Handling touch and motion events .................................................................................... 656
Section 105.1: Buttons ................................................................................................................................................ 656
Section 105.2: Surface ............................................................................................................................................... 657
Section 105.3: Handling multitouch in a surface .................................................................................................... 658
Chapter 106: Detect Shake Event in Android ............................................................................................. 659
Section 106.1: Shake Detector in Android Example ................................................................................................ 659
Section 106.2: Using Seismic shake detection ........................................................................................................ 660
Chapter 107: Hardware Button Events/Intents (PTT, LWP, etc.) ..................................................... 661
Section 107.1: Sonim Devices .................................................................................................................................... 661
Section 107.2: RugGear Devices ............................................................................................................................... 661
Chapter 108: GreenRobot EventBus ................................................................................................................ 662
Section 108.1: Passing a Simple Event ..................................................................................................................... 662
Section 108.2: Receiving Events ............................................................................................................................... 663
Section 108.3: Sending Events .................................................................................................................................. 663
Chapter 109: Otto Event Bus ............................................................................................................................... 664
Section 109.1: Passing an event ................................................................................................................................ 664
Section 109.2: Receiving an event ........................................................................................................................... 664
Chapter 110: Vibration ............................................................................................................................................ 666
Section 110.1: Getting Started with Vibration ........................................................................................................... 666
Section 110.2: Vibrate Indefinitely ............................................................................................................................ 666
Section 110.3: Vibration Patterns .............................................................................................................................. 666
Section 110.4: Stop Vibrate ........................................................................................................................................ 667
Section 110.5: Vibrate for one time .......................................................................................................................... 667
Chapter 111: ContentProvider .............................................................................................................................. 668
Section 111.1: Implementing a basic content provider class .................................................................................. 668
Chapter 112: Dagger 2 ............................................................................................................................................. 672
Section 112.1: Component setup for Application and Activity injection ................................................................ 672
Section 112.2: Custom Scopes .................................................................................................................................. 673
Section 112.3: Using @Subcomponent instead of @Component(dependencies={...}) ....................................... 674
Section 112.4: Creating a component from multiple modules .............................................................................. 674
Section 112.5: How to add Dagger 2 in build.gradle .............................................................................................. 675
Section 112.6: Constructor Injection ......................................................................................................................... 676
Chapter 113: Realm ................................................................................................................................................... 678
Section 113.1: Sorted queries ..................................................................................................................................... 678
Section 113.2: Using Realm with RxJava ................................................................................................................. 678
Section 113.3: Basic Usage ........................................................................................................................................ 679
Section 113.4: List of primitives (RealmList<Integer/String/...>) ............................................................................ 682
Section 113.5: Async queries ..................................................................................................................................... 683
Section 113.6: Adding Realm to your project .......................................................................................................... 683
Section 113.7: Realm Models ..................................................................................................................................... 683
Section 113.8: try-with-resources .............................................................................................................................. 684
Chapter 114: Android Versions ........................................................................................................................... 685
Section 114.1: Checking the Android Version on device at runtime ...................................................................... 685
Chapter 115: Wi-Fi Connections .......................................................................................................................... 686
Section 115.1: Connect with WEP encryption ........................................................................................................... 686
Section 115.2: Connect with WPA2 encryption ........................................................................................................ 686
Section 115.3: Scan for access points ....................................................................................................................... 687
Chapter 116: SensorManager .............................................................................................................................. 689
Section 116.1: Decide if your device is static or not, using the accelerometer ..................................................... 689
Section 116.2: Retrieving sensor events ................................................................................................................... 689
Section 116.3: Sensor transformation to world coordinate system ...................................................................... 690
Chapter 117: ProgressBar ..................................................................................................................................... 692
Section 117.1: Material Linear ProgressBar .............................................................................................................. 692
Section 117.2: Tinting ProgressBar ........................................................................................................................... 694
Section 117.3: Customized progressbar ................................................................................................................... 694
Section 117.4: Creating Custom Progress Dialog .................................................................................................... 696
Section 117.5: Indeterminate ProgressBar ............................................................................................................... 698
Section 117.6: Determinate ProgressBar ................................................................................................................. 699
Chapter 118: Custom Fonts ................................................................................................................................... 701
Section 118.1: Custom font in canvas text ................................................................................................................ 701
Section 118.2: Working with fonts in Android O ...................................................................................................... 701
Section 118.3: Custom font to whole activity ........................................................................................................... 702
Section 118.4: Putting a custom font in your app ................................................................................................... 702
Section 118.5: Initializing a font ................................................................................................................................. 702
Section 118.6: Using a custom font in a TextView .................................................................................................. 702
Section 118.7: Apply font on TextView by xml (Not required Java code) ............................................................ 703
Section 118.8: Ecient Typeface loading ................................................................................................................ 704
Chapter 119: Getting system font names and using the fonts .......................................................... 705
Section 119.1: Getting system font names ............................................................................................................... 705
Section 119.2: Applying a system font to a TextView ............................................................................................. 705
Chapter 120: Text to Speech(TTS) ................................................................................................................... 706
Section 120.1: Text to Speech Base .......................................................................................................................... 706
Section 120.2: TextToSpeech implementation across the APIs ............................................................................ 707
Chapter 121: Spinner ................................................................................................................................................ 711
Section 121.1: Basic Spinner Example ....................................................................................................................... 711
Section 121.2: Adding a spinner to your activity ..................................................................................................... 712
Chapter 122: Data Encryption/Decryption .................................................................................................. 714
Section 122.1: AES encryption of data using password in a secure way ............................................................. 714
Chapter 123: OkHttp ................................................................................................................................................ 716
Section 123.1: Basic usage example ......................................................................................................................... 716
Section 123.2: Setting up OkHttp .............................................................................................................................. 716
Section 123.3: Logging interceptor .......................................................................................................................... 716
Section 123.4: Synchronous Get Call ........................................................................................................................ 717
Section 123.5: Asynchronous Get Call ..................................................................................................................... 717
Section 123.6: Posting form parameters ................................................................................................................. 718
Section 123.7: Posting a multipart request .............................................................................................................. 718
Section 123.8: Rewriting Responses ........................................................................................................................ 718
Chapter 124: Handling Deep Links ................................................................................................................... 720
Section 124.1: Retrieving query parameters ........................................................................................................... 720
Section 124.2: Simple deep link ................................................................................................................................ 720
Section 124.3: Multiple paths on a single domain .................................................................................................. 721
Section 124.4: Multiple domains and multiple paths .............................................................................................. 721
Section 124.5: Both http and https for the same domain ...................................................................................... 722
Section 124.6: Using pathPrefix ................................................................................................................................ 722
Chapter 125: Crash Reporting Tools ............................................................................................................... 723
Section 125.1: Fabric - Crashlytics ............................................................................................................................ 723
Section 125.2: Capture crashes using Sherlock ...................................................................................................... 728
Section 125.3: Force a Test Crash With Fabric ....................................................................................................... 729
Section 125.4: Crash Reporting with ACRA ............................................................................................................. 730
Chapter 126: Check Internet Connectivity .................................................................................................... 732
Section 126.1: Check if device has internet connectivity ........................................................................................ 732
Section 126.2: How to check network strength in android? .................................................................................. 732
Section 126.3: How to check network strength ....................................................................................................... 733
Chapter 127: Creating your own libraries for Android applications ............................................... 736
Section 127.1: Create a library available on Jitpack.io ........................................................................................... 736
Section 127.2: Creating library project .................................................................................................................... 736
Section 127.3: Using library in project as a module ............................................................................................... 737
Chapter 128: Device Display Metrics ............................................................................................................... 738
Section 128.1: Get the screens pixel dimensions ..................................................................................................... 738
Section 128.2: Get screen density ............................................................................................................................ 738
Section 128.3: Formula px to dp, dp to px conversation ....................................................................................... 738
Chapter 129: Building Backwards Compatible Apps ............................................................................... 739
Section 129.1: How to handle deprecated API ........................................................................................................ 739
Chapter 130: Loader ................................................................................................................................................ 741
Section 130.1: Basic AsyncTaskLoader .................................................................................................................... 741
Section 130.2: AsyncTaskLoader with cache .......................................................................................................... 742
Section 130.3: Reloading ........................................................................................................................................... 743
Section 130.4: Pass parameters using a Bundle .................................................................................................... 744
Chapter 131: ProGuard - Obfuscating and Shrinking your code ....................................................... 745
Section 131.1: Rules for some of the widely used Libraries .................................................................................... 745
Section 131.2: Remove trace logging (and other) statements at build time ....................................................... 747
Section 131.3: Protecting your code from hackers ................................................................................................. 747
Section 131.4: Enable ProGuard for your build ........................................................................................................ 748
Section 131.5: Enabling ProGuard with a custom obfuscation configuration file ................................................ 748
Chapter 132: Typedef Annotations: @IntDef, @StringDef .................................................................. 750
Section 132.1: IntDef Annotations ............................................................................................................................. 750
Section 132.2: Combining constants with flags ...................................................................................................... 750
Chapter 133: Capturing Screenshots ............................................................................................................... 752
Section 133.1: Taking a screenshot of a particular view ........................................................................................ 752
Section 133.2: Capturing Screenshot via Android Studio ....................................................................................... 752
Section 133.3: Capturing Screenshot via ADB and saving directly in your PC .................................................... 753
Section 133.4: Capturing Screenshot via Android Device Monitor ........................................................................ 753
Section 133.5: Capturing Screenshot via ADB ......................................................................................................... 754
Chapter 134: MVP Architecture .......................................................................................................................... 755
Section 134.1: Login example in the Model View Presenter (MVP) pattern ......................................................... 755
Section 134.2: Simple Login Example in MVP .......................................................................................................... 758
Chapter 135: Orientation Changes ................................................................................................................... 765
Section 135.1: Saving and Restoring Activity State ................................................................................................. 765
Section 135.2: Retaining Fragments ........................................................................................................................ 765
Section 135.3: Manually Managing Configuration Changes ................................................................................. 766
Section 135.4: Handling AsyncTask ......................................................................................................................... 767
Section 135.5: Lock Screen's rotation programmatically ...................................................................................... 768
Section 135.6: Saving and Restoring Fragment State ........................................................................................... 769
Chapter 136: Xposed ................................................................................................................................................ 771
Section 136.1: Creating a Xposed Module ................................................................................................................ 771
Section 136.2: Hooking a method ............................................................................................................................ 771
Chapter 137: PackageManager .......................................................................................................................... 773
Section 137.1: Retrieve application version ............................................................................................................. 773
Section 137.2: Version name and version code ...................................................................................................... 773
Section 137.3: Install time and update time ............................................................................................................ 773
Section 137.4: Utility method using PackageManager .......................................................................................... 774
Chapter 138: Gesture Detection ........................................................................................................................ 776
Section 138.1: Swipe Detection .................................................................................................................................. 776
Section 138.2: Basic Gesture Detection ................................................................................................................... 777
Chapter 139: Doze Mode ........................................................................................................................................ 779
Section 139.1: Whitelisting an Android application programmatically ................................................................. 779
Section 139.2: Exclude app from using doze mode ............................................................................................... 779
Chapter 140: Colors ................................................................................................................................................. 780
Section 140.1: Color Manipulation ............................................................................................................................ 780
Chapter 141: Keyboard .......................................................................................................................................... 781
Section 141.1: Register a callback for keyboard open and close .......................................................................... 781
Section 141.2: Hide keyboard when user taps anywhere else on the screen ...................................................... 781
Chapter 142: RenderScript .................................................................................................................................. 783
Section 142.1: Getting Started ................................................................................................................................... 783
Section 142.2: Blur a View ......................................................................................................................................... 789
Section 142.3: Blur an image .................................................................................................................................... 791
Chapter 143: Fresco ................................................................................................................................................. 794
Section 143.1: Getting Started with Fresco .............................................................................................................. 794
Section 143.2: Using OkHttp 3 with Fresco .............................................................................................................. 795
Section 143.3: JPEG Streaming with Fresco using DraweeController .................................................................. 795
Chapter 144: Swipe to Refresh ......................................................................................................................... 796
Section 144.1: How to add Swipe-to-Refresh To your app .................................................................................... 796
Section 144.2: Swipe To Refresh with RecyclerView .............................................................................................. 796
Chapter 145: Creating Splash screen ............................................................................................................. 798
Section 145.1: Splash screen with animation ........................................................................................................... 798
Section 145.2: A basic splash screen ....................................................................................................................... 799
Chapter 146: IntentService .................................................................................................................................. 802
Section 146.1: Creating an IntentService .................................................................................................................. 802
Section 146.2: Basic IntentService Example ............................................................................................................ 802
Section 146.3: Sample Intent Service ....................................................................................................................... 803
Chapter 147: Implicit Intents ............................................................................................................................... 805
Section 147.1: Implicit and Explicit Intents ................................................................................................................ 805
Section 147.2: Implicit Intents ................................................................................................................................... 805
Chapter 148: Publish to Play Store .................................................................................................................. 806
Section 148.1: Minimal app submission guide ......................................................................................................... 806
Chapter 149: Universal Image Loader ........................................................................................................... 808
Section 149.1: Basic usage ........................................................................................................................................ 808
Section 149.2: Initialize Universal Image Loader .................................................................................................... 808
Chapter 150: Image Compression .................................................................................................................... 809
Section 150.1: How to compress image without size change ................................................................................ 809
Chapter 151: 9-Patch Images ............................................................................................................................... 812
Section 151.1: Basic rounded corners ....................................................................................................................... 812
Section 151.2: Optional padding lines ...................................................................................................................... 812
Section 151.3: Basic spinner ...................................................................................................................................... 813
Chapter 152: Email Validation ............................................................................................................................ 814
Section 152.1: Email address validation ................................................................................................................... 814
Section 152.2: Email Address validation with using Patterns ................................................................................ 814
Chapter 153: Bottom Sheets ............................................................................................................................... 815
Section 153.1: Quick Setup ......................................................................................................................................... 815
Section 153.2: BottomSheetBehavior like Google maps ........................................................................................ 815
Section 153.3: Modal bottom sheets with BottomSheetDialog ............................................................................. 822
Section 153.4: Modal bottom sheets with BottomSheetDialogFragment ............................................................ 822
Section 153.5: Persistent Bottom Sheets ................................................................................................................. 822
Section 153.6: Open BottomSheet DialogFragment in Expanded mode by default .......................................... 823
Chapter 154: EditText ............................................................................................................................................. 825
Section 154.1: Working with EditTexts ...................................................................................................................... 825
Section 154.2: Customizing the InputType .............................................................................................................. 827
Section 154.3: Icon or button inside Custom Edit Text and its action and click listeners ................................... 827
Section 154.4: Hiding SoftKeyboard ........................................................................................................................ 829
Section 154.5: `inputype` attribute ............................................................................................................................ 830
Chapter 155: Speech to Text Conversion ...................................................................................................... 832
Section 155.1: Speech to Text With Default Google Prompt Dialog ...................................................................... 832
Section 155.2: Speech to Text without Dialog ......................................................................................................... 833
Chapter 156: Installing apps with ADB ........................................................................................................... 835
Section 156.1: Uninstall an app ................................................................................................................................. 835
Section 156.2: Install all apk file in directory ........................................................................................................... 835
Section 156.3: Install an app ..................................................................................................................................... 835
Chapter 157: Count Down Timer ....................................................................................................................... 836
Section 157.1: Creating a simple countdown timer ................................................................................................. 836
Section 157.2: A More Complex Example ................................................................................................................ 836
Chapter 158: Barcode and QR code reading .............................................................................................. 838
Section 158.1: Using QRCodeReaderView (based on Zxing) ................................................................................. 838
Chapter 159: Android PayPal Gateway Integration ................................................................................ 840
Section 159.1: Setup PayPal in your android code ................................................................................................. 840
Chapter 160: Drawables ........................................................................................................................................ 842
Section 160.1: Custom Drawable .............................................................................................................................. 842
Section 160.2: Tint a drawable ................................................................................................................................. 843
Section 160.3: Circular View ...................................................................................................................................... 844
Section 160.4: Make View with rounded corners .................................................................................................... 844
Chapter 161: TransitionDrawable ...................................................................................................................... 846
Section 161.1: Animate views background color (switch-color) with TransitionDrawable .................................. 846
Section 161.2: Add transition or Cross-fade between two images ....................................................................... 846
Chapter 162: Vector Drawables ......................................................................................................................... 848
Section 162.1: Importing SVG file as VectorDrawable ............................................................................................ 848
Section 162.2: VectorDrawable Usage Example .................................................................................................... 850
Section 162.3: VectorDrawable xml example ......................................................................................................... 851
Chapter 163: VectorDrawable and AnimatedVectorDrawable ......................................................... 852
Section 163.1: Basic VectorDrawable ....................................................................................................................... 852
Section 163.2: <group> tags ...................................................................................................................................... 852
Section 163.3: Basic AnimatedVectorDrawable ...................................................................................................... 853
Section 163.4: Using Strokes ..................................................................................................................................... 854
Section 163.5: Using <clip-path> ............................................................................................................................... 856
Section 163.6: Vector compatibility through AppCompat ..................................................................................... 856
Chapter 164: Port Mapping using Cling library in Android .................................................................. 858
Section 164.1: Mapping a NAT port .......................................................................................................................... 858
Section 164.2: Adding Cling Support to your Android Project .............................................................................. 858
Chapter 165: Creating Overlay (always-on-top) Windows .................................................................. 860
Section 165.1: Popup overlay .................................................................................................................................... 860
Section 165.2: Granting SYSTEM_ALERT_WINDOW Permission on android 6.0 and above ............................ 860
Chapter 166: ExoPlayer .......................................................................................................................................... 862
Section 166.1: Add ExoPlayer to the project ............................................................................................................ 862
Section 166.2: Using ExoPlayer ................................................................................................................................ 862
Section 166.3: Main steps to play video & audio using the standard TrackRenderer implementations
............................................................................................................................................................................. 863
Chapter 167: XMPP register login and chat simple example .............................................................. 864
Section 167.1: XMPP register login and chat basic example .................................................................................. 864
Chapter 168: Android Authenticator ............................................................................................................... 873
Section 168.1: Basic Account Authenticator Service ............................................................................................... 873
Chapter 169: AudioManager ................................................................................................................................ 876
Section 169.1: Requesting Transient Audio Focus .................................................................................................. 876
Section 169.2: Requesting Audio Focus ................................................................................................................... 876
Chapter 170: AudioTrack ....................................................................................................................................... 877
Section 170.1: Generate tone of a specific frequency ............................................................................................ 877
Chapter 171: Job Scheduling ............................................................................................................................... 878
Section 171.1: Basic usage ......................................................................................................................................... 878
Chapter 172: Accounts and AccountManager ............................................................................................ 880
Section 172.1: Understanding custom accounts/authentication .......................................................................... 880
Chapter 173: Integrate OpenCV into Android Studio .............................................................................. 882
Section 173.1: Instructions .......................................................................................................................................... 882
Chapter 174: MVVM (Architecture) .................................................................................................................. 890
Section 174.1: MVVM Example using DataBinding Library .................................................................................... 890
Chapter 175: ORMLite in android ...................................................................................................................... 897
Section 175.1: Android OrmLite over SQLite example ............................................................................................ 897
Chapter 176: Retrofit2 with RxJava ................................................................................................................. 901
Section 176.1: Retrofit2 with RxJava ........................................................................................................................ 901
Section 176.2: Nested requests example: multiple requests, combine results .................................................... 902
Section 176.3: Retrofit with RxJava to fetch data asyncronously ........................................................................ 903
Chapter 177: ShortcutManager ......................................................................................................................... 906
Section 177.1: Dynamic Launcher Shortcuts ............................................................................................................ 906
Chapter 178: LruCache ........................................................................................................................................... 907
Section 178.1: Adding a Bitmap(Resource) to the cache ....................................................................................... 907
Section 178.2: Initialising the cache .......................................................................................................................... 907
Section 178.3: Getting a Bitmap(Resouce) from the cache .................................................................................. 907
Chapter 179: Jenkins CI setup for Android Projects ................................................................................ 908
Section 179.1: Step by step approach to set up Jenkins for Android ................................................................... 908
Chapter 180: fastlane ............................................................................................................................................. 912
Section 180.1: Fastfile lane to build and install all flavors for given build type to a device ............................... 912
Section 180.2: Fastfile to build and upload multiple flavors to Beta by Crashlytics .......................................... 912
Chapter 181: Define step value (increment) for custom RangeSeekBar ..................................... 915
Section 181.1: Define a step value of 7 ..................................................................................................................... 915
Chapter 182: Getting started with OpenGL ES 2.0+ ................................................................................. 916
Section 182.1: Setting up GLSurfaceView and OpenGL ES 2.0+ ............................................................................ 916
Section 182.2: Compiling and Linking GLSL-ES Shaders from asset file .............................................................. 916
Chapter 183: Check Data Connection ............................................................................................................. 919
Section 183.1: Check data connection ...................................................................................................................... 919
Section 183.2: Check connection using ConnectivityManager ............................................................................. 919
Section 183.3: Use network intents to perform tasks while data is allowed ........................................................ 919
Chapter 184: Java on Android ........................................................................................................................... 920
Section 184.1: Java 8 features subset with Retrolambda ...................................................................................... 920
Chapter 185: Android Java Native Interface (JNI) .................................................................................. 922
Section 185.1: How to call functions in a native library via the JNI interface ...................................................... 922
Section 185.2: How to call a Java method from native code ............................................................................... 922
Section 185.3: Utility method in JNI layer ................................................................................................................ 923
Chapter 186: Notification Channel Android O ............................................................................................ 925
Section 186.1: Notification Channel .......................................................................................................................... 925
Chapter 187: Robolectric ....................................................................................................................................... 931
Section 187.1: Robolectric test .................................................................................................................................. 931
Section 187.2: Configuration ..................................................................................................................................... 931
Chapter 188: Moshi ................................................................................................................................................... 933
Section 188.1: JSON into Java .................................................................................................................................. 933
Section 188.2: serialize Java objects as JSON ....................................................................................................... 933
Section 188.3: Built in Type Adapters ...................................................................................................................... 933
Chapter 189: Strict Mode Policy : A tool to catch the bug in the Compile Time. ...................... 935
Section 189.1: The below Code Snippet is to setup the StrictMode for Thread Policies. This Code is to be set
at the entry points to our application ............................................................................................................. 935
Section 189.2: The below code deals with leaks of memory, like it detects when in SQLLite finalize is called
or not .................................................................................................................................................................. 935
Chapter 190: Internationalization and localization (I18N and L10N) ............................................... 936
Section 190.1: Planning for localization : enable RTL support in Manifest ........................................................... 936
Section 190.2: Planning for localization : Add RTL support in Layouts ................................................................ 936
Section 190.3: Planning for localization : Test layouts for RTL ............................................................................. 937
Section 190.4: Coding for Localization : Creating default strings and resources ............................................... 937
Section 190.5: Coding for localization : Providing alternative strings .................................................................. 938
Section 190.6: Coding for localization : Providing alternate layouts .................................................................... 939
Chapter 191: Fast way to setup Retrolambda on an android project. .......................................... 940
Section 191.1: Setup and example how to use: ........................................................................................................ 940
Chapter 192: How to use SparseArray ........................................................................................................... 942
Section 192.1: Basic example using SparseArray ................................................................................................... 942
Chapter 193: Shared Element Transitions .................................................................................................... 944
Section 193.1: Shared Element Transition between two Fragments ..................................................................... 944
Chapter 194: Android Things .............................................................................................................................. 947
Section 194.1: Controlling a Servo Motor ................................................................................................................. 947
Chapter 195: Library Dagger 2: Dependency Injection in Applications ........................................ 949
Section 195.1: Create @Module Class and @Singleton annotation for Object ................................................... 949
Section 195.2: Request Dependencies in Dependent Objects .............................................................................. 949
Section 195.3: Connecting @Modules with @Inject ................................................................................................ 949
Section 195.4: Using @Component Interface to Obtain Objects .......................................................................... 950
Chapter 196: JCodec ................................................................................................................................................ 951
Section 196.1: Getting Started ................................................................................................................................... 951
Section 196.2: Getting frame from movie ............................................................................................................... 951
Chapter 197: Formatting phone numbers with pattern. ....................................................................... 952
Section 197.1: Patterns + 1 (786) 1234 5678 .............................................................................................................. 952
Chapter 198: Paint .................................................................................................................................................... 953
Section 198.1: Creating a Paint ................................................................................................................................. 953
Section 198.2: Setting up Paint for text .................................................................................................................... 953
Section 198.3: Setting up Paint for drawing shapes ............................................................................................... 954
Section 198.4: Setting flags ....................................................................................................................................... 954
Chapter 199: What is ProGuard? What is use in Android? ................................................................... 955
Section 199.1: Shrink your code and resources with proguard ............................................................................. 955
Chapter 200: Create Android Custom ROMs .............................................................................................. 957
Section 200.1: Making Your Machine Ready for Building! ..................................................................................... 957
Chapter 201: Genymotion for android ........................................................................................................... 958
Section 201.1: Installing Genymotion, the free version ........................................................................................... 958
Section 201.2: Google framework on Genymotion ................................................................................................ 959
Chapter 202: ConstraintSet ................................................................................................................................. 960
Section 202.1: ConstraintSet with ContraintLayout Programmatically ............................................................... 960
Chapter 203: CleverTap ........................................................................................................................................ 961
Section 203.1: Setting the debug level ..................................................................................................................... 961
Section 203.2: Get an instance of the SDK to record events ................................................................................ 961
Chapter 204: Publish a library to Maven Repositories ......................................................................... 962
Section 204.1: Publish .aar file to Maven ................................................................................................................. 962
Chapter 205: adb shell ........................................................................................................................................... 964
Section 205.1: Granting & revoking API 23+ permissions ...................................................................................... 964
Section 205.2: Send text, key pressed and touch events to Android Device via ADB ....................................... 964
Section 205.3: List packages .................................................................................................................................... 966
Section 205.4: Recording the display ...................................................................................................................... 966
Section 205.5: Open Developer Options ................................................................................................................. 967
Section 205.6: Set Date/Time via adb .................................................................................................................... 967
Section 205.7: Generating a "Boot Complete" broadcast .................................................................................... 968
Section 205.8: Print application data ...................................................................................................................... 968
Section 205.9: Changing file permissions using chmod command ..................................................................... 968
Section 205.10: View external/secondary storage content .................................................................................. 969
Section 205.11: kill a process inside an Android device ......................................................................................... 969
Chapter 206: Ping ICMP ......................................................................................................................................... 971
Section 206.1: Performs a single Ping ..................................................................................................................... 971
Chapter 207: AIDL ..................................................................................................................................................... 972
Section 207.1: AIDL Service ....................................................................................................................................... 972
Chapter 208: Android game development .................................................................................................. 974
Section 208.1: Game using Canvas and SurfaceView ........................................................................................... 974
Chapter 209: Android programming with Kotlin ...................................................................................... 980
Section 209.1: Installing the Kotlin plugin ................................................................................................................ 980
Section 209.2: Configuring an existing Gradle project with Kotlin ....................................................................... 981
Section 209.3: Creating a new Kotlin Activity ......................................................................................................... 982
Section 209.4: Converting existing Java code to Kotlin ........................................................................................ 983
Section 209.5: Starting a new Activity ..................................................................................................................... 983
Chapter 210: Android-x86 in VirtualBox ........................................................................................................ 984
Section 210.1: Virtual hard drive Setup for SDCARD Support ............................................................................... 984
Section 210.2: Installation in partition ...................................................................................................................... 986
Section 210.3: Virtual Machine setup ....................................................................................................................... 988
Chapter 211: Leakcanary ....................................................................................................................................... 989
Section 211.1: Implementing a Leak Canary in Android Application ..................................................................... 989
Chapter 212: Okio ...................................................................................................................................................... 990
Section 212.1: Download / Implement ..................................................................................................................... 990
Section 212.2: PNG decoder ..................................................................................................................................... 990
Section 212.3: ByteStrings and Buers ................................................................................................................... 990
Chapter 213: Bluetooth Low Energy ................................................................................................................ 992
Section 213.1: Finding BLE Devices ........................................................................................................................... 992
Section 213.2: Connecting to a GATT Server .......................................................................................................... 992
Section 213.3: Writing and Reading from Characteristics ..................................................................................... 993
Section 213.4: Subscribing to Notifications from the Gatt Server ......................................................................... 994
Section 213.5: Advertising a BLE Device .................................................................................................................. 994
Section 213.6: Using a Gatt Server ........................................................................................................................... 995
Chapter 214: Looper ................................................................................................................................................ 997
Section 214.1: Create a simple LooperThread ........................................................................................................ 997
Section 214.2: Run a loop with a HandlerThread ................................................................................................... 997
Chapter 215: Annotation Processor ................................................................................................................. 998
Section 215.1: @NonNull Annotation ........................................................................................................................ 998
Section 215.2: Types of Annotations ....................................................................................................................... 998
Section 215.3: Creating and Using Custom Annotations ....................................................................................... 998
Chapter 216: SyncAdapter with periodically do sync of data ......................................................... 1000
Section 216.1: Sync adapter with every min requesting value from server ...................................................... 1000
Chapter 217: Fastjson ........................................................................................................................................... 1010
Section 217.1: Parsing JSON with Fastjson ............................................................................................................ 1010
Section 217.2: Convert the data of type Map to JSON String ............................................................................ 1011
Chapter 218: JSON in Android with org.json ............................................................................................. 1013
Section 218.1: Creating a simple JSON object ...................................................................................................... 1013
Section 218.2: Create a JSON String with null value ............................................................................................ 1013
Section 218.3: Add JSONArray to JSONObject .................................................................................................... 1013
Section 218.4: Parse simple JSON object ............................................................................................................. 1014
Section 218.5: Check for the existence of fields on JSON ................................................................................... 1015
Section 218.6: Create nested JSON object ........................................................................................................... 1015
Section 218.7: Updating the elements in the JSON ............................................................................................. 1016
Section 218.8: Using JsonReader to read JSON from a stream ........................................................................ 1016
Section 218.9: Working with null-string when parsing json ................................................................................. 1018
Section 218.10: Handling dynamic key for JSON response ................................................................................ 1019
Chapter 219: Gson ................................................................................................................................................... 1021
Section 219.1: Parsing JSON with Gson ................................................................................................................. 1021
Section 219.2: Adding a custom Converter to Gson ............................................................................................ 1023
Section 219.3: Parsing a List<String> with Gson ................................................................................................... 1023
Section 219.4: Adding Gson to your project ......................................................................................................... 1024
Section 219.5: Parsing JSON to Generic Class Object with Gson ....................................................................... 1024
Section 219.6: Using Gson with inheritance .......................................................................................................... 1025
Section 219.7: Parsing JSON property to enum with Gson ................................................................................. 1027
Section 219.8: Using Gson to load a JSON file from disk .................................................................................... 1027
Section 219.9: Using Gson as serializer with Retrofit ........................................................................................... 1027
Section 219.10: Parsing json array to generic class using Gson ......................................................................... 1028
Section 219.11: Custom JSON Deserializer using Gson ........................................................................................ 1029
Section 219.12: JSON Serialization/Deserialization with AutoValue and Gson ................................................. 1030
Chapter 220: Android Architecture Components ................................................................................... 1032
Section 220.1: Using Lifecycle in AppCompatActivity ......................................................................................... 1032
Section 220.2: Add Architecture Components ..................................................................................................... 1032
Section 220.3: ViewModel with LiveData transformations ................................................................................. 1033
Section 220.4: Room peristence ............................................................................................................................ 1034
Section 220.5: Custom LiveData ........................................................................................................................... 1036
Section 220.6: Custom Lifecycle-aware component ........................................................................................... 1036
Chapter 221: Jackson ............................................................................................................................................ 1038
Section 221.1: Full Data Binding Example .............................................................................................................. 1038
Chapter 222: Smartcard ..................................................................................................................................... 1040
Section 222.1: Smart card send and receive ........................................................................................................ 1040
Chapter 223: Security ........................................................................................................................................... 1042
Section 223.1: Verifying App Signature - Tamper Detection .............................................................................. 1042
Chapter 224: How to store passwords securely .................................................................................... 1043
Section 224.1: Using AES for salted password encryption .................................................................................. 1043
Chapter 225: Secure SharedPreferences ................................................................................................... 1046
Section 225.1: Securing a Shared Preference ....................................................................................................... 1046
Chapter 226: Secure SharedPreferences ................................................................................................... 1047
Section 226.1: Securing a Shared Preference ....................................................................................................... 1047
Chapter 227: SQLite ............................................................................................................................................... 1048
Section 227.1: onUpgrade() method ..................................................................................................................... 1048
Section 227.2: Reading data from a Cursor ......................................................................................................... 1048
Section 227.3: Using the SQLiteOpenHelper class ............................................................................................... 1050
Section 227.4: Insert data into database .............................................................................................................. 1051
Section 227.5: Bulk insert ....................................................................................................................................... 1051
Section 227.6: Create a Contract, Helper and Provider for SQLite in Android ................................................. 1052
Section 227.7: Delete row(s) from the table ......................................................................................................... 1056
Section 227.8: Updating a row in a table ............................................................................................................. 1057
Section 227.9: Performing a Transaction ............................................................................................................. 1057
Section 227.10: Create Database from assets folder .......................................................................................... 1058
Section 227.11: Store image into SQLite ................................................................................................................ 1060
Section 227.12: Exporting and importing a database ......................................................................................... 1062
Chapter 228: Accessing SQLite databases using the ContentValues class .............................. 1064
Section 228.1: Inserting and updating rows in a SQLite database ..................................................................... 1064
Chapter 229: Firebase .......................................................................................................................................... 1065
Section 229.1: Add Firebase to Your Android Project .......................................................................................... 1065
Section 229.2: Updating a Firebase users's email ............................................................................................... 1066
Section 229.3: Create a Firebase user .................................................................................................................. 1067
Section 229.4: Change Password .......................................................................................................................... 1068
Section 229.5: Firebase Cloud Messaging ............................................................................................................ 1069
Section 229.6: Firebase Storage Operations ........................................................................................................ 1071
Section 229.7: Firebase Realtime Database: how to set/get data .................................................................... 1077
Section 229.8: Demo of FCM based notifications ................................................................................................ 1078
Section 229.9: Sign In Firebase user with email and password ......................................................................... 1088
Section 229.10: Send Firebase password reset email ......................................................................................... 1089
Section 229.11: Re-Authenticate Firebase user ..................................................................................................... 1091
Section 229.12: Firebase Sign Out ......................................................................................................................... 1092
Chapter 230: Firebase Cloud Messaging .................................................................................................... 1093
Section 230.1: Set Up a Firebase Cloud Messaging Client App on Android ...................................................... 1093
Section 230.2: Receive Messages .......................................................................................................................... 1093
Section 230.3: This code that i have implemnted in my app for pushing image,message and also link for
opening in your webView ............................................................................................................................... 1094
Section 230.4: Registration token .......................................................................................................................... 1095
Section 230.5: Subscribe to a topic ....................................................................................................................... 1096
Chapter 231: Firebase Realtime DataBase ................................................................................................ 1097
Section 231.1: Quick setup ....................................................................................................................................... 1097
Section 231.2: Firebase Realtime DataBase event handler ................................................................................ 1097
Section 231.3: Understanding firebase JSON database ..................................................................................... 1098
Section 231.4: Retrieving data from firebase ....................................................................................................... 1099
Section 231.5: Listening for child updates ............................................................................................................. 1100
Section 231.6: Retrieving data with pagination .................................................................................................... 1101
Section 231.7: Denormalization: Flat Database Structure ................................................................................... 1102
Section 231.8: Designing and understanding how to retrieve realtime data from the Firebase Database
........................................................................................................................................................................... 1104
Chapter 232: Firebase App Indexing ............................................................................................................. 1107
Section 232.1: Supporting Http URLs ..................................................................................................................... 1107
Section 232.2: Add AppIndexing API ..................................................................................................................... 1108
Chapter 233: Firebase Crash Reporting ...................................................................................................... 1110
Section 233.1: How to report an error ................................................................................................................... 1110
Section 233.2: How to add Firebase Crash Reporting to your app ................................................................... 1110
Chapter 234: Twitter APIs .................................................................................................................................. 1112
Section 234.1: Creating login with twitter button and attach a callback to it ................................................... 1112
Chapter 235: Youtube-API .................................................................................................................................. 1114
Section 235.1: Activity extending YouTubeBaseActivity ...................................................................................... 1114
Section 235.2: Consuming YouTube Data API on Android ................................................................................. 1115
Section 235.3: Launching StandAlonePlayerActivity ........................................................................................... 1117
Section 235.4: YoutubePlayerFragment in portrait Activty ................................................................................ 1118
Section 235.5: YouTube Player API ........................................................................................................................ 1120
Chapter 236: Integrate Google Sign In ........................................................................................................ 1123
Section 236.1: Google Sign In with Helper class ................................................................................................... 1123
Chapter 237: Google signin integration on android ............................................................................. 1126
Section 237.1: Integration of google Auth in your project. (Get a configuration file) ....................................... 1126
Section 237.2: Code Implementation Google SignIn ........................................................................................... 1126
Chapter 238: Google Awareness APIs .......................................................................................................... 1128
Section 238.1: Get changes for location within a certain range using Fence API ............................................. 1128
Section 238.2: Get current location using Snapshot API ..................................................................................... 1129
Section 238.3: Get changes in user activity with Fence API ................................................................................ 1129
Section 238.4: Get current user activity using Snapshot API .............................................................................. 1130
Section 238.5: Get headphone state with Snapshot API ..................................................................................... 1130
Section 238.6: Get nearby places using Snapshot API ........................................................................................ 1131
Section 238.7: Get current weather using Snapshot API ..................................................................................... 1131
Chapter 239: Google Maps API v2 for Android ........................................................................................ 1132
Section 239.1: Custom Google Map Styles ............................................................................................................ 1132
Section 239.2: Default Google Map Activity ......................................................................................................... 1143
Section 239.3: Show Current Location in a Google Map ..................................................................................... 1144
Section 239.4: Change Oset ................................................................................................................................ 1150
Section 239.5: MapView: embedding a GoogleMap in an existing layout ........................................................ 1150
Section 239.6: Get debug SHA1 fingerprint ........................................................................................................... 1152
Section 239.7: Adding markers to a map ............................................................................................................. 1153
Section 239.8: UISettings ........................................................................................................................................ 1153
Section 239.9: InfoWindow Click Listener ............................................................................................................. 1154
Section 239.10: Obtaining the SH1-Fingerprint of your certificate keystore file ............................................... 1155
Section 239.11: Do not launch Google Maps when the map is clicked (lite mode) ........................................... 1156
Chapter 240: Google Drive API ........................................................................................................................ 1157
Section 240.1: Integrate Google Drive in Android ................................................................................................ 1157
Section 240.2: Create a File on Google Drive ...................................................................................................... 1165
Chapter 241: Displaying Google Ads ............................................................................................................ 1168
Section 241.1: Adding Interstitial Ad ....................................................................................................................... 1168
Section 241.2: Basic Ad Setup ................................................................................................................................ 1169
Chapter 242: AdMob ............................................................................................................................................. 1171
Section 242.1: Implementing .................................................................................................................................. 1171
Chapter 243: Google Play Store ..................................................................................................................... 1173
Section 243.1: Open Google Play Store Listing for your app .............................................................................. 1173
Section 243.2: Open Google Play Store with the list of all applications from your publisher account .......... 1173
Chapter 244: Sign your Android App for Release ................................................................................ 1175
Section 244.1: Sign your App .................................................................................................................................. 1175
Section 244.2: Configure the build.gradle with signing configuration ............................................................... 1176
Chapter 245: TensorFlow ................................................................................................................................... 1178
Section 245.1: How to use ....................................................................................................................................... 1178
Chapter 246: Android Vk Sdk ........................................................................................................................... 1179
Section 246.1: Initialization and login ..................................................................................................................... 1179
Chapter 247: Project SDK versions ............................................................................................................... 1181
Section 247.1: Defining project SDK versions ....................................................................................................... 1181
Chapter 248: Facebook SDK for Android .................................................................................................. 1182
Section 248.1: How to add Facebook Login in Android ....................................................................................... 1182
Section 248.2: Create your own custom button for Facebook login ................................................................. 1184
Section 248.3: A minimalistic guide to Facebook login/signup implementation ............................................. 1185
Section 248.4: Setting permissions to access data from the Facebook profile ............................................... 1186
Section 248.5: Logging out of Facebook .............................................................................................................. 1186
Chapter 249: Thread ............................................................................................................................................ 1187
Section 249.1: Thread Example with its description ............................................................................................. 1187
Section 249.2: Updating the UI from a Background Thread .............................................................................. 1187
Chapter 250: AsyncTask ..................................................................................................................................... 1189
Section 250.1: Basic Usage ..................................................................................................................................... 1189
Section 250.2: Pass Activity as WeakReference to avoid memory leaks ......................................................... 1191
Section 250.3: Download Image using AsyncTask in Android ........................................................................... 1192
Section 250.4: Canceling AsyncTask .................................................................................................................... 1195
Section 250.5: AsyncTask: Serial Execution and Parallel Execution of Task .................................................... 1195
Section 250.6: Order of execution ......................................................................................................................... 1198
Section 250.7: Publishing progress ....................................................................................................................... 1198
Chapter 251: Testing UI with Espresso ......................................................................................................... 1200
Section 251.1: Overall Espresso .............................................................................................................................. 1200
Section 251.2: Espresso simple UI test .................................................................................................................. 1202
Section 251.3: Open Close DrawerLayout ............................................................................................................. 1205
Section 251.4: Set Up Espresso .............................................................................................................................. 1206
Section 251.5: Performing an action on a view .................................................................................................... 1207
Section 251.6: Finding a view with onView ............................................................................................................ 1207
Section 251.7: Create Espresso Test Class ............................................................................................................ 1207
Section 251.8: Up Navigation ................................................................................................................................. 1208
Section 251.9: Group a collection of test classes in a test suite .......................................................................... 1208
Section 251.10: Espresso custom matchers .......................................................................................................... 1209
Chapter 252: Writing UI tests - Android ...................................................................................................... 1212
Section 252.1: MockWebServer example .............................................................................................................. 1212
Section 252.2: IdlingResource ................................................................................................................................ 1214
Chapter 253: Unit testing in Android with JUnit ..................................................................................... 1218
Section 253.1: Moving Business Logic Out of Android Componenets ................................................................ 1218
Section 253.2: Creating Local unit tests ................................................................................................................ 1220
Section 253.3: Getting started with JUnit .............................................................................................................. 1221
Section 253.4: Exceptions ....................................................................................................................................... 1224
Section 253.5: Static import ................................................................................................................................... 1225
Chapter 254: Inter-app UI testing with UIAutomator .......................................................................... 1226
Section 254.1: Prepare your project and write the first UIAutomator test ........................................................ 1226
Section 254.2: Writing more complex tests using the UIAutomatorViewer ...................................................... 1226
Section 254.3: Creating a test suite of UIAutomator tests .................................................................................. 1228
Chapter 255: Lint Warnings ............................................................................................................................... 1229
Section 255.1: Using tools:ignore in xml files ........................................................................................................ 1229
Section 255.2: Configure LintOptions with gradle ............................................................................................... 1229
Section 255.3: Configuring lint checking in Java and XML source files ............................................................ 1230
Section 255.4: How to configure the lint.xml file .................................................................................................. 1230
Section 255.5: Mark Suppress Warnings .............................................................................................................. 1231
Section 255.6: Importing resources without "Deprecated" error ....................................................................... 1231
Chapter 256: Performance Optimization ................................................................................................... 1233
Section 256.1: Save View lookups with the ViewHolder pattern ......................................................................... 1233
Chapter 257: Android Kernel Optimization ............................................................................................... 1234
Section 257.1: Low RAM Configuration .................................................................................................................. 1234
Section 257.2: How to add a CPU Governor ........................................................................................................ 1234
Section 257.3: I/O Schedulers ................................................................................................................................ 1236
Chapter 258: Memory Leaks ............................................................................................................................. 1237
Section 258.1: Avoid leaking Activities with AsyncTask ....................................................................................... 1237
Section 258.2: Common memory leaks and how to fix them ............................................................................ 1238
Section 258.3: Detect memory leaks with the LeakCanary library ................................................................... 1239
Section 258.4: Anonymous callback in activities ................................................................................................. 1239
Section 258.5: Activity Context in static classes ................................................................................................... 1240
Section 258.6: Avoid leaking Activities with Listeners ......................................................................................... 1241
Section 258.7: Avoid memory leaks with Anonymous Class, Handler, Timer Task, Thread ........................... 1246
Chapter 259: Enhancing Android Performance Using Icon Fonts ................................................. 1248
Section 259.1: How to integrate Icon fonts ........................................................................................................... 1248
Section 259.2: TabLayout with icon fonts ............................................................................................................ 1250
Chapter 260: Bitmap Cache .............................................................................................................................. 1252
Section 260.1: Bitmap Cache Using LRU Cache ................................................................................................... 1252
Chapter 261: Loading Bitmaps Eectively ................................................................................................ 1253
Section 261.1: Load the Image from Resource from Android Device. Using Intents ........................................ 1253
Chapter 262: Exceptions ...................................................................................................................................... 1258
Section 262.1: ActivityNotFoundException ............................................................................................................ 1258
Section 262.2: OutOfMemoryError ........................................................................................................................ 1258
Section 262.3: Registering own Handler for unexpected exceptions ................................................................ 1258
Section 262.4: UncaughtException ........................................................................................................................ 1260
Section 262.5: NetworkOnMainThreadException ................................................................................................ 1260
Section 262.6: DexException .................................................................................................................................. 1262
Chapter 263: Logging and using Logcat ..................................................................................................... 1263
Section 263.1: Filtering the logcat output .............................................................................................................. 1263
Section 263.2: Logging ........................................................................................................................................... 1264
Section 263.3: Using the Logcat ............................................................................................................................ 1266
Section 263.4: Log with link to source directly from Logcat ............................................................................... 1267
Section 263.5: Clear logs ........................................................................................................................................ 1267
Section 263.6: Android Studio usage ..................................................................................................................... 1267
Section 263.7: Generating Logging code .............................................................................................................. 1268
Chapter 264: ADB (Android Debug Bridge) ............................................................................................... 1270
Section 264.1: Connect ADB to a device via WiFi ................................................................................................. 1270
Section 264.2: Direct ADB command to specific device in a multi-device setting ........................................... 1272
Section 264.3: Taking a screenshot and video (for kitkat only) from a device display .................................. 1272
Section 264.4: Pull (push) files from (to) the device ............................................................................................ 1273
Section 264.5: Print verbose list of connected devices ....................................................................................... 1274
Section 264.6: View logcat ..................................................................................................................................... 1274
Section 264.7: View and pull cache files of an app ............................................................................................. 1275
Section 264.8: Clear application data ................................................................................................................... 1275
Section 264.9: View an app's internal data (data/data/<sample.package.id>) on a device ......................... 1276
Section 264.10: Install and run an application ...................................................................................................... 1276
Section 264.11: Sending broadcast ........................................................................................................................ 1276
Section 264.12: Backup ........................................................................................................................................... 1277
Section 264.13: View available devices ................................................................................................................. 1278
Section 264.14: Connect device by IP .................................................................................................................... 1278
Section 264.15: Install ADB on Linux system ......................................................................................................... 1279
Section 264.16: View activity stack ........................................................................................................................ 1279
Section 264.17: Reboot device ................................................................................................................................ 1279
Section 264.18: Read device information .............................................................................................................. 1280
Section 264.19: List all permissions that require runtime grant from users on Android 6.0 ............................ 1280
Section 264.20: Turn on/o Wifi ........................................................................................................................... 1280
Section 264.21: Start/stop adb .............................................................................................................................. 1280
Chapter 265: Localization with resources in Android .......................................................................... 1281
Section 265.1: Configuration types and qualifier names for each folder under the "res" directory .............. 1281
Section 265.2: Adding translation to your Android app ...................................................................................... 1282
Section 265.3: Type of resource directories under the "res" folder ................................................................... 1284
Section 265.4: Change locale of android application programmatically ......................................................... 1284
Section 265.5: Currency .......................................................................................................................................... 1287
Chapter 266: Convert vietnamese string to english string Android ............................................. 1288
Section 266.1: example: ........................................................................................................................................... 1288
Section 266.2: Chuyển chuá»—i Tiếng Việt thĂ nh chuá»—i khĂ´ng dấu ....................................................................... 1288
Credits .......................................................................................................................................................................... 1289
You may also like ................................................................................................................................................... 1301
GoalKicker.com – Android™ Notes for Professionals 1
About
Please feel free to share this PDF with anyone for free,
latest version of this book can be downloaded from:
https://goalkicker.com/AndroidBook
This Android™ Notes for Professionals book is compiled from Stack Overflow
Documentation, the content is written by the beautiful people at Stack Overflow.
Text content is released under Creative Commons BY-SA, see credits at the end
of this book whom contributed to the various chapters. Images may be copyright
of their respective owners unless otherwise specified
This is an unofficial free book created for educational purposes and is not
affiliated with official Android™ group(s) or company(s) nor Stack Overflow. All
trademarks and registered trademarks are the property of their respective
company owners
The information presented in this book is not guaranteed to be correct nor
accurate, use at your own risk
Please send feedback and corrections to web@petercv.com
GoalKicker.com – Android™ Notes for Professionals 2
Chapter 1: Getting started with Android
Version API Level Version Code Release Date
1.0 1 BASE 2008-09-23
1.1 2 BASE_1_1 2009-02-09
1.5 3 CUPCAKE 2009-04-27
1.6 4 DONUT 2009-09-15
2.0 5 ECLAIR 2009-10-26
2.0.1 6 ECLAIR_0_1 2009-12-03
2.1.x 7 ECLAIR_MR1 2010-01-12
2.2.x 8 FROYO 2010-05-20
2.3 9 GINGERBREAD 2010-12-06
2.3.3 10 GINGERBREAD_MR1 2011-02-09
3.0.x 11 HONEYCOMB 2011-02-22
3.1.x 12 HONEYCOMB_MR1 2011-05-10
3.2.x 13 HONEYCOMB_MR2 2011-07-15
4.0 14 ICE_CREAM_SANDWICH 2011-10-18
4.0.3 15 ICE_CREAM_SANDWICH_MR1 2011-12-16
4.1 16 JELLY_BEAN 2012-07-09
4.2 17 JELLY_BEAN_MR1 2012-11-13
4.3 18 JELLY_BEAN_MR2 2013-07-24
4.4 19 KITKAT 2013-10-31
4.4W 20 KITKAT_WATCH 2014-06-25
5.0 21 LOLLIPOP 2014-11-12
5.1 22 LOLLIPOP_MR1 2015-03-09
6.0 23 M (Marshmallow) 2015-10-05
7.0 24 N (Nougat) 2016-08-22
7.1 25 N_MR1 (Nougat MR1) 2016-10-04
8.0 26 O (Developer Preview 4) 2017-07-24
Section 1.1: Creating a New Project
Set up Android Studio
Start by setting up Android Studio and then open it. Now, you're ready to make your first Android App!
Note: this guide is based on Android Studio 2.2, but the process on other versions is mainly the same.
Configure Your Project
Basic Configuration
You can start a new project in two ways:
Click Start a New Android Studio Project from the welcome screen.
Navigate to File → New Project if you already have a project open.
Next, you need to describe your application by filling out some fields:
GoalKicker.com – Android™ Notes for Professionals 3
1. Application Name - This name will be shown to the user.
Example: Hello World. You can always change it later in AndroidManifest.xml file.
2. Company Domain - This is the qualifier for your project's package name.
Example: stackoverflow.com.
3. Package Name (aka applicationId) - This is the fully qualified project package name.
It should follow Reverse Domain Name Notation (aka Reverse DNS): Top Level Domain . Company Domain .
[Company Segment .] Application Name.
Example: com.stackoverflow.android.helloworld or com.stackoverflow.helloworld. You can always
change your applicationId by overriding it in your gradle file.
Don't use the default prefix "com.example" unless you don't intend to submit your application to the
Google Play Store. The package name will be your unique applicationId in Google Play.
4. Project Location - This is the directory where your project will be stored.
GoalKicker.com – Android™ Notes for Professionals 4
Select Form Factors and API Level
The next window lets you select the form factors supported by your app, such as phone, tablet, TV, Wear, and
Google Glass. The selected form factors become the app modules within the project. For each form factor, you can
also select the API Level for that app. To get more information, click Help me choose
GoalKicker.com – Android™ Notes for Professionals 5
Chart of the current Android version distributions, shown when you click Help me choose.
The Android Platform Distribution window shows the distribution of mobile devices running each version of
Android, as shown in Figure 2. Click on an API level to see a list of features introduced in the corresponding version
of Android. This helps you choose the minimum API Level that has all the features that your apps needs, so you can
reach as many devices as possible. Then click OK.
Now, choose what platforms and version of Android SDK the application will support.
GoalKicker.com – Android™ Notes for Professionals 6
For now, select only Phone and Tablet.
The Minimum SDK is the lower bound for your app. It is one of the signals the Google Play Store uses to
determine which devices an app can be installed on. For example, Stack Exchange's app supports Android 4.1+.
Android Studio will tell you (approximately) what percentage of devices will be supported given the specified
minimum SDK.
GoalKicker.com – Android™ Notes for Professionals 7
Lower API levels target more devices but have fewer features available.
When deciding on the Minimum SDK, you should consider the Dashboards stats, which will give you version
information about the devices that visited the Google Play Store globally in the last week.
From: Dashboards on Android Developer website.
Add an activity
Now we are going to select a default activity for our application. In Android, an Activity is a single screen that will
be presented to the user. An application can house multiple activities and navigate between them. For this
example, choose Empty Activity and click next.
Here, if you wish, you can change the name of the activity and layout. A good practice is to keep Activity as a suffix
for the activity name, and activity_ as a prefix for the layout name. If we leave these as the default, Android
Studio will generate an activity for us called MainActivity, and a layout file called activity_main. Now click Finish.
Android Studio will create and configure our project, which can take some time depending on the system.
Inspecting the Project
To understand how Android works, let's take a look at some of the files that were created for us.
On the left pane of Android Studio, we can see the structure of our Android application.
GoalKicker.com – Android™ Notes for Professionals 8
First, let's open AndroidManifest.xml by double clicking it. The Android manifest file describes some of the basic
information about an Android application. It contains the declaration of our activities, as well as some more
advanced components.
If an application needs access to a feature protected by a permission, it must declare that it requires that
permission with a <uses-permission> element in the manifest. Then, when the application is installed on the
device, the installer determines whether or not to grant the requested permission by checking the authorities that
signed the application's certificates and, in some cases, asking the user. An application can also protect its own
components (activities, services, broadcast receivers, and content providers) with permissions. It can employ any of
the permissions defined by Android (listed in android.Manifest.permission) or declared by other applications. Or it
can define its own.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.stackoverflow.helloworld">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
GoalKicker.com – Android™ Notes for Professionals 9
</application>
</manifest>
Next, let's open activity_main.xml which is located in app/src/main/res/layout/. This file contains declarations
for the visual components of our MainActivity. You will see visual designer. This allows you to drag and drop
elements onto the selected layout.
You can also switch to the xml layout designer by clicking "Text" at the bottom of Android Studio, as seen here:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.stackexchange.docs.helloworld.MainActivity">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</RelativeLayout>
You will see a widget called a TextView inside of this layout, with the android:text property set to "Hello World!".
This is a block of text that will be shown to the user when they run the application.
You can read more about Layouts and attributes.
Next, let's take a look at MainActivity. This is the Java code that has been generated for MainActivity.
public class MainActivity extends AppCompatActivity {
// The onCreate method is called when an Activity starts
GoalKicker.com – Android™ Notes for Professionals 10
// This is where we will set up our layout
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// setContentView sets the Activity's layout to a specified XML layout
// In our case we are using the activity_main layout
setContentView(R.layout.activity_main);
}
}
As defined in our Android manifest, MainActivity will launch by default when a user starts the HelloWorld app.
Lastly, open up the file named build.gradle located in app/.
Android Studio uses the build system Gradle to compile and build Android applications and libraries.
apply plugin: 'com.android.application'
android {
signingConfigs {
applicationName {
keyAlias 'applicationName'
keyPassword 'password'
storeFile file('../key/applicationName.jks')
storePassword 'anotherPassword'
}
}
compileSdkVersion 26
buildToolsVersion "26.0.0"
defaultConfig {
applicationId "com.stackexchange.docs.helloworld"
minSdkVersion 16
targetSdkVersion 26
versionCode 1
versionName "1.0"
signingConfig signingConfigs.applicationName
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:26.0.0'
}
This file contains information about the build and your app version, and you can also use it to add dependencies to
external libraries. For now, let's not make any changes.
It is advisable to always select the latest version available for the dependencies:
buildToolsVersion: 26.0.0
com.android.support:appcompat-v7: 26.0.0 (July 2017)
firebase: 11.0.4 (August 2017)
GoalKicker.com – Android™ Notes for Professionals 11
compileSdkVersion
compileSdkVersion is your way to tell Gradle what version of the Android SDK to compile your app with. Using the
new Android SDK is a requirement to use any of the new APIs added in that level.
It should be emphasized that changing your compileSdkVersion does not change runtime behavior. While new
compiler warnings/errors may be present when changing your compileSdkVersion, your compileSdkVersion is not
included in your APK: it is purely used at compile time.
Therefore it is strongly recommended that you always compile with the latest SDK. You’ll get all the benefits of new
compilation checks on existing code, avoid newly deprecated APIs, and be ready to use new APIs.
minSdkVersion
If compileSdkVersion sets the newest APIs available to you, minSdkVersion is the lower bound for your app. The
minSdkVersion is one of the signals the Google Play Store uses to determine which of a user’s devices an app can
be installed on.
It also plays an important role during development: by default lint runs against your project, warning you when you
use any APIs above your minSdkVersion, helping you avoid the runtime issue of attempting to call an API that
doesn’t exist. Checking the system version at runtime is a common technique when using APIs only on newer
platform versions.
targetSdkVersion
targetSdkVersion is the main way Android provides forward compatibility by not applying behavior changes unless
the targetSdkVersion is updated. This allows you to use new APIs prior to working through the behavior changes.
Updating to target the latest SDK should be a high priority for every app. That doesn’t mean you have to use every
new feature introduced nor should you blindly update your targetSdkVersion without testing.
targetSDKVersion is the version of Android which is the upper-limit for the available tools. If targetSDKVersion is
less than 23, the app does not need to request permissions at runtime for an instance, even if the app is being run
on API 23+. TargetSDKVersion does not prevent android versions above the picked Android version from running
the app.
You can find more info about the Gradle plugin:
A basic example
Introduction to the Gradle plugin for android and the wrapper
Introduction to the configuration of the build.gradle and the DSL methods
Running the Application
Now, let's run our HelloWorld application. You can either run an Android Virtual Device (which you can set up by
using the AVD Manager in Android Studio, as described in the example below) or connect your own Android device
through a USB cable.
Setting up an Android device
To run an application from Android Studio on your Android Device, you must enable USB Debugging in the
Developer Options in the settings of your device.
Settings > Developer options > USB debugging
If Developer Options is not visible in the settings, navigate to About Phone and tap on the Build Number seven
GoalKicker.com – Android™ Notes for Professionals 12
times. This will enable Developer Options to show up in your settings.
Settings > About phone > Build number
You also might need to change build.gradle configuration to build on a version that your device has.
Running from Android Studio
Click the green Run button from the toolbar at the top of Android Studio. In the window that appears, select
whichever device you would like to run the app on (start an Android Virtual Device if necessary, or see Setting up an
AVD (Android Virtual Device) if you need to set one up) and click OK.
On devices running Android 4.4 (KitKat) and possibly higher, a pop-up will be shown to authorize USB debugging.
Click OK to accept.
The application will now install and run on your Android device or emulator.
APK file location
When you prepare your application for release, you configure, build, and test a release version of your application.
The configuration tasks are straightforward, involving basic code cleanup and code modification tasks that help
optimize your application. The build process is similar to the debug build process and can be done using JDK and
Android SDK tools. The testing tasks serve as a final check, ensuring that your application performs as expected
under real-world conditions. When you are finished preparing your application for release you have a signed APK
file, which you can distribute directly to users or distribute through an application marketplace such as Google Play.
Android Studio
Since in the above examples Gradle is used, the location of the generated APK file is: <Your Project
Location>/app/build/outputs/apk/app-debug.apk
IntelliJ
If you are a user of IntelliJ before switching to Studio, and are importing your IntelliJ project directly, then nothing
changed. The location of the output will be the same under:
out/production/...
Note: this is will become deprecated sometimes around 1.0
Eclipse
If you are importing Android Eclipse project directly, do not do this! As soon as you have dependencies in your
project (jars or Library Projects), this will not work and your project will not be properly setup. If you have no
dependencies, then the apk would be under the same location as you'd find it in Eclipse:
bin/...
GoalKicker.com – Android™ Notes for Professionals 13
Section 1.2: Setting up Android Studio
Android Studio is the Android development IDE that is officially supported and recommended by Google. Android
Studio comes bundled with the Android SDK Manager, which is a tool to download the Android SDK components
required to start developing apps.
Installing Android Studio and Android SDK tools:
1. Download and install Android Studio.
2. Download the latest SDK Tools and SDK Platform-tools by opening the Android Studio, and then following the
Android SDK Tool Updates instructions. You should install the latest available stable packages.
If you need to work on old projects that were built using older SDK versions, you may need to download these
versions as well
Since Android Studio 2.2, a copy of the latest OpenJDK comes bundled with the install and is the recommended JDK
(Java Development Kit) for all Android Studio projects. This removes the requirement of having Oracle's JDK package
installed. To use the bundled SDK, proceed as follows;
1. Open your project in Android Studio and select File > Project Structure in the menu bar.
2. In the SDK Location page and under JDK location, check the Use embedded JDK checkbox.
3. Click OK.
Configure Android Studio
Android Studio provides access to two configuration files through the Help menu:
studio.vmoptions: Customize options for Studio's Java Virtual Machine (JVM), such as heap size and cache
size. Note that on Linux machines this file may be named studio64.vmoptions, depending on your version of
Android Studio.
idea.properties: Customize Android Studio properties, such as the plugins folder path or maximum
supported file size.
Change/add theme
You can change it as your preference.File->Settings->Editor->Colors & Fonts-> and select a theme.Also you
can download new themes from http://color-themes.com/ Once you have downloaded the .jar.zip file, go to File
-> Import Settings... and choose the file downloaded.
Compiling Apps
Create a new project or open an existing project in Android Studio and press the green Play button on the top
toolbar to run it. If it is gray you need to wait a second to allow Android Studio to properly index some files, the
progress of which can be seen in the bottom status bar.
If you want to create a project from the shell make sure that you have a local.properties file, which is created by
Android Studio automatically. If you need to create the project without Android Studio you need a line starting with
sdk.dir= followed by the path to your SDK installation.
Open a shell and go into the project's directory. Enter ./gradlew aR and press enter. aR is a shortcut for
assembleRelease, which will download all dependencies for you and build the app. The final APK file will be in
ProjectName/ModuleName/build/outputs/apk and will been called ModuleName-release.apk.
GoalKicker.com – Android™ Notes for Professionals 14
Section 1.3: Android programming without an IDE
This is a minimalist Hello World example that uses only the most basic Android tools.
Requirements and assumptions
Oracle JDK 1.7 or later
Android SDK Tools (just the command line tools)
This example assumes Linux. You may have to adjust the syntax for your own platform.
Setting up the Android SDK
After unpacking the SDK release:
1. Install additional packages using the SDK manager. Don't use android update sdk --no-ui as instructed in
the bundled Readme.txt; it downloads some 30 GB of unnecessary files. Instead use the interactive SDK
manager android sdk to get the recommended minimum of packages.
2. Append the following JDK and SDK directories to your execution PATH. This is optional, but the instructions
below assume it.
JDK/bin
SDK/platform-tools
SDK/tools
SDK/build-tools/LATEST (as installed in step 1)
3. Create an Android virtual device. Use the interactive AVD Manager (android avd). You might have to fiddle a
bit and search for advice; the on-site instructions aren't always helpful.
(You can also use your own device)
4. Run the device:
emulator -avd DEVICE
5. If the device screen appears to be locked, then swipe to unlock it.
Leave it running while you code the app.
Coding the app
0. Change to an empty working directory.
1. Make the source file:
mkdir --parents src/dom/domain
touch src/dom/domain/SayingHello.java
Content:
package dom.domain;
import android.widget.TextView;
GoalKicker.com – Android™ Notes for Professionals 15
public final class SayingHello extends android.app.Activity
{
protected @Override void onCreate( final android.os.Bundle activityState )
{
super.onCreate( activityState );
final TextView textV = new TextView( SayingHello.this );
textV.setText( "Hello world" );
setContentView( textV );
}
}
2. Add a manifest:
touch AndroidManifest.xml
Content:
<?xml version='1.0'?>
<manifest xmlns:a='http://schemas.android.com/apk/res/android'
package='dom.domain' a:versionCode='0' a:versionName='0'>
<application a:label='Saying hello'>
<activity a:name='dom.domain.SayingHello'>
<intent-filter>
<category a:name='android.intent.category.LAUNCHER'/>
<action a:name='android.intent.action.MAIN'/>
</intent-filter>
</activity>
</application>
</manifest>
3. Make a sub-directory for the declared resources:
mkdir res
Leave it empty for now.
Building the code
0. Generate the source for the resource declarations. Substitute here the correct path to your SDK, and the
installed API to build against (e.g. "android-23"):
aapt package -f \\
-I SDK/platforms/android-API/android.jar \\
-J src -m \\
-M AndroidManifest.xml -S res -v
Resource declarations (described further below) are actually optional. Meantime the above call does nothing
if res/ is still empty.
1. Compile the source code to Java bytecode (.java → .class):
javac \\
-bootclasspath SDK/platforms/android-API/android.jar \\
-classpath src -source 1.7 -target 1.7 \\
src/dom/domain/*.java
GoalKicker.com – Android™ Notes for Professionals 16
2. Translate the bytecode from Java to Android (.class → .dex):
First using Jill (.class → .jayce):
java -jar SDK/build-tools/LATEST/jill.jar \\
--output classes.jayce src
Then Jack (.jayce → .dex):
java -jar SDK/build-tools/LATEST/jack.jar \\
--import classes.jayce --output-dex .
Android bytecode used to be called "Dalvik executable code", and so "dex".
You could replace steps 11 and 12 with a single call to Jack if you like; it can compile directly from Java source
(.java → .dex). But there are advantages to compiling with javac. It's a better known, better documented and
more widely applicable tool.
3. Package up the resource files, including the manifest:
aapt package -f \\
-F app.apkPart \\
-I SDK/platforms/android-API/android.jar \\
-M AndroidManifest.xml -S res -v
That results in a partial APK file (Android application package).
4. Make the full APK using the ApkBuilder tool:
java -classpath SDK/tools/lib/sdklib.jar \\
com.android.sdklib.build.ApkBuilderMain \\
app.apkUnalign \\
-d -f classes.dex -v -z app.apkPart
It warns, "THIS TOOL IS DEPRECATED. See --help for more information." If --help fails with an
ArrayIndexOutOfBoundsException, then instead pass no arguments:
java -classpath SDK/tools/lib/sdklib.jar \\
com.android.sdklib.build.ApkBuilderMain
It explains that the CLI (ApkBuilderMain) is deprecated in favour of directly calling the Java API (ApkBuilder).
(If you know how to do that from the command line, please update this example.)
5. Optimize the data alignment of the APK (recommended practice):
zipalign -f -v 4 app.apkUnalign app.apk
Installing and running
0. Install the app to the Android device:
GoalKicker.com – Android™ Notes for Professionals 17
adb install -r app.apk
1. Start the app:
adb shell am start -n dom.domain/.SayingHello
It should run and say hello.
That's all. That's what it takes to say hello using the basic Android tools.
Declaring a resource
This section is optional. Resource declarations aren't required for a simple "hello world" app. If they aren't required
for your app either, then you could streamline the build somewhat by omitting step 10, and removing the reference
to the res/ directory from step 13.
Otherwise, here's a brief example of how to declare a resource, and how to reference it.
0. Add a resource file:
mkdir res/values
touch res/values/values.xml
Content:
<?xml version='1.0'?>
<resources>
<string name='appLabel'>Saying hello</string>
</resources>
1. Reference the resource from the XML manifest. This is a declarative style of reference:
<!-- <application a:label='Saying hello'> -->
<application a:label='@string/appLabel'>
2. Reference the same resource from the Java source. This is an imperative reference:
// v.setText( "Hello world" );
v.setText( "This app is called "
+ getResources().getString( R.string.appLabel ));
3. Test the above modifications by rebuilding, reinstalling and re-running the app (steps 10-17).
It should restart and say, "This app is called Saying hello".
Uninstalling the app
adb uninstall dom.domain
See also
original question - The original question that prompted this example
working example - A working build script that uses the above commands
GoalKicker.com – Android™ Notes for Professionals 18
Section 1.4: Application Fundamentals
Android Apps are written in Java. The Android SDK tools compile the code, data and resource files into an APK
(Android package). Generally, one APK file contains all the content of the app.
Each app runs on its own virtual machine(VM) so that app can run isolated from other apps. Android system works
with the principle of least privilege. Each app only has access to the components which it requires to do its work,
and no more. However, there are ways for an app to share data with other apps, such as by sharing Linux user id
between app, or apps can request permission to access device data like SD card, contacts etc.
App Components
App components are the building blocks of an Android app. Each components plays a specific role in an Android
app which serves a distinct purpose and has distinct life-cycles(the flow of how and when the component is created
and destroyed). Here are the four types of app components:
1. Activities: An activity represents a single screen with a User Interface(UI). An Android app may have more
than one activity. (e.g. an email app might have one activity to list all the emails, another to show the
contents of each email, and another to compose new email.) All the activities in an App work together to
create a User eXperience (UX).
2. Services: A service runs in the background to perform long-running operations or to perform work for a
remote processes. A service does not provide any UI, it runs only in the background with the User's input.
(e.g. a service can play music in the background while the user is in a different App, or it might download data
from the internet without blocking user's interaction with the Android device.)
3. Content Providers: A content provider manages shared app data. There are four ways to store data in an
app: it can be written to a file and stored in the file system, inserted or updated to a SQLite database, posted
to the web, or saved in any other persistent storage location the App can access. Through content providers,
other Apps can query or even modify the data. (e.g. Android system provides a content provider that
manages the user's contact information so that any app which has permission can query the contacts.)
Content providers can also be used to save the data which is private to the app for better data integrity.
4. Broadcast receivers: A broadcast receiver responds to the system-wide broadcasts of announcements (e.g.
a broadcast announcing that the screen has turned off, the battery is low, etc.) or from Apps (e.g. to let other
apps know that some data has been downloaded to the device and is available for them to use). Broadcast
receivers don't have UIs but they can show notification in the status bar to alert the user. Usually broadcast
receivers are used as a gateway to other components of the app, consisting mostly of activities and services.
One unique aspect of the Android system is that any app can start another app's component (e.g. if you want to
make call, send SMS, open a web page, or view a photo, there is an app which already does that and your app can
make use of it, instead of developing a new activity for the same task).
When the system starts a component, it starts the process for that app (if it isn't already running, i.e. only one
foreground process per app can run at any given time on an Android system) and instantiates the classes needed
for that component. Thus the component runs on the process of that App that it belongs to. Therefore, unlike apps
on other systems, Android apps don't have a single entry point(there is no main() method).
Because the system runs each app in a separate process, one app cannot directly activate another app's
components, however the Android system can. Thus to start another app's component, one app must send a
message to the system that specifies an intent to start that component, then the system will start that component.
Context
Instances of the class android.content.Context provide the connection to the Android system which executes the
application. Instance of Context is required to get access to the resources of the project and the global information
GoalKicker.com – Android™ Notes for Professionals 19
about the app's environment.
Let's have an easy to digest example: Consider you are in a hotel, and you want to eat something. You call roomservice
and ask them to bring you things or clean up things for you. Now think of this hotel as an Android app,
yourself as an activity, and the room-service person is then your context, which provides you access to the hotel
resources like room-service, food items etc.
Yet an other example, You are in a restaurant sitting on a table, each table has an attendant, when ever you want to
order food items you ask the attendant to do so. The attendant then places your order and your food items gets
served on your table. Again in this example, the restaurant is an Android App, the tables or the customers are App
components, the food items are your App resources and the attendant is your context thus giving you a way to
access the resources like food items.
Activating any of the above components requires the context's instance. Not just only the above, but almost every
system resource: creation of the UI using views(discussed later), creating instance of system services, starting new
activities or services -- all require context.
More detailed description is written here.
Section 1.5: Setting up an AVD (Android Virtual Device)
TL;DR It basically allows us to simulate real devices and test our apps without a real device.
According to Android Developer Documentation,
an Android Virtual Device (AVD) definition lets you define the characteristics of an Android Phone, Tablet,
Android Wear, or Android TV device that you want to simulate in the Android Emulator. The AVD Manager
helps you easily create and manage AVDs.
To set up an AVD, follow these steps:
1. Click this button to bring up the AVD Manager:
2. You should see a dialog like this:
GoalKicker.com – Android™ Notes for Professionals 20
3. Now click the + Create Virtual Device... button. This will bring up Virtual Device Configuration Dialog:
GoalKicker.com – Android™ Notes for Professionals 21
4. Select any device you want, then click Next:
5. Here you need to choose an Android version for your emulator. You might also need to download it first by
clicking Download. After you've chosen a version, click Next.
GoalKicker.com – Android™ Notes for Professionals 22
6. Here, enter a name for your emulator, initial orientation, and whether you want to display a frame around it.
After you chosen all these, click Finish.
7. Now you got a new AVD ready for launching your apps on it.
GoalKicker.com – Android™ Notes for Professionals 23
Chapter 2: Android Studio
Section 2.1: Setup Android Studio
System Requirements
Microsoft® Windows® 8/7/Vista/2003 (32 or 64-bit).
Mac® OS X® 10.8.5 or higher, up to 10.9 (Mavericks)
GNOME or KDE desktop
Installation
Window
1. Download and install JDK (Java Development Kit) version 8
2. Download Android Studio
3. Launch Android Studio.exe then mention JDK path and download the latest SDK
Linux
1. Download and install JDK (Java Development Kit) version 8
2. Download Android Studio
3. Extract the zip file
4. Open terminal, cd to the extracted folder, cd to bin (example cd android-studio/bin)
5. Run ./studio.sh
Section 2.2: View And Add Shortcuts in Android Studio
By going to Settings >> Keymap A window will popup showing All the Editor Actions with the their name and
shortcuts. Some of the Editor Actions do not have shortcuts. So right click on that and add a new shortcut to that.
Check the image below
GoalKicker.com – Android™ Notes for Professionals 24
Section 2.3: Android Studio useful shortcuts
The following are some of the more common/useful shortcuts.
These are based on the default IntelliJ shortcut map. You can switch to other common IDE shortcut maps via File
-> Settings -> Keymap -> <Choose Eclipse/Visual Studio/etc from Keymaps dropdown>
Action Shortcut
Format code CTRL + ALT + L
Add unimplemented methods CTRL + I
Show logcat ALT + 6
Build CTRL + F9
Build and Run CTRL + F10
Find CTRL + F
Find in project CTRL + SHIFT + F
Find and replace CTRL + R
Find and replace in project CTRL + SHIFT + R
Override methods CTRL + O
Show project ALT + 1
Hide project - logcat SHIFT + ESC
Collapse all CTRL + SHIFT + NumPad +
View Debug Points CTRL + SHIFT + F8
Expand all CTRL + SHIFT + NumPad -
Open Settings ALT + s
GoalKicker.com – Android™ Notes for Professionals 25
Select Target (open current file in Project view) ALT + F1 → ENTER
Search Everywhere SHIFT → SHIFT (Double shift)
Code | Surround With CTRL → ALT + T
Create method form selected code ALT + CTRL
Refactor:
Action Shortcut
Refactor This (menu/picker for all applicable
refactor actions of the current element) Mac CTRL + T - Win/Linux CTRL + ALT + T
Rename SHIFT + F6
Extract Method Mac CMD + ALT + M - Win/Linux CTRL + ALT + M
Extract Parameter Mac CMD + ALT + P - Win/Linux CTRL + ALT + P
Extract Variable Mac CMD + ALT + V - Win/Linux CTRL + ALT + V
Section 2.4: Android Studio Improve performance tip
Enable Offline Work:
1. Click File -> Settings. Search for "gradle" and click in Offline work box.
2. Go to Compiler (in same settings dialog just below Gradle) and add --offline to Command-line Options text
box.
Improve Gradle Performance
Add following two line of code in your gradle.properties file.
org.gradle.daemon=true
org.gradle.parallel=true
Increasing the value of -Xmx and -Xms in studio.vmoptions file
-Xms1024m
-Xmx4096m
-XX:MaxPermSize=1024m
-XX:ReservedCodeCacheSize=256m
-XX:+UseCompressedOops
Window
%USERPROFILE%.{FOLDER_NAME}\studio.exe.vmoptions and/or
%USERPROFILE%.{FOLDER_NAME}\studio64.exe.vmoptions
Mac
~/Library/Preferences/{FOLDER_NAME}/studio.vmoptions
Linux
~/.{FOLDER_NAME}/studio.vmoptions and/or ~/.{FOLDER_NAME}/studio64.vmoptions
GoalKicker.com – Android™ Notes for Professionals 26
Section 2.5: Gradle build project takes forever
Android Studio -> Preferences -> Gradle -> Tick Offline work and then restart your Android studio.
Reference screenshot:
Section 2.6: Enable/Disable blank line copy
ctrl + alt + shift + / (cmd + alt + shift + / on MacOS) should show you the following dialog:
Clicking on Registry you will get
GoalKicker.com – Android™ Notes for Professionals 27
The key you want to enable/disable is
editor.skip.copy.and.cut.for.empty.selection
Tested on Linux Ubuntu and MacOS.
Section 2.7: Custom colors of logcat message based on
message importance
Go to File -> Settings -> Editor -> Colors & Fonts -> Android Logcat
Change the colors as you need:
GoalKicker.com – Android™ Notes for Professionals 28
Choose the appropriate color:
Section 2.8: Filter logs from UI
Android logs can be filtered directly from the UI. Using this code
GoalKicker.com – Android™ Notes for Professionals 29
public class MainActivity extends AppCompatActivity {
private final static String TAG1 = MainActivity.class.getSimpleName();
private final static String TAG2 = MainActivity.class.getCanonicalName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Log.e(TAG1,"Log from onCreate method with TAG1");
Log.i(TAG2,"Log from onCreate method with TAG2");
}
}
If I use the regex TAG1|TAG2 and the level verbose I get
01-14 10:34:46.961 12880-12880/android.doc.so.thiebaudthomas.sodocandroid E/MainActivity: Log from
onCreate method with TAG1
01-14 10:34:46.961 12880-12880/android.doc.so.thiebaudthomas.sodocandroid
I/androdi.doc.so.thiebaudthomas.sodocandroid.MainActivity: Log from onCreate method with TAG2
The level can be set to get logs with given level and above. For example the verbose level will catch verbose,
debug, info, warn, error and assert logs.
Using the same example, if I set the level to error, I only get
01-14 10:34:46.961 12880-12880/androdi.doc.so.thiebaudthomas.sodocandroid E/MainActivity: Log from
onCreate method with TAG1
Section 2.9: Create filters configuration
Custom filters can be set and save from the UI. In the AndroidMonitor tab, click on the right dropdown (must
contains Show only selected application or No filters) and select Edit filter configuration.
Enter the filter you want
GoalKicker.com – Android™ Notes for Professionals 30
And use it (you can selected it from the same dropdown)
Important If you add an input in the filter bar, android studio will consider both your filter and your input.
With both input and filter there is no output
Without filter, there is some outputs
Section 2.10: Create assets folder
Right click in MAIN folder > New > Folder > Assets Folder.
Assets folder will be under MAIN folder with the same symbol as RES folder.
In this example I put a font file.
GoalKicker.com – Android™ Notes for Professionals 31
GoalKicker.com – Android™ Notes for Professionals 32
Chapter 3: Instant Run in Android Studio
Section 3.1: Enabling or disabling Instant Run
1. Open the Settings or Preferences dialog:
On Windows or Linux, select File > Settings from the main menu.
On Mac OSX, select Android Studio > Preferences from the main menu.
2. Navigate to Build, Execution, Deployment > Compiler.
3. In the text field next to Command-line Options, enter your command-line options.
4. Click OK to save and exit.
The top option is Instant run. Check/uncheck that box.
Documentation
Section 3.2: Types of code Swaps in Instant Run
There are three types of code swaps that Instant run enables to support faster debugging and running app from
your code in Android Studio.
Hot Swap
Warm Swap
Cold Swap
When are each of these swaps triggered?
GoalKicker.com – Android™ Notes for Professionals 33
HOT SWAP is triggered when an existing method's implementation is changed.
WARM SWAP is triggered when an existing resource is changed or removed (anything in the res folder)
COLD SWAP whenever there is a structural code change in your app's code e.g.
1. Add, remove, or change:
an annotation
an instance field
a static field
a static method signature
an instance method signature
2. Change which parent class the current class inherits from
3. Change the list of implemented interfaces
4. Change a class's static initializer
5. Reorder layout elements that use dynamic resource IDs
What happens when a code swap happens?
HOT SWAP changes are visible instantly - as soon as the next call to the method whose implementation is changed
is made.
WARM SWAP restarts the current activity
COLD SWAP restarts the entire app (without reinstall)
Section 3.3: Unsupported code changes when using Instant
Run
There are a few changes where instant won't do its trick and a full build and reinstall fo your app will happen just
like it used to happen before Instant Run was born.
1. Change the app manifest
2. Change resources referenced by the app manifest
3. Change an Android widget UI element (requires a Clean and Rerun)
Documentation
GoalKicker.com – Android™ Notes for Professionals 34
Chapter 4: TextView
Everything related to TextView customization in Android SDK
Section 4.1: Spannable TextView
A spannable TextView can be used in Android to highlight a particular portion of text with a different color, style,
size, and/or click event in a single TextView widget.
Consider that you have defined a TextView as follows:
TextView textview=findViewById(R.id.textview);
Then you can apply different highlighting to it as shown below:
Spannable color: In order to set a different color to some portion of text, a ForegroundColorSpan can be
used, as shown in the following example:
Spannable spannable = new SpannableString(firstWord+lastWord);
spannable.setSpan(new ForegroundColorSpan(firstWordColor), 0, firstWord.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan(new ForegroundColorSpan(lastWordColor), firstWord.length(),
firstWord.length()+lastWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textview.setText( spannable );
Output created by the code above:
Spannable font: In order to set a different font size to some portion of text, a RelativeSizeSpan can be
used, as shown in the following example:
Spannable spannable = new SpannableString(firstWord+lastWord);
spannable.setSpan(new RelativeSizeSpan(1.1f),0, firstWord.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // set size
spannable.setSpan(new RelativeSizeSpan(0.8f), firstWord.length(), firstWord.length() +
lastWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); // set size
textview.setText( spannable );
Output created by the code above:
Spannable typeface: In order to set a different font typeface to some portion of text, a custom
TypefaceSpan can be used, as shown in the following example:
Spannable spannable = new SpannableString(firstWord+lastWord);
GoalKicker.com – Android™ Notes for Professionals 35
spannable.setSpan( new CustomTypefaceSpan("SFUIText-Bold.otf",fontBold), 0,
firstWord.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
spannable.setSpan( new CustomTypefaceSpan("SFUIText-Regular.otf",fontRegular),
firstWord.length(), firstWord.length() + lastWord.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
text.setText( spannable );
However, in order to make the above code working, the class CustomTypefaceSpan has to be derived from
the class TypefaceSpan. This can be done as follows:
public class CustomTypefaceSpan extends TypefaceSpan {
private final Typeface newType;
public CustomTypefaceSpan(String family, Typeface type) {
super(family);
newType = type;
}
@Override
public void updateDrawState(TextPaint ds) {
applyCustomTypeFace(ds, newType);
}
@Override
public void updateMeasureState(TextPaint paint) {
applyCustomTypeFace(paint, newType);
}
private static void applyCustomTypeFace(Paint paint, Typeface tf) {
int oldStyle;
Typeface old = paint.getTypeface();
if (old == null) {
oldStyle = 0;
} else {
oldStyle = old.getStyle();
}
int fake = oldStyle & ~tf.getStyle();
if ((fake & Typeface.BOLD) != 0) {
paint.setFakeBoldText(true);
}
if ((fake & Typeface.ITALIC) != 0) {
paint.setTextSkewX(-0.25f);
}
paint.setTypeface(tf);
}
}
Section 4.2: Strikethrough TextView
Strikethrough the entire text
String sampleText = "This is a test strike";
textView.setPaintFlags(tv.getPaintFlags()| Paint.STRIKE_THRU_TEXT_FLAG);
textView.setText(sampleText);
Output: This is a test strike
GoalKicker.com – Android™ Notes for Professionals 36
Strikethrough only parts of the text
String sampleText = "This is a test strike";
SpannableStringBuilder spanBuilder = new SpannableStringBuilder(sampleText);
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
spanBuilder.setSpan(
strikethroughSpan, // Span to add
0, // Start
4, // End of the span (exclusive)
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE // Text changes will not reflect in the strike changing
);
textView.setText(spanBuilder);
Output: This is a test strike
Section 4.3: TextView with image
Android allows programmers to place images at all four corners of a TextView. For example, if you are creating a
field with a TextView and at same time you want to show that the field is editable, then developers will usually place
an edit icon near that field. Android provides us an interesting option called compound drawable for a TextView:
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:drawablePadding="4dp"
android:drawableRight="@drawable/edit"
android:text="Hello world"
android:textSize="18dp" />
You can set the drawable to any side of your TextView as follows:
android:drawableLeft="@drawable/edit"
android:drawableRight="@drawable/edit"
android:drawableTop="@drawable/edit"
android:drawableBottom="@drawable/edit"
Setting the drawable can also be achieved programmatically in the following way:
yourTextView.setCompoundDrawables(leftDrawable, rightDrawable, topDrawable, bottomDrawable);
Setting any of the parameters handed over to setCompoundDrawables() to null will remove the icon from the
corresponding side of the TextView.
Section 4.4: Make RelativeSizeSpan align to top
In order to make a RelativeSizeSpan align to the top, a custom class can be derived from the class
SuperscriptSpan. In the following example, the derived class is named TopAlignSuperscriptSpan:
activity_main.xml:
<TextView
android:id="@+id/txtView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
GoalKicker.com – Android™ Notes for Professionals 37
android:textSize="26sp" />
MainActivity.java:
TextView txtView = (TextView) findViewById(R.id.txtView);
SpannableString spannableString = new SpannableString("RM123.456");
spannableString.setSpan( new TopAlignSuperscriptSpan( (float)0.35 ), 0, 2,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE );
txtView.setText(spannableString);
TopAlignSuperscriptSpan.java:
private class TopAlignSuperscriptSpan extends SuperscriptSpan {
//divide superscript by this number
protected int fontScale = 2;
//shift value, 0 to 1.0
protected float shiftPercentage = 0;
//doesn't shift
TopAlignSuperscriptSpan() {}
//sets the shift percentage
TopAlignSuperscriptSpan( float shiftPercentage ) {
if( shiftPercentage > 0.0 && shiftPercentage < 1.0 )
this.shiftPercentage = shiftPercentage;
}
@Override
public void updateDrawState( TextPaint tp ) {
//original ascent
float ascent = tp.ascent();
//scale down the font
tp.setTextSize( tp.getTextSize() / fontScale );
//get the new font ascent
float newAscent = tp.getFontMetrics().ascent;
//move baseline to top of old font, then move down size of new font
//adjust for errors with shift percentage
tp.baselineShift += ( ascent - ascent * shiftPercentage )
- (newAscent - newAscent * shiftPercentage );
}
@Override
public void updateMeasureState( TextPaint tp ) {
updateDrawState( tp );
}
}
Reference screenshot:
GoalKicker.com – Android™ Notes for Professionals 38
Section 4.5: Pinchzoom on TextView
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="@+id/mytv"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:text="This is my sample text for pinch zoom demo, you can zoom in and out using
pinch zoom, thanks" />
</RelativeLayout>
MainActivity.java:
import android.app.Activity;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.TextView;
public class MyTextViewPinchZoomClass extends Activity implements OnTouchListener {
final static float STEP = 200;
TextView mytv;
float mRatio = 1.0f;
int mBaseDist;
float mBaseRatio;
float fontsize = 13;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mytv = (TextView) findViewById(R.id.mytv);
GoalKicker.com – Android™ Notes for Professionals 39
mytv.setTextSize(mRatio + 13);
}
public boolean onTouchEvent(MotionEvent event) {
if (event.getPointerCount() == 2) {
int action = event.getAction();
int pureaction = action & MotionEvent.ACTION_MASK;
if (pureaction == MotionEvent.ACTION_POINTER_DOWN) {
mBaseDist = getDistance(event);
mBaseRatio = mRatio;
} else {
float delta = (getDistance(event) - mBaseDist) / STEP;
float multi = (float) Math.pow(2, delta);
mRatio = Math.min(1024.0f, Math.max(0.1f, mBaseRatio * multi));
mytv.setTextSize(mRatio + 13);
}
}
return true;
}
int getDistance(MotionEvent event) {
int dx = (int) (event.getX(0) - event.getX(1));
int dy = (int) (event.getY(0) - event.getY(1));
return (int) (Math.sqrt(dx * dx + dy * dy));
}
public boolean onTouch(View v, MotionEvent event) {
return false;
}
}
Section 4.6: Textview with dierent Textsize
You can archive different Textsizes inside a Textview with a Span
TextView textView = (TextView) findViewById(R.id.textView);
Spannable span = new SpannableString(textView.getText());
span.setSpan(new RelativeSizeSpan(0.8f), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(span)
Section 4.7: Theme and Style customization
MainActivity.java:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
GoalKicker.com – Android™ Notes for Professionals 40
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
tools:context=".MainActivity">
<com.customthemeattributedemo.customview.CustomTextView
style="?mediumTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/message_hello"
custom:font_family="@string/bold_font" />
<com.customthemeattributedemo.customview.CustomTextView
style="?largeTextStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:text="@string/message_hello"
custom:font_family="@string/bold_font" />
</LinearLayout>
CustomTextView.java:
public class CustomTextView extends TextView {
private static final String TAG = "TextViewPlus";
private Context mContext;
public CustomTextView(Context context) {
super(context);
mContext = context;
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
setCustomFont(context, attrs);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
setCustomFont(context, attrs);
}
private void setCustomFont(Context ctx, AttributeSet attrs) {
TypedArray customFontNameTypedArray = ctx.obtainStyledAttributes(attrs,
R.styleable.CustomTextView);
String customFont =
customFontNameTypedArray.getString(R.styleable.CustomTextView_font_family);
Typeface typeface = null;
typeface = Typeface.createFromAsset(ctx.getAssets(), customFont);
setTypeface(typeface);
customFontNameTypedArray.recycle();
}
}
attrs.xml:
GoalKicker.com – Android™ Notes for Professionals 41
<?xml version="1.0" encoding="utf-8"?>
<resources>
<attr name="mediumTextStyle" format="reference" />
<attr name="largeTextStyle" format="reference" />
<declare-styleable name="CustomTextView">
<attr name="font_family" format="string" />
<!--- Your other attributes -->
</declare-styleable>
</resources>
strings.xml:
<resources>
<string name="app_name">Custom Style Theme Attribute Demo</string>
<string name="message_hello">Hello Hiren!</string>
<string name="bold_font">bold.ttf</string>
</resources>
styles.xml:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
<item name="mediumTextStyle">@style/textMedium</item>
<item name="largeTextStyle">@style/textLarge</item>
</style>
<style name="textMedium" parent="textParentStyle">
<item name="android:textAppearance">@android:style/TextAppearance.Medium</item>
</style>
<style name="textLarge" parent="textParentStyle">
<item name="android:textAppearance">@android:style/TextAppearance.Large</item>
</style>
<style name="textParentStyle">
<item name="android:textColor">@android:color/white</item>
<item name="android:background">@color/colorPrimary</item>
<item name="android:padding">5dp</item>
</style>
</resources>
Section 4.8: TextView customization
public class CustomTextView extends TextView {
GoalKicker.com – Android™ Notes for Professionals 42
private float strokeWidth;
private Integer strokeColor;
private Paint.Join strokeJoin;
private float strokeMiter;
public CustomTextView(Context context) {
super(context);
init(null);
}
public CustomTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs);
}
public CustomTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs);
}
public void init(AttributeSet attrs) {
if (attrs != null) {
TypedArray a = getContext().obtainStyledAttributes(attrs, R.styleable.CustomTextView);
if (a.hasValue(R.styleable.CustomTextView_strokeColor)) {
float strokeWidth = a.getDimensionPixelSize(R.styleable.CustomTextView_strokeWidth,
1);
int strokeColor = a.getColor(R.styleable.CustomTextView_strokeColor, 0xff000000);
float strokeMiter = a.getDimensionPixelSize(R.styleable.CustomTextView_strokeMiter,
10);
Paint.Join strokeJoin = null;
switch (a.getInt(R.styleable.CustomTextView_strokeJoinStyle, 0)) {
case (0):
strokeJoin = Paint.Join.MITER;
break;
case (1):
strokeJoin = Paint.Join.BEVEL;
break;
case (2):
strokeJoin = Paint.Join.ROUND;
break;
}
this.setStroke(strokeWidth, strokeColor, strokeJoin, strokeMiter);
}
}
}
public void setStroke(float width, int color, Paint.Join join, float miter) {
strokeWidth = width;
strokeColor = color;
strokeJoin = join;
strokeMiter = miter;
}
@Override
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
int restoreColor = this.getCurrentTextColor();
if (strokeColor != null) {
GoalKicker.com – Android™ Notes for Professionals 43
TextPaint paint = this.getPaint();
paint.setStyle(Paint.Style.STROKE);
paint.setStrokeJoin(strokeJoin);
paint.setStrokeMiter(strokeMiter);
this.setTextColor(strokeColor);
paint.setStrokeWidth(strokeWidth);
super.onDraw(canvas);
paint.setStyle(Paint.Style.FILL);
this.setTextColor(restoreColor);
}
}
}
Usage:
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
CustomTextView customTextView = (CustomTextView) findViewById(R.id.pager_title);
}
}
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@mipmap/background">
<pk.sohail.gallerytest.activity.CustomTextView
android:id="@+id/pager_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center"
android:text="@string/txt_title_photo_gallery"
android:textColor="@color/white"
android:textSize="30dp"
android:textStyle="bold"
app:outerShadowRadius="10dp"
app:strokeColor="@color/title_text_color"
app:strokeJoinStyle="miter"
app:strokeWidth="2dp" />
</RelativeLayout>
attars:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CustomTextView">
GoalKicker.com – Android™ Notes for Professionals 44
<attr name="outerShadowRadius" format="dimension" />
<attr name="strokeWidth" format="dimension" />
<attr name="strokeMiter" format="dimension" />
<attr name="strokeColor" format="color" />
<attr name="strokeJoinStyle">
<enum name="miter" value="0" />
<enum name="bevel" value="1" />
<enum name="round" value="2" />
</attr>
</declare-styleable>
</resources>
Programmatically usage:
CustomTextView mtxt_name = (CustomTextView) findViewById(R.id.pager_title);
//then use
setStroke(float width, int color, Paint.Join join, float miter);
//method before setting
setText("Sample Text");
Section 4.9: Single TextView with two dierent colors
Colored text can be created by passing the text and a font color name to the following function:
private String getColoredSpanned(String text, String color) {
String input = "<font color=" + color + ">" + text + "</font>";
return input;
}
The colored text can then be set to a TextView (or even to a Button, EditText, etc.) by using the example code
below.
First, define a TextView as follows:
TextView txtView = (TextView)findViewById(R.id.txtView);
Then, create differently colored text and assign it to strings:
String name = getColoredSpanned("Hiren", "#800000");
String surName = getColoredSpanned("Patel","#000080");
Finally, set the two differently colored strings to the TextView:
txtView.setText(Html.fromHtml(name+" "+surName));
Reference screenshot:
GoalKicker.com – Android™ Notes for Professionals 45
GoalKicker.com – Android™ Notes for Professionals 46
Chapter 5: AutoCompleteTextView
Section 5.1: AutoComplete with CustomAdapter, ClickListener
and Filter
Main layout : activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent">
<AutoCompleteTextView
android:id="@+id/auto_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:completionThreshold="2"
android:hint="@string/hint_enter_name" />
</LinearLayout>
Row layout row.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/lbl_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="16dp"
android:paddingLeft="8dp"
android:paddingRight="8dp"
android:paddingTop="16dp"
android:text="Medium Text"
android:textAppearance="?android:attr/textAppearanceMedium" />
</RelativeLayout>
strings.xml
<resources>
<string name="hint_enter_name">Enter Name</string>
</resources>
MainActivity.java
public class MainActivity extends AppCompatActivity {
AutoCompleteTextView txtSearch;
List<People> mList;
PeopleAdapter adapter;
private People selectedPerson;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GoalKicker.com – Android™ Notes for Professionals 47
setContentView(R.layout.activity_main);
mList = retrievePeople();
txtSearch = (AutoCompleteTextView) findViewById(R.id.auto_name);
adapter = new PeopleAdapter(this, R.layout.activity_main, R.id.lbl_name, mList);
txtSearch.setAdapter(adapter);
txtSearch.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int pos, long id) {
//this is the way to find selected object/item
selectedPerson = (People) adapterView.getItemAtPosition(pos);
}
});
}
private List<People> retrievePeople() {
List<People> list = new ArrayList<People>();
list.add(new People("James", "Bond", 1));
list.add(new People("Jason", "Bourne", 2));
list.add(new People("Ethan", "Hunt", 3));
list.add(new People("Sherlock", "Holmes", 4));
list.add(new People("David", "Beckham", 5));
list.add(new People("Bryan", "Adams", 6));
list.add(new People("Arjen", "Robben", 7));
list.add(new People("Van", "Persie", 8));
list.add(new People("Zinedine", "Zidane", 9));
list.add(new People("Luis", "Figo", 10));
list.add(new People("John", "Watson", 11));
return list;
}
}
Model class : People.java
public class People {
private String name, lastName;
private int id;
public People(String name, String lastName, int id) {
this.name = name;
this.lastName = lastName;
this.id = id;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getlastName() {
GoalKicker.com – Android™ Notes for Professionals 48
return lastName;
}
public void setlastName(String lastName) {
this.lastName = lastName;
}
}
Adapter class : PeopleAdapter.java
public class PeopleAdapter extends ArrayAdapter<People> {
Context context;
int resource, textViewResourceId;
List<People> items, tempItems, suggestions;
public PeopleAdapter(Context context, int resource, int textViewResourceId, List<People> items)
{
super(context, resource, textViewResourceId, items);
this.context = context;
this.resource = resource;
this.textViewResourceId = textViewResourceId;
this.items = items;
tempItems = new ArrayList<People>(items); // this makes the difference.
suggestions = new ArrayList<People>();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = convertView;
if (convertView == null) {
LayoutInflater inflater = (LayoutInflater)
context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.row, parent, false);
}
People people = items.get(position);
if (people != null) {
TextView lblName = (TextView) view.findViewById(R.id.lbl_name);
if (lblName != null)
lblName.setText(people.getName());
}
return view;
}
@Override
public Filter getFilter() {
return nameFilter;
}
/**
* Custom Filter implementation for custom suggestions we provide.
*/
Filter nameFilter = new Filter() {
@Override
public CharSequence convertResultToString(Object resultValue) {
String str = ((People) resultValue).getName();
return str;
}
@Override
protected FilterResults performFiltering(CharSequence constraint) {
GoalKicker.com – Android™ Notes for Professionals 49
if (constraint != null) {
suggestions.clear();
for (People people : tempItems) {
if
(people.getName().toLowerCase().contains(constraint.toString().toLowerCase())) {
suggestions.add(people);
}
}
FilterResults filterResults = new FilterResults();
filterResults.values = suggestions;
filterResults.count = suggestions.size();
return filterResults;
} else {
return new FilterResults();
}
}
@Override
protected void publishResults(CharSequence constraint, FilterResults results) {
List<People> filterList = (ArrayList<People>) results.values;
if (results != null && results.count > 0) {
clear();
for (People people : filterList) {
add(people);
notifyDataSetChanged();
}
}
}
};
}
Section 5.2: Simple, hard-coded AutoCompleteTextView
Design (layout XML):
<AutoCompleteTextView
android:id="@+id/autoCompleteTextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="65dp"
android:ems="10" />
Find the view in code after setContentView() (or its fragment or custom view equivalent):
final AutoCompleteTextView myAutoCompleteTextView =
(AutoCompleteTextView) findViewById(R.id.autoCompleteTextView1);
Provide hard-coded data via an adapter:
String[] countries = getResources().getStringArray(R.array.list_of_countries);
ArrayAdapter<String> adapter = new
ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,countries);
myAutoCompleteTextView.setAdapter(adapter);
Tip: Though the preferred way would be to provide data via a Loader of some kind instead of a hard-coded list like
this.
GoalKicker.com – Android™ Notes for Professionals 50
Chapter 6: Autosizing TextViews
A TextView that automatically resizes text to fit perfectly within its bounds.
Android O allows you to instruct a TextView to let the size of the text expand or contract automatically to fill its
layout based on the TextView’s characteristics and boundaries.
You can set up the TextView autosizing in either code or XML.
There are two ways to set autosizing TextView: Granularity and Preset Sizes
Section 6.1: Granularity
In Java:
Call the setAutoSizeTextTypeUniformWithConfiguration() method:
setAutoSizeTextTypeUniformWithConfiguration(int autoSizeMinTextSize, int autoSizeMaxTextSize, int
autoSizeStepGranularity, int unit)
In XML:
Use the autoSizeMinTextSize, autoSizeMaxTextSize, and autoSizeStepGranularity attributes to set the autosizing
dimensions in the layout XML file:
<TextView android:id=”@+id/autosizing_textview_presetsize”
android:layout_width=”wrap_content”
android:layout_height=”250dp”
android:layout_marginLeft=”0dp”
android:layout_marginTop=”0dp”
android:autoSizeMaxTextSize=”100sp”
android:autoSizeMinTextSize=”12sp”
android:autoSizeStepGranularity=”2sp”
android:autoSizeText=”uniform”
android:text=”Hello World!”
android:textSize=”100sp”
app:layout_constraintLeft_toLeftOf=”parent”
app:layout_constraintTop_toTopOf=”parent” />
Check out the AutosizingTextViews-Demo at GitHub for more details.
Section 6.2: Preset Sizes
In Java:
Call the setAutoSizeTextTypeUniformWithPresetSizes() method:
setAutoSizeTextTypeUniformWithPresetSizes(int[] presetSizes, int unit)
In XML:
Use the autoSizePresetSizes attribute in the layout XML file:
<TextView android:id=”@+id/autosizing_textview_presetsize”
GoalKicker.com – Android™ Notes for Professionals 51
android:layout_width=”wrap_content”
android:layout_height=”250dp”
android:layout_marginLeft=”0dp”
android:layout_marginTop=”0dp”
android:autoSizeText=”uniform”
android:autoSizePresetSizes=”@array/autosize_text_sizes”
android:text=”Hello World!”
android:textSize=”100sp”
app:layout_constraintLeft_toLeftOf=”parent”
app:layout_constraintTop_toTopOf=”parent” />
To access the array as a resource, define the array in the res/values/arrays.xml file:
<array name=”autosize_text_sizes”>
<item>10sp</item>
<item>12sp</item>
<item>20sp</item>
<item>40sp</item>
<item>100sp</item>
</array>
Check out the AutosizingTextViews-Demo at GitHub for more details.
GoalKicker.com – Android™ Notes for Professionals 52
Chapter 7: ListView
ListView is a viewgroup which groups several items from a data source like array or database and displays them in a
scroll-able list. Data are bound with listview using an Adapter class.
Section 7.1: Custom ArrayAdapter
By default the ArrayAdapter class creates a view for each array item by calling toString() on each item and placing
the contents in a TextView.
To create a complex view for each item (for example, if you want an ImageView for each array item), extend the
ArrayAdapter class and override the getView() method to return the type of View you want for each item.
For example:
public class MyAdapter extends ArrayAdapter<YourClassData>{
private LayoutInflater inflater;
public MyAdapter (Context context, List<YourClassData> data){
super(context, 0, data);
inflater = LayoutInflater.from(context);
}
@Override
public long getItemId(int position)
{
//It is just an example
YourClassData data = (YourClassData) getItem(position);
return data.ID;
}
@Override
public View getView(int position, View view, ViewGroup parent)
{
ViewHolder viewHolder;
if (view == null) {
view = inflater.inflate(R.layout.custom_row_layout_design, null);
// Do some initialization
//Retrieve the view on the item layout and set the value.
viewHolder = new ViewHolder(view);
view.setTag(viewHolder);
}
else {
viewHolder = (ViewHolder) view.getTag();
}
//Retrieve your object
YourClassData data = (YourClassData) getItem(position);
viewHolder.txt.setTypeface(m_Font);
viewHolder.txt.setText(data.text);
viewHolder.img.setImageBitmap(BitmapFactory.decodeFile(data.imageAddr));
return view;
}
GoalKicker.com – Android™ Notes for Professionals 53
private class ViewHolder
{
private final TextView txt;
private final ImageView img;
private ViewHolder(View view)
{
txt = (TextView) view.findViewById(R.id.txt);
img = (ImageView) view.findViewById(R.id.img);
}
}
}
Section 7.2: A basic ListView with an ArrayAdapter
By default the ArrayAdapter creates a view for each array item by calling toString() on each item and placing the
contents in a TextView.
Example:
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, myStringArray);
where android.R.layout.simple_list_item_1 is the layout that contains a TextView for each string in the array.
Then simply call setAdapter() on your ListView:
ListView listView = (ListView) findViewById(R.id.listview);
listView.setAdapter(adapter);
To use something other than TextViews for the array display, for instance, ImageViews, or to have some of data
besides toString() results fill the views, override getView(int, View, ViewGroup) to return the type of view you
want. Check this example.
Section 7.3: Filtering with CursorAdapter
// Get the reference to your ListView
ListView listResults = (ListView) findViewById(R.id.listResults);
// Set its adapter
listResults.setAdapter(adapter);
// Enable filtering in ListView
listResults.setTextFilterEnabled(true);
// Prepare your adapter for filtering
adapter.setFilterQueryProvider(new FilterQueryProvider() {
@Override
public Cursor runQuery(CharSequence constraint) {
// in real life, do something more secure than concatenation
// but it will depend on your schema
// This is the query that will run on filtering
String query = "SELECT _ID as _id, name FROM MYTABLE "
+ "where name like '%" + constraint + "%' "
+ "ORDER BY NAME ASC";
return db.rawQuery(query, null);
}
GoalKicker.com – Android™ Notes for Professionals 54
});
Let's say your query will run every time the user types in an EditText:
EditText queryText = (EditText) findViewById(R.id.textQuery);
queryText.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(final CharSequence s, final int start, final int count, final
int after) {
}
@Override
public void onTextChanged(final CharSequence s, final int start, final int before, final
int count) {
// This is the filter in action
adapter.getFilter().filter(s.toString());
// Don't forget to notify the adapter
adapter.notifyDataSetChanged();
}
@Override
public void afterTextChanged(final Editable s) {
}
});
GoalKicker.com – Android™ Notes for Professionals 55
Chapter 8: Layouts
A layout defines the visual structure for a user interface, such as an activity or widget.
A layout is declared in XML, including screen elements that will appear in it. Code can be added to the application to
modify the state of screen objects at runtime, including those declared in XML.
Section 8.1: LayoutParams
Every single ViewGroup (e.g. LinearLayout, RelativeLayout, CoordinatorLayout, etc.) needs to store information
about its children's properties. About the way its children are being laid out in the ViewGroup. This information is
stored in objects of a wrapper class ViewGroup.LayoutParams.
To include parameters specific to a particular layout type, ViewGroups use subclasses of ViewGroup.LayoutParams
class.
E.g. for
LinearLayout it's LinearLayout.LayoutParams
RelativeLayout it's RelativeLayout.LayoutParams
CoordinatorLayout it's CoordinatorLayout.LayoutParams
...
Most of ViewGroups reutilize the ability to set margins for their children, so they do not subclass
ViewGroup.LayoutParams directly, but they subclass ViewGroup.MarginLayoutParams instead (which itself is a
subclass of ViewGroup.LayoutParams).
LayoutParams in xml
LayoutParams objects are created based on the inflated layout xml file.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="50dp"
android:layout_gravity="right"
android:gravity="bottom"
android:text="Example text"
android:textColor="@android:color/holo_green_dark"/>
<ImageView
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:background="@android:color/holo_green_dark"
android:scaleType="centerInside"
android:src="@drawable/example"/>
</LinearLayout>
All parameters that begin with layout_ specify how the enclosing layout should work. When the layout is inflated,
those parameters are wrapped in a proper LayoutParams object, that later will be used by the Layout to properly
GoalKicker.com – Android™ Notes for Professionals 56
position a particular View within the ViewGroup. Other attributes of a View are directly View-related and are
processed by the View itself.
For TextView:
layout_width, layout_height and layout_gravity will be stored in a LinearLayout.LayoutParams object
and used by the LinearLayout
gravity, text and textColor will be used by the TextView itself
For ImageView:
layout_width, layout_height and layout_weight will be stored in a LinearLayout.LayoutParams object and
used by the LinearLayout
background, scaleType and src will be used by the ImageView itself
Getting LayoutParams object
getLayoutParams is a View's method that allows to retrieve a current LayoutParams object.
Because the LayoutParams object is directly related to the enclosing ViewGroup, this method will return a non-null
value only when View is attached to the ViewGroup. You need to bare in mind that this object might not be present
at all times. Especially you should not depend on having it inside View's constructor.
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
setupView(context);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
setupView(context);
}
private void setupView(Context context) {
if (getLayoutParams().height == 50){ // DO NOT DO THIS!
// This might produce NullPointerException
doSomething();
}
}
//...
}
If you want to depend on having LayoutParams object, you should use onAttachedToWindow method instead.
public class ExampleView extends View {
public ExampleView(Context context) {
super(context);
}
GoalKicker.com – Android™ Notes for Professionals 57
public ExampleView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ExampleView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
if (getLayoutParams().height == 50) { // getLayoutParams() will NOT return null here
doSomething();
}
}
//...
}
Casting LayoutParams object
You might need to use features that are specific to a particular ViewGroup (e.g. you might want to programmatically
change rules of a RelativeLayout). For that purpose you will need to know how to properly cast the
ViewGroup.LayoutParams object.
This might be a bit confusing when getting a LayoutParams object for a child View that actually is another
ViewGroup.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/outer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<FrameLayout
android:id="@+id/inner_layout"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="right"/>
</LinearLayout>
IMPORTANT: The type of LayoutParams object is directly related to the type of the ENCLOSING ViewGroup.
Incorrect casting:
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
FrameLayout.LayoutParams par = (FrameLayout.LayoutParams) innerLayout.getLayoutParams();
// INCORRECT! This will produce ClassCastException
Correct casting:
FrameLayout innerLayout = (FrameLayout)findViewById(R.id.inner_layout);
LinearLayout.LayoutParams par = (LinearLayout.LayoutParams) innerLayout.getLayoutParams();
// CORRECT! the enclosing layout is a LinearLayout
GoalKicker.com – Android™ Notes for Professionals 58
Section 8.2: Gravity and layout gravity
android:layout_gravity
android:layout_gravity is used to set the position of an element in its parent (e.g. a child View inside a
Layout).
Supported by LinearLayout and FrameLayout
android:gravity
android:gravity is used to set the position of content inside an element (e.g. a text inside a TextView).
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:orientation="vertical">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_gravity="left"
android:gravity="center_vertical">
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorPrimary"
android:gravity="left"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorPrimary"
android:gravity="center"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorPrimary"
android:gravity="right"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_gravity="center"
android:gravity="center_vertical">
GoalKicker.com – Android™ Notes for Professionals 59
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorAccent"
android:gravity="left"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorAccent"
android:gravity="center"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorAccent"
android:gravity="right"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="vertical"
android:layout_gravity="right"
android:gravity="center_vertical">
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorPrimaryDark"
android:gravity="left"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorPrimaryDark"
android:gravity="center"/>
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorPrimaryDark"
android:gravity="right"/>
</LinearLayout>
</LinearLayout>
Which gets rendered as following:
GoalKicker.com – Android™ Notes for Professionals 60
Section 8.3: CoordinatorLayout Scrolling Behavior
Version ≥ 2.3-2.3.2
An enclosing CoordinatorLayout can be used to achieve Material Design Scrolling Effects when using inner layouts
that support Nested Scrolling, such as NestedScrollView or RecyclerView.
For this example:
app:layout_scrollFlags="scroll|enterAlways" is used in the Toolbar properties
app:layout_behavior="@string/appbar_scrolling_view_behavior" is used in the ViewPager properties
A RecyclerView is used in the ViewPager Fragments
Here is the layout xml file used in an Activity:
<android.support.design.widget.CoordinatorLayout
android:id="@+id/main_layout"
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"
GoalKicker.com – Android™ Notes for Professionals 61
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/appBarLayout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="6dp">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:background="?attr/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:elevation="0dp"
app:layout_scrollFlags="scroll|enterAlways"
/>
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
app:tabMode="fixed"
android:layout_below="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/colorPrimary"
app:elevation="0dp"
app:tabTextColor="#d3d3d3"
android:minHeight="?attr/actionBarSize"
/>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_below="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
/>
</android.support.design.widget.CoordinatorLayout>
Result:
GoalKicker.com – Android™ Notes for Professionals 62
Section 8.4: Percent Layouts
Version ≥ 2.3
The Percent Support Library provides PercentFrameLayout and PercentRelativeLayout, two ViewGroups that
provide an easy way to specify View dimensions and margins in terms of a percentage of the overall size.
You can use the Percent Support Library by adding the following to your dependencies.
compile 'com.android.support:percent:25.3.1'
If you wanted to display a view that fills the screen horizontally but only half the screen vertically you would do thie
following.
<android.support.percent.PercentFrameLayout
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">
<FrameLayout
app:layout_widthPercent="100%"
app:layout_heightPercent="50%"
android:background="@android:color/black" />
<android.support.percent.PercentFrameLayout>
You can also define the percentages in a separate XML file with code such as:
GoalKicker.com – Android™ Notes for Professionals 63
<fraction name="margin_start_percent">25%</fraction>
And refer to them in your layouts with @fraction/margin_start_percent.
They also contain the ability to set a custom aspect ratio via app:layout_aspectRatio.
This allows you to set only a single dimension, such as only the width, and the height will be automatically
determined based on the aspect ratio you’ve defined, whether it is 4:3 or 16:9 or even a square 1:1 aspect ratio.
For example:
<ImageView
app:layout_widthPercent="100%"
app:layout_aspectRatio="178%"
android:scaleType="centerCrop"
android:src="@drawable/header_background"/>
Section 8.5: View Weight
One of the most used attribute for LinearLayout is the weight of its child views. Weight defines how much space a
view will consume compared to other views within a LinearLayout.
Weight is used when you want to give specific screen space to one component compared to other.
Key Properties:
weightSum is the overall sum of weights of all child views. If you don't specify the weightSum, the system will
calculate the sum of all the weights on its own.
layout_weight specifies the amount of space out of the total weight sum the widget will occupy.
Code:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:weightSum="4">
<EditText
android:layout_weight="2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Type Your Text Here" />
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="Text1" />
<Button
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="wrap_content"
GoalKicker.com – Android™ Notes for Professionals 64
android:text="Text1" />
</LinearLayout>
The output is:
Now even if the size of the device is larger, the EditText will take 2/4 of the screen's space. Hence the look of your
app is seen consistent across all screens.
Note: Here the layout_width is kept 0dp as the widget space is divided horizontally. If the widgets are to be aligned
vertically layout_height will be set to 0dp. This is done to increase the efficiency of the code because at runtime the
system won't attempt to calculate the width or height respectively as this is managed by the weight. If you instead
used wrap_content the system would attempt to calculate the width/height first before applying the weight
attribute which causes another calculation cycle.
Section 8.6: Creating LinearLayout programmatically
Hierarchy
GoalKicker.com – Android™ Notes for Professionals 65
- LinearLayout(horizontal)
- ImageView
- LinearLayout(vertical)
- TextView
- TextView
Code
LinearLayout rootView = new LinearLayout(context);
rootView.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
rootView.setOrientation(LinearLayout.HORIZONTAL);
// for imageview
ImageView imageView = new ImageView(context);
// for horizontal linearlayout
LinearLayout linearLayout2 = new LinearLayout(context);
linearLayout2.setLayoutParams(new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.WRAP_CONTENT));
linearLayout2.setOrientation(LinearLayout.VERTICAL);
TextView tv1 = new TextView(context);
TextView tv2 = new TextView(context);
// add 2 textview to horizontal linearlayout
linearLayout2.addView(tv1);
linearLayout2.addView(tv2);
// finally, add imageview and horizontal linearlayout to vertical linearlayout (rootView)
rootView.addView(imageView);
rootView.addView(linearLayout2);
Section 8.7: LinearLayout
The LinearLayout is a ViewGroup that arranges its children in a single column or a single row. The orientation can be
set by calling the method setOrientation() or using the xml attribute android:orientation.
1. Vertical orientation : android:orientation="vertical"
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@android:string/cancel" />
</LinearLayout>
Here is a screenshot how this will look like:
GoalKicker.com – Android™ Notes for Professionals 66
2. Horizontal orientation : android:orientation="horizontal"
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@android:string/cancel" />
The LinearLayout also supports assigning a weight to individual children with the android:layout_weight
attribute.
Section 8.8: RelativeLayout
RelativeLayout is a ViewGroup that displays child views in relative positions. By default, all child views are drawn at
GoalKicker.com – Android™ Notes for Professionals 67
the top-left of the layout, so you must define the position of each view using the various layout properties available
from RelativeLayout.LayoutParams. The value for each layout property is either a boolean to enable a layout
position relative to the parent RelativeLayout or an ID that references another view in the layout against which the
view should be positioned.
Example:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/imageView"
android:src="@mipmap/ic_launcher" />
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/editText"
android:layout_toRightOf="@+id/imageView"
android:layout_toEndOf="@+id/imageView"
android:hint="@string/hint" />
</RelativeLayout>
Here is a screenshot how this will look like:
GoalKicker.com – Android™ Notes for Professionals 68
Section 8.9: FrameLayout
FrameLayout is designed to block out an area on the screen to display a single item. You can, however, add multiple
children to a FrameLayout and control their position within the FrameLayout by assigning gravity to each child,
using the android:layout_gravity attribute.
Generally, FrameLayout is used to hold a single child view. Common use cases are creating place holders for
inflating Fragments in Activity, overlapping views or applying foreground to the views.
Example:
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:src="@drawable/nougat"
android:scaleType="fitCenter"
android:layout_height="match_parent"
android:layout_width="match_parent"/>
GoalKicker.com – Android™ Notes for Professionals 69
<TextView
android:text="FrameLayout Example"
android:textSize="30sp"
android:textStyle="bold"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:gravity="center"/>
</FrameLayout>
It will look like this:
Section 8.10: GridLayout
GridLayout, as the name suggests is a layout used to arrange Views in a grid. A GridLayout divides itself into
columns and rows. As you can see in the example below, the amount of columns and/or rows is specified by the
properties columnCount and rowCount. Adding Views to this layout will add the first view to the first column, the
second view to the second column, and the third view to the first column of the second row.
<?xml version="1.0" encoding="utf-8"?>
<GridLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
GoalKicker.com – Android™ Notes for Professionals 70
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:columnCount="2"
android:rowCount="2">
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/first"
android:background="@color/colorPrimary"
android:layout_margin="@dimen/default_margin" />
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/second"
android:background="@color/colorPrimary"
android:layout_margin="@dimen/default_margin" />
<TextView
android:layout_width="@dimen/fixed"
android:layout_height="wrap_content"
android:text="@string/third"
android:background="@color/colorPrimary"
android:layout_margin="@dimen/default_margin" />
</GridLayout>
GoalKicker.com – Android™ Notes for Professionals 71
Section 8.11: CoordinatorLayout
Version ≥ 2.3
The CoordinatorLayout is a container somewhat similar to FrameLayout but with extra capabilities, it is called
super-powered FrameLayout in the official documentation.
By attaching a CoordinatorLayout.Behavior to a direct child of CoordinatorLayout, you’ll be able to intercept touch
events, window insets, measurement, layout, and nested scrolling.
In order to use it, you will first have to add a dependency for the support library in your gradle file:
compile 'com.android.support:design:25.3.1'
The number of the latest version of the library may be found here
One practical use case of the CoordinatorLayout is creating a view with a FloatingActionButton. In this specific
case, we will create a RecyclerView with a SwipeRefreshLayout and a FloatingActionButton on top of that. Here's
how you can do that:
GoalKicker.com – Android™ Notes for Professionals 72
<?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:id="@+id/coord_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/swipe_refresh_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/recycler_view"/>
</android.support.v4.widget.SwipeRefreshLayout>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:clickable="true"
android:color="@color/colorAccent"
android:src="@mipmap/ic_add_white"
android:layout_gravity="end|bottom"
app:layout_anchorGravity="bottom|right|end"/>
</android.support.design.widget.CoordinatorLayout>
Notice how the FloatingActionButton is anchored to the CoordinatorLayout with
app:layout_anchor="@id/coord_layout"
GoalKicker.com – Android™ Notes for Professionals 73
Chapter 9: ConstraintLayout
Parameter Details
child The View to be added to the layout
index The index of the View in the layout hierarchy
params The LayoutParams of the View
attrs The AttributeSet that defines the LayoutParams
view The View that has been added or removed
changed Indicates if this View has changed size or position
left The left position, relative to the parent View
top The top position, relative to the parent View
right The right position, relative to the parent View
bottom The bottom position, relative to the parent View
widthMeasureSpec The horizontal space requirements imposed by the parent View
heightMeasureSpec The vertical space requirements imposed by the parent View
layoutDirection -
a -
widthAttr -
heightAttr -
ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way. It is compatible
with Android 2.3 (API level 9) and higher.
It allows you to create large and complex layouts with a flat view hierarchy. It is similar to RelativeLayout in that all
views are laid out according to relationships between sibling views and the parent layout, but it's more flexible than
RelativeLayout and easier to use with Android Studio's Layout Editor.
Section 9.1: Adding ConstraintLayout to your project
To work with ConstraintLayout, you need Android Studio Version 2.2 or newer and have at least version 32 (or
higher) of Android Support Repository.
1. Add the Constraint Layout library as a dependency in your build.gradle file:
dependencies {
compile 'com.android.support.constraint:constraint-layout:1.0.2'
}
2. Sync project
To add a new constraint layout to your project:
1. Right-click on your module's layout directory, then click New > XML > Layout XML.
2. Enter a name for the layout and enter "android.support.constraint.ConstraintLayout" for the Root Tag.
3. Click Finish.
Otherwise just add in a layout file:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
GoalKicker.com – Android™ Notes for Professionals 74
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.constraint.ConstraintLayout>
Section 9.2: Chains
Since ConstraintLayout alpha 9, Chains are available. A Chain is a set of views inside a ConstraintLayout that are
connected in a bi-directional way between them, i.e A connected to B with a constraint, and B connected to A with
another constraint.
Example:
<android.support.constraint.ConstraintLayout
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">
<!-- this view is linked to the bottomTextView -->
<TextView
android:id="@+id/topTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView"
app:layout_constraintBottom_toTopOf="@+id/bottomTextView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainPacked="true"/>
<!-- this view is linked to the topTextView at the same time -->
<TextView
android:id="@+id/bottomTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Bottom\nMkay"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/topTextView"/>
</android.support.constraint.ConstraintLayout>
In this example, the two views are positioned one under another and both of them are centered vertically. You may
change the vertical position of these views by adjusting the chain's bias. Add the following code to the first element
of a chain:
app:layout_constraintVertical_bias="0.2"
In a vertical chain, the first element is a top-most view, and in a horizontal chain it is the left-most view. The first
element defines the whole chain's behavior.
Chains are a new feature and are updated frequently. Here is an official Android Documentation on Chains.
GoalKicker.com – Android™ Notes for Professionals 75
Chapter 10: TextInputLayout
TextInputLayout was introduced to display the floating label on EditText. The EditText has to be wrapped by
TextInputLayout in order to display the floating label.
Section 10.1: Basic usage
It is the basic usage of the TextInputLayout.
Make sure to add the dependency in the build.gradle file as described in the remarks section.
Example:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/username"/>
</android.support.design.widget.TextInputLayout>
Section 10.2: Password Visibility Toggles
With an input password type, you can also enable an icon that can show or hide the entire text using the
passwordToggleEnabled attribute.
You can also customize same default using these attributes:
passwordToggleDrawable: to change the default eye icon
passwordToggleTint: to apply a tint to the password visibility toggle drawable.
passwordToggleTintMode: to specify the blending mode used to apply the background tint.
Example:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:passwordToggleContentDescription="@string/description"
app:passwordToggleDrawable="@drawable/another_toggle_drawable"
app:passwordToggleEnabled="true">
<EditText/>
</android.support.design.widget.TextInputLayout>
Section 10.3: Adding Character Counting
The TextInputLayout has a character counter for an EditText defined within it.
The counter will be rendered below the EditText.
Just use the setCounterEnabled() and setCounterMaxLength methods:
TextInputLayout til = (TextInputLayout) findViewById(R.id.username);
GoalKicker.com – Android™ Notes for Professionals 76
til.setCounterEnabled(true);
til.setCounterMaxLength(15);
or the app:counterEnabled and app:counterMaxLength attributes in the xml.
<android.support.design.widget.TextInputLayout
app:counterEnabled="true"
app:counterMaxLength="15">
<EditText/>
</android.support.design.widget.TextInputLayout>
Section 10.4: Handling Errors
You can use the TextInputLayout to display error messages according to the material design guidelines using the
setError and setErrorEnabledmethods.
In order to show the error below the EditText use:
TextInputLayout til = (TextInputLayout) findViewById(R.id.username);
til.setErrorEnabled(true);
til.setError("You need to enter a name");
To enable error in the TextInputLayout you can eithr use app:errorEnabled="true" in xml or
til.setErrorEnabled(true); as shown above.
You will obtain:
Section 10.5: Customizing the appearance of the
TextInputLayout
You can customize the appearance of the TextInputLayout and its embedded EditTextby defining custom styles in
your styles.xml. The defined styles can either be added as styles or themes to your TextInputLayout.
Example for customizing the hint appearance:
styles.xml:
<!--Floating label text style-->
<style name="MyHintStyle" parent="TextAppearance.AppCompat.Small">
<item name="android:textColor">@color/black</item>
</style>
<!--Input field style-->
<style name="MyEditText" parent="Theme.AppCompat.Light">
<item name="colorControlNormal">@color/indigo</item>
<item name="colorControlActivated">@color/pink</item>
</style>
GoalKicker.com – Android™ Notes for Professionals 77
To Apply Style update your TextInputLayout And EditText as follows
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:hintTextAppearance="@style/MyHintStyle">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/Title"
android:theme="@style/MyEditText" />
</android.support.design.widget.TextInputLayout>
Example to customize the accent color of the TextInputLayout. The accent color affects the color of the baseline of
the EditText and the text color for the floating hint text:
styles.xml:
<style name="TextInputLayoutWithPrimaryColor" parent="Widget.Design.TextInputLayout">
<item name="colorAccent">@color/primary</item>
</style>
layout file:
<android.support.design.widget.TextInputLayout
android:id="@+id/textInputLayout_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/TextInputLayoutWithPrimaryColor">
<android.support.design.widget.TextInputEditText
android:id="@+id/textInputEditText_password"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/login_hint_password"
android:inputType="textPassword" />
</android.support.design.widget.TextInputLayout>
Section 10.6: TextInputEditText
The TextInputEditText is an EditText with an extra fix to display a hint in the IME when in 'extract' mode.
The Extract mode is the mode that the keyboard editor switches to when you click on an EditText when the space
is too small (for example landscape on a smartphone).
In this case, using an EditText while you are editing the text you can see that the IME doesn't give you a hint of
what you're editing
The TextInputEditText fixes this issue providing hint text while the user’s device’s IME is in Extract mode.
Example:
<android.support.design.widget.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Description"
GoalKicker.com – Android™ Notes for Professionals 78
>
<android.support.design.widget.TextInputEditText
android:id="@+id/description"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.design.widget.TextInputLayout>
GoalKicker.com – Android™ Notes for Professionals 79
Chapter 11: CoordinatorLayout and
Behaviors
The CoordinatorLayout is a super-powered FrameLayout and goal of this ViewGroup is to coordinate the views that
are inside it.
The main appeal of the CoordinatorLayout is its ability to coordinate the animations and transitions of the views
within the XML file itself.
CoordinatorLayout is intended for two primary use cases:
:As a top-level application decor or chrome layout
:As a container for a specific interaction with one or more child views
Section 11.1: Creating a simple Behavior
To create a Behavior just extend the CoordinatorLayout.Behavior class.
Extend the CoordinatorLayout.Behavior
Example:
public class MyBehavior<V extends View> extends CoordinatorLayout.Behavior<V> {
/**
* Default constructor.
*/
public MyBehavior() {
}
/**
* Default constructor for inflating a MyBehavior from layout.
*
* @param context The {@link Context}.
* @param attrs The {@link AttributeSet}.
*/
public MyBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
This behavior need to be attached to a child View of a CoordinatorLayout to be called.
Attach a Behavior programmatically
MyBehavior myBehavior = new MyBehavior();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) view.getLayoutParams();
params.setBehavior(myBehavior);
Attach a Behavior in XML
You can use the layout_behavior attribute to attach the behavior in XML:
<View
android:layout_height="...."
android:layout_width="...."
GoalKicker.com – Android™ Notes for Professionals 80
app:layout_behavior=".MyBehavior" />
Attach a Behavior automatically
If you are working with a custom view you can attach the behavior using the
@CoordinatorLayout.DefaultBehavior annotation:
@CoordinatorLayout.DefaultBehavior(MyBehavior.class)
public class MyView extends ..... {
}
Section 11.2: Using the SwipeDismissBehavior
The SwipeDismissBehavior works on any View and implements the functionality of swipe to dismiss in our layouts
with a CoordinatorLayout.
Just use:
final SwipeDismissBehavior<MyView> swipe = new SwipeDismissBehavior();
//Sets the swipe direction for this behavior.
swipe.setSwipeDirection(
SwipeDismissBehavior.SWIPE_DIRECTION_ANY);
//Set the listener to be used when a dismiss event occurs
swipe.setListener(
new SwipeDismissBehavior.OnDismissListener() {
@Override public void onDismiss(View view) {
//......
}
@Override
public void onDragStateChanged(int state) {
//......
}
});
//Attach the SwipeDismissBehavior to a view
LayoutParams coordinatorParams =
(LayoutParams) mView.getLayoutParams();
coordinatorParams.setBehavior(swipe);
Section 11.3: Create dependencies between Views
You can use the CoordinatorLayout.Behavior to create dependencies between views. You can anchor a View to
another View by:
using the layout_anchor attribute.
creating a custom Behavior and implementing the layoutDependsOn method returning true.
For example, in order to create a Behavior for moving an ImageView when another one is moved (example
Toolbar), perform the following steps:
Create the custom Behavior:
public class MyBehavior extends CoordinatorLayout.Behavior<ImageView> {...}
GoalKicker.com – Android™ Notes for Professionals 81
Override the layoutDependsOn method returning true. This method is called every time a change occurs to
the layout:
@Override
public boolean layoutDependsOn(CoordinatorLayout parent,
ImageView child, View dependency) {
// Returns true to add a dependency.
return dependency instanceof Toolbar;
}
Whenever the method layoutDependsOn returns true the method onDependentViewChanged is called:
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, ImageView child, View
dependency) {
// Implement here animations, translations, or movements; always related to the provided
dependency.
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
child.setTranslationY(translationY);
}
GoalKicker.com – Android™ Notes for Professionals 82
Chapter 12: TabLayout
Section 12.1: Using a TabLayout without a ViewPager
Most of the time a TabLayout is used together with a ViewPager, in order to get the swipe functionality that comes
with it.
It is possible to use a TabLayout without a ViewPager by using a TabLayout.OnTabSelectedListener.
First, add a TabLayout to your activity's XML file:
<android.support.design.widget.TabLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:id="@+id/tabLayout" />
For navigation within an Activity, manually populate the UI based on the tab selected.
TabLayout tabLayout = (TabLayout) findViewById(R.id.tabLayout);
tabLayout.addOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
@Override
public void onTabSelected(TabLayout.Tab tab) {
int position = tab.getPosition();
switch (tab.getPosition()) {
case 1:
getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment_container, new ChildFragment()).commit();
break;
// Continue for each tab in TabLayout
}
@Override
public void onTabUnselected(TabLayout.Tab tab) {
}
@Override
public void onTabReselected(TabLayout.Tab tab) {
}
});
GoalKicker.com – Android™ Notes for Professionals 83
Chapter 13: ViewPager
ViewPager is a Layout manager that allows the user to flip left and right through pages of data. It is most often used
in conjunction with Fragment, which is a convenient way to supply and manage the lifecycle of each page.
Section 13.1: ViewPager with a dots indicator
All we need are: ViewPager, TabLayout and 2 drawables for selected and default dots.
Firstly, we have to add TabLayout to our screen layout, and connect it with ViewPager. We can do this in two ways:
Nested TabLayout in ViewPager
<android.support.v4.view.ViewPager
android:id="@+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.TabLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</android.support.v4.view.ViewPager>
In this case TabLayout will be automatically connected with ViewPager, but TabLayout will be next to
ViewPager, not over him.
Separate TabLayout
<android.support.v4.view.ViewPager
android:id="@+id/photos_viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
GoalKicker.com – Android™ Notes for Professionals 84
<android.support.design.widget.TabLayout
android:id="@+id/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
In this case, we can put TabLayout anywhere, but we have to connect TabLayout with ViewPager
programmatically
ViewPager pager = (ViewPager) view.findViewById(R.id.photos_viewpager);
PagerAdapter adapter = new PhotosAdapter(getChildFragmentManager(), photosUrl);
pager.setAdapter(adapter);
TabLayout tabLayout = (TabLayout) view.findViewById(R.id.tab_layout);
tabLayout.setupWithViewPager(pager, true);
Once we created our layout, we have to prepare our dots. So we create three files: selected_dot.xml,
default_dot.xml and tab_selector.xml.
selected_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="@color/colorAccent"/>
</shape>
</item>
</layer-list>
default_dot.xml
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item>
<shape
android:innerRadius="0dp"
android:shape="ring"
android:thickness="8dp"
android:useLevel="false">
<solid android:color="@android:color/darker_gray"/>
</shape>
</item>
</layer-list>
tab_selector.xml
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@drawable/selected_dot"
android:state_selected="true"/>
<item android:drawable="@drawable/default_dot"/>
GoalKicker.com – Android™ Notes for Professionals 85
</selector>
Now we need to add only 3 lines of code to TabLayout in our xml layout and you're done.
app:tabBackground="@drawable/tab_selector"
app:tabGravity="center"
app:tabIndicatorHeight="0dp"
Section 13.2: Basic ViewPager usage with fragments
A ViewPager allows to show multiple fragments in an activity that can be navigated by either fliping left or right. A
ViewPager needs to be feed of either Views or Fragments by using a PagerAdapter.
There are however two more specific implementations that you will find most useful in case of using Fragments
which are FragmentPagerAdapter and FragmentStatePagerAdapter. When a Fragment needs to be instantiated for
the first time, getItem(position) will be called for each position that needs instantiating. The getCount() method
will return the total number of pages so the ViewPager knows how many Fragments need to be shown.
Both FragmentPagerAdapter and FragmentStatePagerAdapter keep a cache of the Fragments that the ViewPager
will need to show. By default the ViewPager will try to store a maximum of 3 Fragments that correspond to the
currently visible Fragment, and the ones next to the right and left. Also FragmentStatePagerAdapter will keep the
state of each of your fragments.
Be aware that both implementations assume your fragments will keep their positions, so if you keep a list of the
fragments instead of having a static number of them as you can see in the getItem() method, you will need to
create a subclass of PagerAdapter and override at least instantiateItem(),destroyItem() and
getItemPosition()methods.
Just add a ViewPager in your layout as described in the basic example:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.v4.view.ViewPager
android:id="@+id/vpPager">
</android.support.v4.view.ViewPager>
</LinearLayout>
Then define the adapter that will determine how many pages exist and which fragment to display for each page of
the adapter.
public class MyViewPagerActivity extends AppCompatActivity {
private static final String TAG = MyViewPagerActivity.class.getName();
private MyPagerAdapter mFragmentAdapter;
private ViewPager mViewPager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myActivityLayout);
//Apply the Adapter
mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(mFragmentAdapter);
}
GoalKicker.com – Android™ Notes for Professionals 86
private class MyPagerAdapter extends FragmentPagerAdapter{
public MyPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
default:
return null;
}
}
// Returns total number of pages
@Override
public int getCount() {
return 3;
}
}
}
Version ≥ 3.2.x
If you are using android.app.Fragment you have to add this dependency:
compile 'com.android.support:support-v13:25.3.1'
If you are using android.support.v4.app.Fragment you have to add this dependency:
compile 'com.android.support:support-fragment:25.3.1'
Section 13.3: ViewPager with PreferenceFragment
Until recently, using android.support.v4.app.FragmentPagerAdapter would prevent the usage of a
PreferenceFragment as one of the Fragments used in the FragmentPagerAdapter.
The latest versions of the support v7 library now include the PreferenceFragmentCompat class, which will work with
a ViewPager and the v4 version of FragmentPagerAdapter.
Example Fragment that extends PreferenceFragmentCompat:
import android.os.Bundle;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.view.View;
public class MySettingsPrefFragment extends PreferenceFragmentCompat {
public MySettingsPrefFragment() {
GoalKicker.com – Android™ Notes for Professionals 87
// Required empty public constructor
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.fragment_settings_pref);
}
@Override
public void onCreatePreferences(Bundle bundle, String s) {
}
}
You can now use this Fragment in a android.support.v4.app.FragmentPagerAdapter subclass:
private class PagerAdapterWithSettings extends FragmentPagerAdapter {
public PagerAdapterWithSettings(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new FragmentOne();
case 1:
return new FragmentTwo();
case 2:
return new MySettingsPrefFragment();
default:
return null;
}
}
// .......
}
Section 13.4: Adding a ViewPager
Make sure the following dependency is added to your app's build.gradle file under dependencies:
compile 'com.android.support:support-core-ui:25.3.0'
Then add the ViewPager to your activity layout:
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
Then define your PagerAdapter:
GoalKicker.com – Android™ Notes for Professionals 88
public class MyPagerAdapter extends PagerAdapter {
private Context mContext;
public CustomPagerAdapter(Context context) {
mContext = context;
}
@Override
public Object instantiateItem(ViewGroup collection, int position) {
// Create the page for the given position. For example:
LayoutInflater inflater = LayoutInflater.from(mContext);
ViewGroup layout = (ViewGroup) inflater.inflate(R.layout.xxxx, collection, false);
collection.addView(layout);
return layout;
}
@Override
public void destroyItem(ViewGroup collection, int position, Object view) {
// Remove a page for the given position. For example:
collection.removeView((View) view);
}
@Override
public int getCount() {
//Return the number of views available.
return numberOfPages;
}
@Override
public boolean isViewFromObject(View view, Object object) {
// Determines whether a page View is associated with a specific key object
// as returned by instantiateItem(ViewGroup, int). For example:
return view == object;
}
}
Finally setup the ViewPager in your Activity:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewPager viewPager = (ViewPager) findViewById(R.id.viewpager);
viewPager.setAdapter(new MyPagerAdapter(this));
}
}
Section 13.5: Setup OnPageChangeListener
If you need to listen for changes to the page selected you can implement the ViewPager.OnPageChangeListener
listener on the ViewPager:
viewPager.addOnPageChangeListener(new OnPageChangeListener() {
// This method will be invoked when a new page becomes selected. Animation is not necessarily
GoalKicker.com – Android™ Notes for Professionals 89
complete.
@Override
public void onPageSelected(int position) {
// Your code
}
// This method will be invoked when the current page is scrolled, either as part of
// a programmatically initiated smooth scroll or a user initiated touch scroll.
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// Your code
}
// Called when the scroll state changes. Useful for discovering when the user begins
// dragging, when the pager is automatically settling to the current page,
// or when it is fully stopped/idle.
@Override
public void onPageScrollStateChanged(int state) {
// Your code
}
});
Section 13.6: ViewPager with TabLayout
A TabLayout can be used for easier navigation.
You can set the tabs for each fragment in your adapter by using TabLayout.newTab() method but there is another
more convenient and easier method for this task which is TabLayout.setupWithViewPager().
This method will sync by creating and removing tabs according to the contents of the adapter associated with your
ViewPager each time you call it.
Also, it will set a callback so each time the user flips the page, the corresponding tab will be selected.
Just define a layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
app:tabMode="scrollable" />
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="0px"
android:layout_weight="1" />
</LinearLayout>
Then implement the FragmentPagerAdapter and apply it to the ViewPager:
public class MyViewPagerActivity extends AppCompatActivity {
private static final String TAG = MyViewPagerActivity.class.getName();
private MyPagerAdapter mFragmentAdapter;
private ViewPager mViewPager;
private TabLayout mTabLayout;
@Override
GoalKicker.com – Android™ Notes for Professionals 90
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myActivityLayout);
// Get the ViewPager and apply the PagerAdapter
mFragmentAdapter = new MyPagerAdapter(getSupportFragmentManager());
mViewPager = (ViewPager) findViewById(R.id.view_pager);
mViewPager.setAdapter(mFragmentAdapter);
// link the tabLayout and the viewpager together
mTabLayout = (TabLayout) findViewById(R.id.tab_layout);
mTabLayout.setupWithViewPager(mViewPager);
}
private class MyPagerAdapter extends FragmentPagerAdapter{
public MyPagerAdapter(FragmentManager supportFragmentManager) {
super(supportFragmentManager);
}
// Returns the fragment to display for that page
@Override
public Fragment getItem(int position) {
switch(position) {
case 0:
return new Fragment1();
case 1:
return new Fragment2();
case 2:
return new Fragment3();
default:
return null;
}
}
// Will be displayed as the tab's label
@Override
public CharSequence getPageTitle(int position) {
switch(position) {
case 0:
return "Fragment 1 title";
case 1:
return "Fragment 2 title";
case 2:
return "Fragment 3 title";
default:
return null;
}
}
// Returns total number of pages
@Override
public int getCount() {
return 3;
}
GoalKicker.com – Android™ Notes for Professionals 91
}
}
GoalKicker.com – Android™ Notes for Professionals 92
Chapter 14: CardView
Parameter Details
cardBackgroundColor Background color for CardView.
cardCornerRadius Corner radius for CardView.
cardElevation Elevation for CardView.
cardMaxElevation Maximum Elevation for CardView.
cardPreventCornerOverlap Add padding to CardView on v20 and before to prevent intersections between the Card
content and rounded corners.
cardUseCompatPadding Add padding in API v21+ as well to have the same measurements with previous
versions. May be a boolean value, such as "true" or "false".
contentPadding Inner padding between the edges of the Card and children of the CardView.
contentPaddingBottom Inner padding between the bottom edge of the Card and children of the CardView.
contentPaddingLeft Inner padding between the left edge of the Card and children of the CardView.
contentPaddingRight Elevation for CardView.
cardElevation Inner padding between the right edge of the Card and children of the CardView.
contentPaddingTop Inner padding between the top edge of the Card and children of the CardView.
A FrameLayout with a rounded corner background and shadow.
CardView uses elevation property on Lollipop for shadows and falls back to a custom emulated shadow
implementation on older platforms.
Due to expensive nature of rounded corner clipping, on platforms before Lollipop, CardView does not clip its
children that intersect with rounded corners. Instead, it adds padding to avoid such intersection (See
setPreventCornerOverlap(boolean) to change this behavior).
Section 14.1: Getting Started with CardView
CardView is a member of the Android Support Library, and provides a layout for cards.
To add CardView to your project, add the following line to your build.gradle dependencies.
compile 'com.android.support:cardview-v7:25.1.1'
A number of the latest version may be found here
In your layout you can then add the following to get a card.
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!-- one child layout containing other layouts or views -->
</android.support.v7.widget.CardView>
You can then add other layouts inside this and they will be encompassed in a card.
Also, CardView can be populated with any UI element and manipulated from code.
<?xml version="1.0" encoding="utf-8"?>
GoalKicker.com – Android™ Notes for Professionals 93
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/card_view"
android:layout_margin="5dp"
card_view:cardBackgroundColor="#81C784"
card_view:cardCornerRadius="12dp"
card_view:cardElevation="3dp"
card_view:contentPadding="4dp" >
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="16dp" >
<ImageView
android:layout_width="100dp"
android:layout_height="100dp"
android:id="@+id/item_image"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_marginRight="16dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/item_title"
android:layout_toRightOf="@+id/item_image"
android:layout_alignParentTop="true"
android:textSize="30sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/item_detail"
android:layout_toRightOf="@+id/item_image"
android:layout_below="@+id/item_title"
/>
</RelativeLayout>
</android.support.v7.widget.CardView>
Section 14.2: Adding Ripple animation
To enable the ripple animation in a CardView, add the following attributes:
<android.support.v7.widget.CardView
...
android:clickable="true"
android:foreground="?android:attr/selectableItemBackground">
...
</android.support.v7.widget.CardView>
Section 14.3: Customizing the CardView
CardView provides a default elevation and corner radius so that cards have a consistent appearance across the
GoalKicker.com – Android™ Notes for Professionals 94
platforms.
You can customize these default values using these attributes in the xml file:
1. card_view:cardElevation attribute add elevation in CardView.
2. card_view:cardBackgroundColor attribute is used to customize background color of CardView's
background(you can give any color).
3. card_view:cardCornerRadius attribute is used to curve 4 edges of CardView
4. card_view:contentPadding attribute add padding between card and children of card
Note: card_view is a namespace defined in topmost parent layout view.
xmlns:card_view="http://schemas.android.com/apk/res-auto"
Here an example:
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
card_view:cardElevation="4dp"
card_view:cardBackgroundColor="@android:color/white"
card_view:cardCornerRadius="8dp"
card_view:contentPadding="16dp">
<!-- one child layout containing other layouts or views -->
</android.support.v7.widget.CardView>
You can also do it programmatically using:
card.setCardBackgroundColor(....);
card.setCardElevation(...);
card.setRadius(....);
card.setContentPadding();
Check the official javadoc for additional properties.
Section 14.4: Using Images as Background in CardView (Pre-
Lollipop device issues)
While using Image/Colour as an background in a CardView, You might end up with slight white paddings (If default
Card colour is white) on the edges. This occurs due to the default rounded corners in the Card View. Here is how to
avoid those margins in Pre-lollipop devices.
We need to use an attribute card_view:cardPreventCornerOverlap="false" in the CardView. 1). In XML use the
following snippet.
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
card_view:cardPreventCornerOverlap="false"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/row_wallet_redeem_img"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:adjustViewBounds="true"
GoalKicker.com – Android™ Notes for Professionals 95
android:scaleType="centerCrop"
android:src="@drawable/bg_image" />
</android.support.v7.widget.CardView>
2. In Java like this cardView.setPreventCornerOverlap(false).
Doing so removes an unwanted padding on the Card's edges. Here are some visual examples related to this
implementation.
1 Card with image background in API 21 (perfectly fine)
2 Card with image background in API 19 without attribute (notice the paddings around image)
3 FIXED Card with image background in API 19 with attribute cardView.setPreventCornerOverlap(false)
(Issue now fixed)
GoalKicker.com – Android™ Notes for Professionals 96
Also read about this on Documentation here
Original SOF post here
Section 14.5: Animate CardView background color with
TransitionDrawable
public void setCardColorTran(CardView card) {
ColorDrawable[] color = {new ColorDrawable(Color.BLUE), new ColorDrawable(Color.RED)};
TransitionDrawable trans = new TransitionDrawable(color);
if(Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
card.setBackground(trans);
} else {
card.setBackgroundDrawable(trans);
}
trans.startTransition(5000);
}
GoalKicker.com – Android™ Notes for Professionals 97
Chapter 15: NavigationView
Section 15.1: How to add the NavigationView
To use a NavigationView just add the dependency in the build.gradle file as described in the remarks section
Then add the NavigationView in the layout
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.DrawerLayout
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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<android.support.design.widget.NavigationView
android:id="@+id/nav_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="start"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</android.support.v4.widget.DrawerLayout>
res/layout/nav_header_main.xml: The view which will been displayed on the top of the drawer
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/nav_header_height"
android:background="@drawable/side_nav_bar"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark"
android:orientation="vertical"
android:gravity="bottom">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:src="@android:drawable/sym_def_app_icon"
android:id="@+id/imageView" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
GoalKicker.com – Android™ Notes for Professionals 98
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="Android Studio"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="android.studio@android.com"
android:id="@+id/textView" />
</LinearLayout>
res/layout/app_bar_main.xml An abstraction layer for the toolbar to separate it from the content:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:context="eu.rekisoft.playground.MainActivity">
<android.support.design.widget.AppBarLayout
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.AppBarLayout>
<include layout="@layout/content_main"/>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
res/layout/content_main.xml The real content of the activity just for demo, here you would put your normal
layout xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="@dimen/activity_horizontal_margin"
GoalKicker.com – Android™ Notes for Professionals 99
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:showIn="@layout/app_bar_main"
tools:context="eu.rekisoft.playground.MainActivity">
<TextView
android:text="Hello World!"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
Define your menu file as res/menu/activity_main_drawer.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<group android:checkableBehavior="single">
<item
android:id="@+id/nav_camera"
android:icon="@drawable/ic_menu_camera"
android:title="Import" />
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="Slideshow" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manage"
android:title="Tools" />
</group>
<item android:title="Communicate">
<menu>
<item
android:id="@+id/nav_share"
android:icon="@drawable/ic_menu_share"
android:title="Share" />
<item
android:id="@+id/nav_send"
android:icon="@drawable/ic_menu_send"
android:title="Send" />
</menu>
</item>
</menu>
And finally the java/main/eu/rekisoft/playground/MainActivity.java:
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
GoalKicker.com – Android™ Notes for Professionals 100
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open,
R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
@Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
switch(item.getItemId()) {/*...*/}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
GoalKicker.com – Android™ Notes for Professionals 101
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
It will look like this:
Section 15.2: Add underline in menu elements
Each group ends with a line separator. If each item in your menu has its own group you will achieve the desired
graphical output. It will work only if your different groups have different android:id. Also, in menu.xml remember
to mention android:checkable="true" for single item and android:checkableBehavior="single" for a group of
items.
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/pos_item_help"
android:checkable="true"
android:title="Help" />
<item
android:id="@+id/pos_item_pos"
android:checkable="true"
android:title="POS" />
<item
android:id="@+id/pos_item_orders"
android:checkable="true"
android:title="Orders" />
<group
android:id="@+id/group"
android:checkableBehavior="single">
GoalKicker.com – Android™ Notes for Professionals 102
<item
android:id="@+id/menu_nav_home"
android:icon="@drawable/ic_home_black_24dp"
android:title="@string/menu_nav_home" />
</group>
......
</menu>
Section 15.3: Add seperators to menu
Access the RecyclerView in the NavigationView and add ItemDecoration to it.
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
NavigationMenuView navMenuView = (NavigationMenuView) navigationView.getChildAt(0);
navMenuView.addItemDecoration(new DividerItemDecoration(this));
Code for DividerItemDecoration
GoalKicker.com – Android™ Notes for Professionals 103
public class DividerItemDecoration extends RecyclerView.ItemDecoration {
private static final int[] ATTRS = new int[]{android.R.attr.listDivider};
private Drawable mDivider;
public DividerItemDecoration(Context context) {
final TypedArray styledAttributes = context.obtainStyledAttributes(ATTRS);
mDivider = styledAttributes.getDrawable(0);
styledAttributes.recycle();
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
int left = parent.getPaddingLeft();
int right = parent.getWidth() - parent.getPaddingRight();
int childCount = parent.getChildCount();
for (int i = 1; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
Preview:
Section 15.4: Add menu Divider using default
DividerItemDecoration
Just use default DividerItemDecoration class :
NavigationView navigationView = (NavigationView) findViewById(R.id.navigation);
NavigationMenuView navMenuView = (NavigationMenuView) navigationView.getChildAt(0);
GoalKicker.com – Android™ Notes for Professionals 104
navMenuView.addItemDecoration(new DividerItemDecoration(context,DividerItemDecoration.VERTICAL));
Preview :
GoalKicker.com – Android™ Notes for Professionals 105
Chapter 16: RecyclerView
Parameter Detail
Adapter A subclass of RecyclerView.Adapter responsible for providing views that represent items in a data
set
Position The position of a data item within an Adapter
Index The index of an attached child view as used in a call to getChildAt(int). Contrast with Position
Binding The process of preparing a child view to display data corresponding to a position within the adapter
Recycle (view)
A view previously used to display data for a specific adapter position may be placed in a cache for
later reuse to display the same type of data again later. This can drastically improve performance by
skipping initial layout inflation or construction
Scrap (view)
A child view that has entered into a temporarily detached state during layout. Scrap views may be
reused without becoming fully detached from the parent RecyclerView, either unmodified if no
rebinding is required or modified by the adapter if the view was considered dirty
Dirty (view) A child view that must be rebound by the adapter before being displayed
RecyclerView is a more advanced version of List View with improved performance and additional features.
Section 16.1: Adding a RecyclerView
Add the dependency as described in the Remark section, then add a RecyclerView to your layout:
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
Once you have added a RecyclerView widget to your layout, obtain a handle to the object, connect it to a layout
manager and attach an adapter for the data to be displayed:
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
// set a layout manager (LinearLayoutManager in this example)
mLayoutManager = new LinearLayoutManager(getApplicationContext());
mRecyclerView.setLayoutManager(mLayoutManager);
// specify an adapter
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
Or simply setup layout manager from xml by adding this lines:
xmlns:app="http://schemas.android.com/apk/res-auto"
app:layoutManager="android.support.v7.widget.LinearLayoutManager"
If you know that changes in content of the RecyclerView won't change the layout size of the RecyclerView, use the
following code to improve the performance of the component. If RecyclerView has a fixed size, it knows that
RecyclerView itself will not resize due to its children, so it doesn’t call request layout at all. It just handles the change
itself. If invalidating whatever the parent is, the coordinator, layout, or whatever. (you can use this method even
before setting LayoutManager and Adapter):
mRecyclerView.setHasFixedSize(true);
GoalKicker.com – Android™ Notes for Professionals 106
RecyclerView provides these built-in layout managers to use. So you can create a list, a grid and a staggered grid
using RecyclerView:
1. LinearLayoutManager shows items in a vertical or horizontal scrolling list.
2. GridLayoutManager shows items in a grid.
3. StaggeredGridLayoutManager shows items in a staggered grid.
Section 16.2: Smoother loading of items
If the items in your RecyclerView load data from the network (commonly images) or carry out other processing,
that can take a significant amount of time and you may end up with items on-screen but not fully loaded. To avoid
this you can extend the existing LinearLayoutManager to preload a number of items before they become visible onscreen:
package com.example;
import android.content.Context;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.OrientationHelper;
import android.support.v7.widget.RecyclerView;
/**
* A LinearLayoutManager that preloads items off-screen.
* <p>
* Preloading is useful in situations where items might take some time to load
* fully, commonly because they have maps, images or other items that require
* network requests to complete before they can be displayed.
* <p>
* By default, this layout will load a single additional page's worth of items,
* a page being a pixel measure equivalent to the on-screen size of the
* recycler view. This can be altered using the relevant constructor, or
* through the {@link #setPages(int)} method.
*/
public class PreLoadingLinearLayoutManager extends LinearLayoutManager {
private int mPages = 1;
private OrientationHelper mOrientationHelper;
public PreLoadingLinearLayoutManager(final Context context) {
super(context);
}
public PreLoadingLinearLayoutManager(final Context context, final int pages) {
super(context);
this.mPages = pages;
}
public PreLoadingLinearLayoutManager(final Context context, final int orientation, final boolean
reverseLayout) {
super(context, orientation, reverseLayout);
}
@Override
public void setOrientation(final int orientation) {
super.setOrientation(orientation);
mOrientationHelper = null;
}
/**
* Set the number of pages of layout that will be preloaded off-screen,
GoalKicker.com – Android™ Notes for Professionals 107
* a page being a pixel measure equivalent to the on-screen size of the
* recycler view.
* @param pages the number of pages; can be {@code 0} to disable preloading
*/
public void setPages(final int pages) {
this.mPages = pages;
}
@Override
protected int getExtraLayoutSpace(final RecyclerView.State state) {
if (mOrientationHelper == null) {
mOrientationHelper = OrientationHelper.createOrientationHelper(this, getOrientation());
}
return mOrientationHelper.getTotalSpace() * mPages;
}
}
Section 16.3: RecyclerView with DataBinding
Here is a generic ViewHolder class that you can use with any DataBinding layout. Here an instance of particular
ViewDataBinding class is created using the inflated View object and DataBindingUtil utility class.
import android.databinding.DataBindingUtil;
import android.support.v7.widget.RecyclerView;
import android.view.View;
public class BindingViewHolder<T> extends RecyclerView.ViewHolder{
private final T binding;
public BindingViewHolder(View itemView) {
super(itemView);
binding = (T)DataBindingUtil.bind(itemView);
}
public T getBinding() {
return binding;
}
}
After creating this class you can use the <layout> in your layout file to enable databinding for that layout like this:
file name: my_item.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="item"
type="ItemModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
GoalKicker.com – Android™ Notes for Professionals 108
android:text="@{item.itemLabel}" />
</LinearLayout>
</layout>
and here is your sample dataModel:
public class ItemModel {
public String itemLabel;
}
By default, Android Data Binding library generates a ViewDataBinding class based on the layout file name,
converting it to Pascal case and suffixing "Binding" to it. For this example it would be MyItemBinding for the layout
file my_item.xml. That Binding class would also have a setter method to set the object defined as data in the layout
file(ItemModel for this example).
Now that we have all the pieces we can implement our adapter like this:
class MyAdapter extends RecyclerView.Adapter<BindingViewHolder<MyItemBinding>>{
ArrayList<ItemModel> items = new ArrayList<>();
public MyAdapter(ArrayList<ItemModel> items) {
this.items = items;
}
@Override public BindingViewHolder<MyItemBinding> onCreateViewHolder(ViewGroup parent, int
viewType) {
return new
BindingViewHolder<>(LayoutInflater.from(parent.getContext()).inflate(R.layout.my_item, parent,
false));
}
@Override public void onBindViewHolder(BindingViewHolder<ItemModel> holder, int position) {
holder.getBinding().setItemModel(items.get(position));
holder.getBinding().executePendingBindings();
}
@Override public int getItemCount() {
return items.size();
}
}
Section 16.4: Animate data change
RecyclerView will perform a relevant animation if any of the "notify" methods are used except for
notifyDataSetChanged; this includes notifyItemChanged, notifyItemInserted, notifyItemMoved,
notifyItemRemoved, etc.
The adapter should extend this class instead of RecyclerView.Adapter.
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import java.util.List;
public abstract class AnimatedRecyclerAdapter<T, VH extends RecyclerView.ViewHolder>
extends RecyclerView.Adapter<VH> {
protected List<T> models;
GoalKicker.com – Android™ Notes for Professionals 109
protected AnimatedRecyclerAdapter(@NonNull List<T> models) {
this.models = models;
}
//Set new models.
public void setModels(@NonNull final List<T> models) {
applyAndAnimateRemovals(models);
applyAndAnimateAdditions(models);
applyAndAnimateMovedItems(models);
}
//Remove an item at position and notify changes.
private T removeItem(int position) {
final T model = models.remove(position);
notifyItemRemoved(position);
return model;
}
//Add an item at position and notify changes.
private void addItem(int position, T model) {
models.add(position, model);
notifyItemInserted(position);
}
//Move an item at fromPosition to toPosition and notify changes.
private void moveItem(int fromPosition, int toPosition) {
final T model = models.remove(fromPosition);
models.add(toPosition, model);
notifyItemMoved(fromPosition, toPosition);
}
//Remove items that no longer exist in the new models.
private void applyAndAnimateRemovals(@NonNull final List<T> newTs) {
for (int i = models.size() - 1; i >= 0; i--) {
final T model = models.get(i);
if (!newTs.contains(model)) {
removeItem(i);
}
}
}
//Add items that do not exist in the old models.
private void applyAndAnimateAdditions(@NonNull final List<T> newTs) {
for (int i = 0, count = newTs.size(); i < count; i++) {
final T model = newTs.get(i);
if (!models.contains(model)) {
addItem(i, model);
}
}
}
//Move items that have changed their position.
private void applyAndAnimateMovedItems(@NonNull final List<T> newTs) {
for (int toPosition = newTs.size() - 1; toPosition >= 0; toPosition--) {
final T model = newTs.get(toPosition);
final int fromPosition = models.indexOf(model);
if (fromPosition >= 0 && fromPosition != toPosition) {
moveItem(fromPosition, toPosition);
}
}
}
}
GoalKicker.com – Android™ Notes for Professionals 110
You should NOT use the same List for setModels and List in the adapter.
You declare models as global variables. DataModel is a dummy class only.
private List<DataModel> models;
private YourAdapter adapter;
Initialize models before pass it to adapter. YourAdapter is the implementation of AnimatedRecyclerAdapter.
models = new ArrayList<>();
//Add models
models.add(new DataModel());
//Do NOT pass the models directly. Otherwise, when you modify global models,
//you will also modify models in adapter.
//adapter = new YourAdapter(models); <- This is wrong.
adapter = new YourAdapter(new ArrayList(models));
Call this after you have updated your global models.
adapter.setModels(new ArrayList(models));
If you do not override equals, all the comparison is compared by reference.
Example using SortedList
Android introduced the SortedList class soon after RecyclerView was introduced. This class handles all 'notify'
method calls to the RecyclerView.Adapter to ensure proper animation, and even allows batching multiple
changes, so the animations don't jitter.
import android.support.v7.util.SortedList;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.util.SortedListAdapterCallback;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private SortedList<DataModel> mSortedList;
class ViewHolder extends RecyclerView.ViewHolder {
TextView text;
CheckBox checkBox;
ViewHolder(View itemView){
super(itemView);
//Initiate your code here...
}
void setDataModel(DataModel model) {
//Update your UI with the data model passed here...
GoalKicker.com – Android™ Notes for Professionals 111
text.setText(modle.getText());
checkBox.setChecked(model.isChecked());
}
}
public MyAdapter() {
mSortedList = new SortedList<>(DataModel.class, new
SortedListAdapterCallback<DataModel>(this) {
@Override
public int compare(DataModel o1, DataModel o2) {
//This gets called to find the ordering between objects in the array.
if (o1.someValue() < o2.someValue()) {
return -1;
} else if (o1.someValue() > o2.someValue()) {
return 1;
} else {
return 0;
}
}
@Override
public boolean areContentsTheSame(DataModel oldItem, DataModel newItem) {
//This is to see of the content of this object has changed. These items are only
considered equal if areItemsTheSame() returned true.
//If this returns false, onBindViewHolder() is called with the holder containing the
item, and the item's position.
return oldItem.getText().equals(newItem.getText()) && oldItem.isChecked() ==
newItem.isChecked();
}
@Override
public boolean areItemsTheSame(DataModel item1, DataModel item2) {
//Checks to see if these two items are the same. If not, it is added to the list,
otherwise, check if content has changed.
return item1.equals(item2);
}
});
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = //Initiate your item view here.
return new ViewHolder(itemView);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
//Just update the holder with the object in the sorted list from the given position
DataModel model = mSortedList.get(position);
if (model != null) {
holder.setDataModel(model);
}
}
@Override
public int getItemCount() {
return mSortedList.size();
}
public void resetList(List<DataModel> models) {
//If you are performing multiple changes, use the batching methods to ensure proper
GoalKicker.com – Android™ Notes for Professionals 112
animation.
mSortedList.beginBatchedUpdates();
mSortedList.clear();
mSortedList.addAll(models);
mSortedList.endBatchedUpdates();
}
//The following methods each modify the data set and automatically handles calling the
appropriate 'notify' method on the adapter.
public void addModel(DataModel model) {
mSortedList.add(model);
}
public void addModels(List<DataModel> models) {
mSortedList.addAll(models);
}
public void clear() {
mSortedList.clear();
}
public void removeModel(DataModel model) {
mSortedList.remove(model);
}
public void removeModelAt(int i) {
mSortedList.removeItemAt(i);
}
}
Section 16.5: Popup menu with recyclerView
put this code inside your ViewHolder
note: In this code I am using btnExpand click-event, for whole recyclerview click event you can set listener to
itemView object.
public class MyViewHolder extends RecyclerView.ViewHolder{
CardView cv;
TextView recordName, visibleFile, date, time;
Button btnIn, btnExpand;
public MyViewHolder(final View itemView) {
super(itemView);
cv = (CardView)itemView.findViewById(R.id.cardview);
recordName = (TextView)itemView.findViewById(R.id.tv_record);
visibleFile = (TextView)itemView.findViewById(R.id.visible_file);
date = (TextView)itemView.findViewById(R.id.date);
time = (TextView)itemView.findViewById(R.id.time);
btnIn = (Button)itemView.findViewById(R.id.btn_in_out);
btnExpand = (Button) itemView.findViewById(R.id.btn_expand);
btnExpand.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu popup = new PopupMenu(btnExpand.getContext(), itemView);
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
GoalKicker.com – Android™ Notes for Professionals 113
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
moveFile(recordName.getText().toString(),
getAdapterPosition());
return true;
case R.id.action_play:
String valueOfPath = recordName.getText().toString();
Intent intent = new Intent();
intent.setAction(android.content.Intent.ACTION_VIEW);
File file = new File(valueOfPath);
intent.setDataAndType(Uri.fromFile(file), "audio/*");
context.startActivity(intent);
return true;
case R.id.action_share:
String valueOfPath = recordName.getText().toString();
File filee = new File(valueOfPath);
try {
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.setType("audio/*");
sendIntent.putExtra(Intent.EXTRA_STREAM,
Uri.fromFile(filee));
context.startActivity(sendIntent);
} catch (NoSuchMethodError | IllegalArgumentException |
NullPointerException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
return true;
default:
return false;
}
}
});
// here you can inflate your menu
popup.inflate(R.menu.my_menu_item);
popup.setGravity(Gravity.RIGHT);
// if you want icon with menu items then write this try-catch block.
try {
Field mFieldPopup=popup.getClass().getDeclaredField("mPopup");
mFieldPopup.setAccessible(true);
MenuPopupHelper mPopup = (MenuPopupHelper) mFieldPopup.get(popup);
mPopup.setForceShowIcon(true);
} catch (Exception e) {
}
popup.show();
}
});
}
}
alternative way to show icons in menu
try {
Field[] fields = popup.getClass().getDeclaredFields();
for (Field field : fields) {
GoalKicker.com – Android™ Notes for Professionals 114
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popup);
Class<?> classPopupHelper = Class.forName(menuPopupHelper
.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod(
"setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Exception e) {
}
Here is the output:
Section 16.6: Using several ViewHolders with ItemViewType
Sometimes a RecyclerView will need to use several types of Views to be displayed in the list shown in the UI, and
each View needs a different layout xml to be inflated.
For this issue, you may use different ViewHolders in single Adapter, by using a special method in RecyclerView -
getItemViewType(int position).
Below is example of using two ViewHolders:
1. A ViewHolder for displaying list entries
2. A ViewHolder for displaying multiple header views
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(context).inflate(viewType, parent, false);
return ViewHolder.create(itemView, viewType);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final Item model = this.items.get(position);
((ViewHolder) holder).bind(model);
}
@Override
public int getItemViewType(int position) {
GoalKicker.com – Android™ Notes for Professionals 115
return inSearchState ? R.layout.item_header : R.layout.item_entry;
}
abstract class ViewHolder {
abstract void bind(Item model);
public static ViewHolder create(View v, int viewType) {
return viewType == R.layout.item_header ? new HeaderViewHolder(v) :new
EntryViewHolder(v);
}
}
static class EntryViewHolder extends ViewHolder {
private View v;
public EntryViewHolder(View v) {
this.v = v;
}
@Override public void bind(Item model) {
// Bind item data to entry view.
}
}
static class HeaderViewHolder extends ViewHolder {
private View v;
public HeaderViewHolder(View v) {
this.v = v;
}
@Override public void bind(Item model) {
// Bind item data to header view.
}
}
Section 16.7: Filter items inside RecyclerView with a
SearchView
add filter method in RecyclerView.Adapter:
public void filter(String text) {
if(text.isEmpty()){
items.clear();
items.addAll(itemsCopy);
} else{
ArrayList<PhoneBookItem> result = new ArrayList<>();
text = text.toLowerCase();
for(PhoneBookItem item: itemsCopy){
//match by name or phone
if(item.name.toLowerCase().contains(text) ||
item.phone.toLowerCase().contains(text)){
result.add(item);
}
}
items.clear();
items.addAll(result);
}
notifyDataSetChanged();
GoalKicker.com – Android™ Notes for Professionals 116
}
itemsCopy is initialized in adapter's constructor like itemsCopy.addAll(items).
If you do so, just call filter from OnQueryTextListener from SearchView:
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
adapter.filter(query);
return true;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.filter(newText);
return true;
}
});
Section 16.8: Drag&Drop and Swipe with RecyclerView
You can implement the swipe-to-dismiss and drag-and-drop features with the RecyclerView without using 3rd party
libraries.
Just use the ItemTouchHelper class included in the RecyclerView support library.
Instantiate the ItemTouchHelper with the SimpleCallback callback and depending on which functionality you
support, you should override onMove(RecyclerView, ViewHolder, ViewHolder) and / or onSwiped(ViewHolder,
int)and and finally attach to your RecyclerView.
ItemTouchHelper.SimpleCallback simpleItemTouchCallback = new ItemTouchHelper.SimpleCallback(0,
ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int swipeDir) {
// remove item from adapter
}
@Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
final int fromPos = viewHolder.getAdapterPosition();
final int toPos = target.getAdapterPosition();
// move item in `fromPos` to `toPos` in adapter.
return true;// true if moved, false otherwise
}
};
ItemTouchHelper itemTouchHelper = new ItemTouchHelper(simpleItemTouchCallback);
itemTouchHelper.attachToRecyclerView(recyclerView);
It's worth mentioning that SimpleCallback constructor applies the same swiping strategy to all items in the
RecyclerView. It's possible in any case to update the default swiping direction for specific items by simply
overriding method getSwipeDirs(RecyclerView, ViewHolder).
Let's suppose for example that our RecyclerView includes a HeaderViewHolder and that we obviously don't want to
apply swiping to it. It will be enough to override getSwipeDirs as follows:
GoalKicker.com – Android™ Notes for Professionals 117
@Override
public int getSwipeDirs(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
if (viewHolder instanceof HeaderViewHolder) {
// no swipe for header
return 0;
}
// default swipe for all other items
return super.getSwipeDirs(recyclerView, viewHolder);
}
Section 16.9: Show default view till items load or when data is
not available
Screenshot
Adapter Class
private class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
final int EMPTY_VIEW = 77777;
List<CustomData> datalist = new ArrayList<>();
MyAdapter() {
super();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater layoutInflater = LayoutInflater.from(parent.getContext());
GoalKicker.com – Android™ Notes for Professionals 118
if (viewType == EMPTY_VIEW) {
return new EmptyView(layoutInflater.inflate(R.layout.nothing_yet, parent, false));
} else {
return new ItemView(layoutInflater.inflate(R.layout.my_item, parent, false));
}
}
@SuppressLint("SetTextI18n")
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == EMPTY_VIEW) {
EmptyView emptyView = (EmptyView) holder;
emptyView.primaryText.setText("No data yet");
emptyView.secondaryText.setText("You're doing good !");
emptyView.primaryText.setCompoundDrawablesWithIntrinsicBounds(null, new
IconicsDrawable(getActivity()).icon(FontAwesome.Icon.faw_ticket).sizeDp(48).color(Color.DKGRAY),
null, null);
} else {
ItemView itemView = (ItemView) holder;
// Bind data to itemView
}
}
@Override
public int getItemCount() {
return datalist.size() > 0 ? datalist.size() : 1;
}
@Override
public int getItemViewType(int position) {
if datalist.size() == 0) {
return EMPTY_VIEW;
}
return super.getItemViewType(position);
}
}
nothing_yet.xml
<?xml version="1.0" encoding="utf-8"?>
<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:layout_gravity="center"
android:orientation="vertical"
android:paddingBottom="100dp"
android:paddingTop="100dp">
<TextView
android:id="@+id/nothingPrimary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:drawableTint="@android:color/secondary_text_light"
android:drawableTop="@drawable/ic_folder_open_black_24dp"
android:enabled="false"
android:fontFamily="sans-serif-light"
android:text="No Item's Yet"
GoalKicker.com – Android™ Notes for Professionals 119
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/secondary_text_light"
android:textSize="40sp"
tools:targetApi="m" />
<TextView
android:id="@+id/nothingSecondary"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:enabled="false"
android:fontFamily="sans-serif-condensed"
android:text="You're doing good !"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@android:color/tertiary_text_light" />
</LinearLayout>
I'm using FontAwesome with Iconics Library for the images. Add this to your app level build.gradle file.
compile 'com.mikepenz:fontawesome-typeface:4.6.0.3@aar'
compile 'com.mikepenz:iconics-core:2.8.1@aar'
Section 16.10: Add header/footer to a RecyclerView
This is a sample adapter code.
public class SampleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int FOOTER_VIEW = 1;
// Define a view holder for Footer view
public class FooterViewHolder extends ViewHolder {
public FooterViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Do whatever you want on clicking the item
}
});
}
}
// Now define the viewholder for Normal list item
public class NormalViewHolder extends ViewHolder {
public NormalViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// Do whatever you want on clicking the normal items
}
});
}
}
// And now in onCreateViewHolder you have to pass the correct view
// while populating the list item.
GoalKicker.com – Android™ Notes for Professionals 120
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v;
if (viewType == FOOTER_VIEW) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_footer, parent,
false);
FooterViewHolder vh = new FooterViewHolder(v);
return vh;
}
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_normal, parent, false);
NormalViewHolder vh = new NormalViewHolder(v);
return vh;
}
// Now bind the viewholders in onBindViewHolder
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
try {
if (holder instanceof NormalViewHolder) {
NormalViewHolder vh = (NormalViewHolder) holder;
vh.bindView(position);
} else if (holder instanceof FooterViewHolder) {
FooterViewHolder vh = (FooterViewHolder) holder;
}
} catch (Exception e) {
e.printStackTrace();
}
}
// Now the critical part. You have return the exact item count of your list
// I've only one footer. So I returned data.size() + 1
// If you've multiple headers and footers, you've to return total count
// like, headers.size() + data.size() + footers.size()
@Override
public int getItemCount() {
if (data == null) {
return 0;
}
if (data.size() == 0) {
//Return 1 here to show nothing
return 1;
}
// Add extra view to show the footer view
return data.size() + 1;
}
// Now define getItemViewType of your own.
@Override
public int getItemViewType(int position) {
GoalKicker.com – Android™ Notes for Professionals 121
if (position == data.size()) {
// This is where we'll add footer.
return FOOTER_VIEW;
}
return super.getItemViewType(position);
}
// So you're done with adding a footer and its action on onClick.
// Now set the default ViewHolder for NormalViewHolder
public class ViewHolder extends RecyclerView.ViewHolder {
// Define elements of a row here
public ViewHolder(View itemView) {
super(itemView);
// Find view by ID and initialize here
}
public void bindView(int position) {
// bindView() method to implement actions
}
}
}
Here's a good read about the implementation of RecyclerView with header and footer.
Alternate method:
While the above answer will work you can use this approach as well using a recycler view using a NestedScrollView
.You can add a layout for header using the following approach:
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<include
layout="@layout/drawer_view_header"
android:id="@+id/navigation_header"/>
<android.support.v7.widget.RecyclerView
android:layout_below="@id/navigation_header"
android:id="@+id/followers_list"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</RelativeLayout>
</android.support.v4.widget.NestedScrollView>
Or you may also use a LinearLayout with vertical alignment in your NestedScrollView.
Note: This will only work with RecyclerView above 23.2.0
compile 'com.android.support:recyclerview-v7:23.2.0'
GoalKicker.com – Android™ Notes for Professionals 122
Section 16.11: Endless Scrolling in Recycleview
Here I have shared a code snippet for implementing endless scrolling in recycle view.
Step 1: First make a one abstract method in Recycleview adapter like below.
public abstract class ViewAllCategoryAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
public abstract void load();
}
Step 2: Now override onBindViewHolder and getItemCount() method of ViewAllCategoryAdapter class and call
Load() method like below.
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
if ((position >= getItemCount() - 1)) {
load();
}
}
@Override
public int getItemCount() {
return YOURLIST.size();
}
Step 3: Now every backend logic is complete now it's time to execute this logic.It's simple you can override load
method where you create object of your adapter.this method is automatically call while user reach at end of the
listing.
adapter = new ViewAllCategoryAdapter(CONTEXT, YOURLIST) {
@Override
public void load() {
/* do your stuff here */
/* This method is automatically call while user reach at end of your list. */
}
};
recycleCategory.setAdapter(adapter);
Now load() method automatically call while user scroll at end of list.
Best Luck
Section 16.12: Add divider lines to RecyclerView items
Just add these lines to the initialization
RecyclerView mRecyclerView = (RecyclerView) view.findViewById(recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(),
DividerItemDecoration.VERTICAL));
Add an adapter and call .notifyDataSetChanged(); as usual !
This is not an inbuilt feature of Recyclerview but added in the support libraries. So don't forget to include this in
your app level build.gradle file
GoalKicker.com – Android™ Notes for Professionals 123
compile "com.android.support:appcompat-v7:25.3.1"
compile "com.android.support:recyclerview-v7:25.3.1"
Multiple ItemDecorations can be added to a single RecyclerView.
Changing divider color :
It's pretty easy to set an color for a itemDecoration.
1. step is: creating a divider.xml file which is located on drawable folder
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="line">
<size
android:width="1px"
android:height="1px"/>
<solid android:color="@color/divider_color"/>
</shape>
2. step is: setting drawable
// Get drawable object
Drawable mDivider = ContextCompat.getDrawable(m_jContext, R.drawable.divider);
// Create a DividerItemDecoration whose orientation is Horizontal
DividerItemDecoration hItemDecoration = new DividerItemDecoration(m_jContext,
DividerItemDecoration.HORIZONTAL);
// Set the drawable on it
hItemDecoration.setDrawable(mDivider);
// Create a DividerItemDecoration whose orientation is vertical
DividerItemDecoration vItemDecoration = new DividerItemDecoration(m_jContext,
DividerItemDecoration.VERTICAL);
// Set the drawable on it
vItemDecoration.setDrawable(mDivider);
GoalKicker.com – Android™ Notes for Professionals 124
GoalKicker.com – Android™ Notes for Professionals 125
Chapter 17: RecyclerView Decorations
Parameter Details
decoration the item decoration to add to the RecyclerView
index the index in the list of decorations for this RecyclerView. This is the order in which getItemOffset and
onDraw are called. Later calls might overdraw previous ones.
Section 17.1: Add divider to RecyclerView
First of all you need to create a class which extends RecyclerView.ItemDecoration :
public class SimpleBlueDivider extends RecyclerView.ItemDecoration {
private Drawable mDivider;
public SimpleBlueDivider(Context context) {
mDivider = context.getResources().getDrawable(R.drawable.divider_blue);
}
@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
//divider padding give some padding whatever u want or disable
int left =parent.getPaddingLeft()+80;
int right = parent.getWidth() - parent.getPaddingRight()-30;
int childCount = parent.getChildCount();
for (int i = 0; i < childCount; i++) {
View child = parent.getChildAt(i);
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
int top = child.getBottom() + params.bottomMargin;
int bottom = top + mDivider.getIntrinsicHeight();
mDivider.setBounds(left, top, right, bottom);
mDivider.draw(c);
}
}
}
Add divider_blue.xml to your drawable folder :
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<size android:width="1dp" android:height="4dp" />
<solid android:color="#AA123456" />
</shape>
Then use it like :
recyclerView.addItemDecoration(new SimpleBlueDivider(context));
The result will be like :
GoalKicker.com – Android™ Notes for Professionals 126
This image is just an example how dividers working , if you want to follow Material Design specs when adding
dividers please take a look at this link : dividers and thanks @Brenden Kromhout by providing link .
GoalKicker.com – Android™ Notes for Professionals 127
Section 17.2: Drawing a Separator
This will draw a line at the bottom of every view but the last to act as a separator between items.
public class SeparatorDecoration extends RecyclerView.ItemDecoration {
private final Paint mPaint;
private final int mAlpha;
public SeparatorDecoration(@ColorInt int color, float width) {
mPaint = new Paint();
mPaint.setColor(color);
mPaint.setStrokeWidth(width);
mAlpha = mPaint.getAlpha();
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State
state) {
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
view.getLayoutParams();
// we retrieve the position in the list
final int position = params.getViewAdapterPosition();
// add space for the separator to the bottom of every view but the last one
if (position < state.getItemCount()) {
outRect.set(0, 0, 0, (int) mPaint.getStrokeWidth()); // left, top, right, bottom
} else {
outRect.setEmpty(); // 0, 0, 0, 0
}
}
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
// a line will draw half its size to top and bottom,
// hence the offset to place it correctly
final int offset = (int) (mPaint.getStrokeWidth() / 2);
// this will iterate over every visible view
for (int i = 0; i < parent.getChildCount(); i++) {
final View view = parent.getChildAt(i);
final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams)
view.getLayoutParams();
// get the position
final int position = params.getViewAdapterPosition();
// and finally draw the separator
if (position < state.getItemCount()) {
// apply alpha to support animations
mPaint.setAlpha((int) (view.getAlpha() * mAlpha));
float positionY = view.getBottom() + offset + view.getTranslationY();
// do the drawing
c.drawLine(view.getLeft() + view.getTranslationX(),
positionY,
view.getRight() + view.getTranslationX(),
positionY,
mPaint);
}
GoalKicker.com – Android™ Notes for Professionals 128
}
}
}
Section 17.3: How to add dividers using and
DividerItemDecoration
The DividerItemDecoration is a RecyclerView.ItemDecoration that can be used as a divider between items.
DividerItemDecoration mDividerItemDecoration = new DividerItemDecoration(context,
mLayoutManager.getOrientation());
recyclerView.addItemDecoration(mDividerItemDecoration);
It supports both orientation using DividerItemDecoration.VERTICAL and DividerItemDecoration.HORIZONTAL.
Section 17.4: Per-item margins with ItemDecoration
You can use a RecyclerView.ItemDecoration to put extra margins around each item in a RecyclerView. This can in
some cases clean up both your adapter implementation and your item view XML.
public class MyItemDecoration
extends RecyclerView.ItemDecoration {
private final int extraMargin;
@Override
public void getItemOffsets(Rect outRect, View view,
RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view);
// It's easy to put extra margin on the last item...
if (position + 1 == parent.getAdapter().getItemCount()) {
outRect.bottom = extraMargin; // unit is px
}
// ...or you could give each item in the RecyclerView different
// margins based on its position...
if (position % 2 == 0) {
outRect.right = extraMargin;
} else {
outRect.left = extraMargin;
}
// ...or based on some property of the item itself
MyListItem item = parent.getAdapter().getItem(position);
if (item.isFirstItemInSection()) {
outRect.top = extraMargin;
}
}
public MyItemDecoration(Context context) {
extraMargin = context.getResources()
.getDimensionPixelOffset(R.dimen.extra_margin);
}
}
To enable the decoration, simply add it to your RecyclerView:
GoalKicker.com – Android™ Notes for Professionals 129
// in your onCreate()
RecyclerView rv = (RecyclerView) findItemById(R.id.myList);
rv.addItemDecoration(new MyItemDecoration(context));
Section 17.5: ItemOsetDecoration for GridLayoutManager in
RecycleView
Following example will help to give equal space to an item in GridLayout.
ItemOffsetDecoration.java
public class ItemOffsetDecoration extends RecyclerView.ItemDecoration {
private int mItemOffset;
private int spanCount = 2;
public ItemOffsetDecoration(int itemOffset) {
mItemOffset = itemOffset;
}
public ItemOffsetDecoration(@NonNull Context context, @DimenRes int itemOffsetId) {
this(context.getResources().getDimensionPixelSize(itemOffsetId));
}
@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent,
RecyclerView.State state) {
super.getItemOffsets(outRect, view, parent, state);
int position = parent.getChildLayoutPosition(view);
GridLayoutManager manager = (GridLayoutManager) parent.getLayoutManager();
if (position < manager.getSpanCount())
outRect.top = mItemOffset;
if (position % 2 != 0) {
outRect.right = mItemOffset;
}
outRect.left = mItemOffset;
outRect.bottom = mItemOffset;
}
}
You can call ItemDecoration like below code.
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
GridLayoutManager lLayout = new GridLayoutManager(getActivity(), 2);
ItemOffsetDecoration itemDecoration = new ItemOffsetDecoration(mActivity, R.dimen.item_offset);
recyclerView.addItemDecoration(itemDecoration);
recyclerView.setLayoutManager(lLayout);
and example item offset
GoalKicker.com – Android™ Notes for Professionals 130
<dimen name="item_offset">5dp</dimen>
GoalKicker.com – Android™ Notes for Professionals 131
Chapter 18: RecyclerView onClickListeners
Section 18.1: Kotlin and RxJava example
First example reimplemented in Kotlin and using RxJava for cleaner interaction.
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.support.v7.widget.RecyclerView
import rx.subjects.PublishSubject
public class SampleAdapter(private val items: Array<String>) :
RecyclerView.Adapter<SampleAdapter.ViewHolder>() {
// change to different subjects from rx.subjects to get different behavior
// BehaviorSubject for example allows to receive last event on subscribe
// PublishSubject sends events only after subscribing on the other hand which is desirable for
clicks
public val itemClickStream: PublishSubject<View> = PublishSubject.create()
override fun getItemCount(): Int {
return items.size
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder? {
val v = LayoutInflater.from(parent.getContext()).inflate(R.layout.text_row_item, parent,
false);
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
holder.bind(items[position])
}
public inner class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
private val textView: TextView by lazy { view.findViewById(R.id.textView) as TextView }
init {
view.setOnClickListener { v -> itemClickStream.onNext(v) }
}
fun bind(text: String) {
textView.text = text
}
}
}
Usage is quite simple then. It's possible to subscribe on separate thread using RxJava facilities.
val adapter = SampleAdapter(arrayOf("Hello", "World"))
adapter.itemClickStream.subscribe { v ->
if (v.id == R.id.textView) {
// do something
}
}
GoalKicker.com – Android™ Notes for Professionals 132
Section 18.2: RecyclerView Click listener
public class RecyclerTouchListener implements RecyclerView.OnItemTouchListener {
private GestureDetector gestureDetector;
private RecyclerTouchListener.ClickListener clickListener;
public RecyclerTouchListener(Context context, final RecyclerView recyclerView, final
RecyclerTouchListener.ClickListener clickListener) {
this.clickListener = clickListener;
gestureDetector = new GestureDetector(context, new
GestureDetector.SimpleOnGestureListener() {
@Override
public boolean onSingleTapUp(MotionEvent e) {
return true;
}
@Override
public void onLongPress(MotionEvent e) {
View child = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null) {
clickListener.onLongClick(child, recyclerView.getChildPosition(child));
}
}
});
}
@Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {
View child = rv.findChildViewUnder(e.getX(), e.getY());
if (child != null && clickListener != null && gestureDetector.onTouchEvent(e)) {
clickListener.onClick(child, rv.getChildPosition(child));
}
return false;
}
@Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
@Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
public interface ClickListener {
void onLongClick(View child, int childPosition);
void onClick(View child, int childPosition);
}
}
In MainActivity
RecyclerView recyclerView =(RecyclerView) findViewById(R.id.recyclerview);
recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getActivity(),recyclerView, new
RecyclerTouchListener.ClickListener() {
@Override
public void onLongClick(View child, int childPosition) {
GoalKicker.com – Android™ Notes for Professionals 133
}
@Override
public void onClick(View child, int childPosition) {
}
}));
Section 18.3: Another way to implement Item Click Listener
Another way to implement item click listener is to use interface with several methods, the number of which is equal
to the number of clickable views, and use overrided click listeners as you can see below. This method is more
flexible, because you can set click listeners to different views and quite easy control the click logic separately for
each.
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.CustomHolder> {
private ArrayList<Object> mObjects;
private ClickInterface mClickInterface;
public interface ClickInterface {
void clickEventOne(Object obj);
void clickEventTwo(Object obj1, Object obj2);
}
public void setClickInterface(ClickInterface clickInterface) {
mClickInterface = clickInterface;
}
public CustomAdapter(){
mList = new ArrayList<>();
}
public void addItems(ArrayList<Object> objects) {
mObjects.clear();
mObjects.addAll(objects);
notifyDataSetChanged();
}
@Override
public CustomHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item, parent, false);
return new CustomHolder(v);
}
@Override
public void onBindViewHolder(CustomHolder holder, int position) {
//make all even positions not clickable
holder.firstClickListener.setClickable(position%2==0);
holder.firstClickListener.setPosition(position);
holder.secondClickListener.setPosition(position);
}
private class FirstClickListener implements View.OnClickListener {
private int mPosition;
private boolean mClickable;
GoalKicker.com – Android™ Notes for Professionals 134
void setPosition(int position) {
mPosition = position;
}
void setClickable(boolean clickable) {
mPosition = position;
}
@Override
public void onClick(View v) {
if(mClickable) {
mClickInterface.clickEventOne(mObjects.get(mPosition));
}
}
}
private class SecondClickListener implements View.OnClickListener {
private int mPosition;
void setPosition(int position) {
mPosition = position;
}
@Override
public void onClick(View v) {
mClickInterface.clickEventTwo(mObjects.get(mPosition), v);
}
}
@Override
public int getItemCount() {
return mObjects.size();
}
protected class CustomHolder extends RecyclerView.ViewHolder {
FirstClickListener firstClickListener;
SecondClickListener secondClickListener;
View v1, v2;
public DialogHolder(View itemView) {
super(itemView);
v1 = itemView.findViewById(R.id.v1);
v2 = itemView.findViewById(R.id.v2);
firstClickListener = new FirstClickListener();
secondClickListener = new SecondClickListener();
v1.setOnClickListener(firstClickListener);
v2.setOnClickListener(secondClickListener);
}
}
}
And when you have an instance of adapter, you can set your click listener which listens to clicking on each of the
views:
customAdapter.setClickInterface(new CustomAdapter.ClickInterface {
@Override
public void clickEventOne(Object obj) {
// Your implementation here
}
@Override
GoalKicker.com – Android™ Notes for Professionals 135
public void clickEventTwo(Object obj1, Object obj2) {
// Your implementation here
}
});
Section 18.4: New Example
public class SampleAdapter extends RecyclerView.Adapter<SampleAdapter.ViewHolder> {
private String[] mDataSet;
private OnRVItemClickListener mListener;
/**
* Provide a reference to the type of views that you are using (custom ViewHolder)
*/
public static class ViewHolder extends RecyclerView.ViewHolder {
private final TextView textView;
public ViewHolder(View v) {
super(v);
// Define click listener for the ViewHolder's View.
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) { // handle click events here
Log.d(TAG, "Element " + getPosition() + " clicked.");
mListener.onRVItemClicked(getPosition(),v); //set callback
}
});
textView = (TextView) v.findViewById(R.id.textView);
}
public TextView getTextView() {
return textView;
}
}
/**
* Initialize the dataset of the Adapter.
*
* @param dataSet String[] containing the data to populate views to be used by RecyclerView.
*/
public SampleAdapter(String[] dataSet) {
mDataSet = dataSet;
}
// Create new views (invoked by the layout manager)
@Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
// Create a new view.
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.text_row_item, viewGroup, false);
return new ViewHolder(v);
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(ViewHolder viewHolder, final int position) {
// Get element from your dataset at this position and replace the contents of the view
// with that element
viewHolder.getTextView().setText(mDataSet[position]);
GoalKicker.com – Android™ Notes for Professionals 136
}
// Return the size of your dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mDataSet.length;
}
public void setOnRVClickListener(OnRVItemClickListener) {
mListener = OnRVItemClickListener;
}
public interface OnRVItemClickListener {
void onRVItemClicked(int position, View v);
}
}
Section 18.5: Easy OnLongClick and OnClick Example
First of all, implement your view holder:
implements View.OnClickListener, View.OnLongClickListener
Then, register the listeners as follows:
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
Next, override the listeners as follows:
@Override
public void onClick(View v) {
onclicklistner.onItemClick(getAdapterPosition(), v);
}
@Override
public boolean onLongClick(View v) {
onclicklistner.onItemLongClick(getAdapterPosition(), v);
return true;
}
And finally, add the following code:
public void setOnItemClickListener(onClickListner onclicklistner) {
SampleAdapter.onclicklistner = onclicklistner;
}
public void setHeader(View v) {
this.headerView = v;
}
public interface onClickListner {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
Adaptor demo
package adaptor;
GoalKicker.com – Android™ Notes for Professionals 137
import android.annotation.SuppressLint;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import com.wings.example.recycleview.MainActivity;
import com.wings.example.recycleview.R;
import java.util.ArrayList;
public class SampleAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context context;
private ArrayList<String> arrayList;
private static onClickListner onclicklistner;
private static final int VIEW_HEADER = 0;
private static final int VIEW_NORMAL = 1;
private View headerView;
public SampleAdapter(Context context) {
this.context = context;
arrayList = MainActivity.arrayList;
}
public class HeaderViewHolder extends RecyclerView.ViewHolder {
public HeaderViewHolder(View itemView) {
super(itemView);
}
}
public class ItemViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener,
View.OnLongClickListener {
TextView txt_pos;
SampleAdapter sampleAdapter;
public ItemViewHolder(View itemView, SampleAdapter sampleAdapter) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
txt_pos = (TextView) itemView.findViewById(R.id.txt_pos);
this.sampleAdapter = sampleAdapter;
itemView.setOnClickListener(this);
}
@Override
public void onClick(View v) {
onclicklistner.onItemClick(getAdapterPosition(), v);
}
@Override
public boolean onLongClick(View v) {
onclicklistner.onItemLongClick(getAdapterPosition(), v);
return true;
}
}
public void setOnItemClickListener(onClickListner onclicklistner) {
GoalKicker.com – Android™ Notes for Professionals 138
SampleAdapter.onclicklistner = onclicklistner;
}
public void setHeader(View v) {
this.headerView = v;
}
public interface onClickListner {
void onItemClick(int position, View v);
void onItemLongClick(int position, View v);
}
@Override
public int getItemCount() {
return arrayList.size()+1;
}
@Override
public int getItemViewType(int position) {
return position == 0 ? VIEW_HEADER : VIEW_NORMAL;
}
@SuppressLint("InflateParams")
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
if (viewType == VIEW_HEADER) {
return new HeaderViewHolder(headerView);
} else {
View view =
LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.custom_recycler_row_sample_item,
viewGroup, false);
return new ItemViewHolder(view, this);
}
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
if (viewHolder.getItemViewType() == VIEW_HEADER) {
return;
} else {
ItemViewHolder itemViewHolder = (ItemViewHolder) viewHolder;
itemViewHolder.txt_pos.setText(arrayList.get(position-1));
}
}
}
The example code above can be called by the following code:
sampleAdapter.setOnItemClickListener(new SampleAdapter.onClickListner() {
@Override
public void onItemClick(int position, View v) {
position = position+1;//As we are adding header
Log.e(TAG + "ON ITEM CLICK", position + "");
Snackbar.make(v, "On item click "+position, Snackbar.LENGTH_LONG).show();
}
@Override
public void onItemLongClick(int position, View v) {
position = position+1;//As we are adding header
Log.e(TAG + "ON ITEM LONG CLICK", position + "");
Snackbar.make(v, "On item longclick "+position, Snackbar.LENGTH_LONG).show();
GoalKicker.com – Android™ Notes for Professionals 139
}
});
Section 18.6: Item Click Listeners
To implement an item click listener and/or an item long click listener, you can create an interface in your adapter:
public class CustomAdapter extends RecyclerView.Adapter<CustomAdapter.ViewHolder> {
public interface OnItemClickListener {
void onItemSeleted(int position, View view, CustomObject object);
}
public interface OnItemLongClickListener {
boolean onItemSelected(int position, View view, CustomObject object);
}
public final class ViewHolder extends RecyclerView.ViewHolder {
public ViewHolder(View itemView) {
super(itemView);
final int position = getAdapterPosition();
itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if(mOnItemClickListener != null) {
mOnItemClickListener.onItemSeleted(position, view, mDataSet.get(position));
}
}
});
itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View view) {
if(mOnItemLongClickListener != null) {
return mOnItemLongClickListener.onItemSelected(position, view,
mDataSet.get(position));
}
}
});
}
}
private List<CustomObject> mDataSet;
private OnItemClickListener mOnItemClickListener;
private OnItemLongClickListener mOnItemLongClickListener;
public CustomAdapter(List<CustomObject> dataSet) {
mDataSet = dataSet;
}
@Override
public CustomAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_item_custom, parent, false);
return new ViewHolder(view);
GoalKicker.com – Android™ Notes for Professionals 140
}
@Override
public void onBindViewHolder(CustomAdapter.ViewHolder holder, int position) {
// Bind views
}
@Override
public int getItemCount() {
return mDataSet.size();
}
public void setOnItemClickListener(OnItemClickListener listener) {
mOnItemClickListener = listener;
}
public void setOnItemLongClickListener(OnItemLongClickListener listener) {
mOnItemLongClickListener = listener;
}
}
Then you can set your click listeners after you create an instance of the adapter:
customAdapter.setOnItemClickListener(new CustomAdapter.OnItemClickListener {
@Override
public void onItemSelected(int position, View view, CustomObject object) {
// Your implementation here
}
});
customAdapter.setOnItemLongClickListener(new CustomAdapter.OnItemLongClickListener {
@Override
public boolean onItemSelected(int position, View view, CustomObject object) {
// Your implementation here
return true;
}
});
GoalKicker.com – Android™ Notes for Professionals 141
Chapter 19: RecyclerView and
LayoutManagers
Section 19.1: Adding header view to recyclerview with
gridlayout manager
To add a header to a recyclerview with a gridlayout, first the adapter needs to be told that the header view is the
first position - rather than the standard cell used for the content. Next, the layout manager must be told that the
first position should have a span equal to the *span count of the entire list. *
Take a regular RecyclerView.Adapter class and configure it as follows:
public class HeaderAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int ITEM_VIEW_TYPE_HEADER = 0;
private static final int ITEM_VIEW_TYPE_ITEM = 1;
private List<YourModel> mModelList;
public HeaderAdapter (List<YourModel> modelList) {
mModelList = modelList;
}
public boolean isHeader(int position) {
return position == 0;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
if (viewType == ITEM_VIEW_TYPE_HEADER) {
View headerView = inflater.inflate(R.layout.header, parent, false);
return new HeaderHolder(headerView);
}
View cellView = inflater.inflate(R.layout.gridcell, parent, false);
return new ModelHolder(cellView);
}
@Override
public int getItemViewType(int position) {
return isHeader(position) ? ITEM_VIEW_TYPE_HEADER : ITEM_VIEW_TYPE_ITEM;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder h, int position) {
if (isHeader(position)) {
return;
}
final YourModel model = mModelList.get(position -1 ); // Subtract 1 for header
ModelHolder holder = (ModelHolder) h;
// populate your holder with data from your model as usual
}
@Override
GoalKicker.com – Android™ Notes for Professionals 142
public int getItemCount() {
return _categories.size() + 1; // add one for the header
}
}
Then in the activity/fragment:
final HeaderAdapter adapter = new HeaderAdapter (mModelList);
final GridLayoutManager manager = new GridLayoutManager();
manager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
@Override
public int getSpanSize(int position) {
return adapter.isHeader(position) ? manager.getSpanCount() : 1;
}
});
mRecyclerView.setLayoutManager(manager);
mRecyclerView.setAdapter(adapter);
The same approach can be used add a footer in addition to or instead of a header.
Source: Chiu-Ki Chan's Square Island blog
Section 19.2: GridLayoutManager with dynamic span count
When creating a recyclerview with a gridlayout layout manager you have to specify the span count in the
constructor. Span count refers to the number of columns. This is fairly clunky and doesn't take into account larger
screen sizes or screen orientation. One approach is to create multiple layouts for the various screen sizes. Another
more dynamic approach can be seen below.
First we create a custom RecyclerView class as follows:
public class AutofitRecyclerView extends RecyclerView {
private GridLayoutManager manager;
private int columnWidth = -1;
public AutofitRecyclerView(Context context) {
super(context);
init(context, null);
}
public AutofitRecyclerView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context, attrs);
}
public AutofitRecyclerView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context, attrs);
}
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
int[] attrsArray = {
android.R.attr.columnWidth
};
TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
columnWidth = array.getDimensionPixelSize(0, -1);
array.recycle();
}
GoalKicker.com – Android™ Notes for Professionals 143
manager = new GridLayoutManager(getContext(), 1);
setLayoutManager(manager);
}
@Override
protected void onMeasure(int widthSpec, int heightSpec) {
super.onMeasure(widthSpec, heightSpec);
if (columnWidth > 0) {
int spanCount = Math.max(1, getMeasuredWidth() / columnWidth);
manager.setSpanCount(spanCount);
}
}
}
This class determines how many columns can fit into the recyclerview. To use it you will need to put it into your
layout.xml as follows:
<?xml version="1.0" encoding="utf-8"?>
<com.path.to.your.class.autofitRecyclerView.AutofitRecyclerView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/auto_fit_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="200dp"
android:clipToPadding="false"
/>
Notice that we use the columnWidth attribute. The recyclerview will need it to determine how many columns will fit
into the available space.
In your activity/fragment you just get a reference to the recylerview and set an adapter to it (and any item
decorations or animations that you want to add). DO NOT SET A LAYOUT MANAGER
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.auto_fit_recycler_view);
recyclerView.setAdapter(new MyAdapter());
(where MyAdapter is your adapter class)
You now have a recyclerview that will adjust the spancount (ie columns) to fit the screen size. As a final addition you
might want to center the columns in the recyclerview (by default they are aligned to layout_start). You can do that
by modifying the AutofitRecyclerView class a little. Start by creating an inner class in the recyclerview. This will be a
class that extends from GridLayoutManager. It will add enough padding to the left and right in order to center the
rows:
public class AutofitRecyclerView extends RecyclerView {
// etc see above
private class CenteredGridLayoutManager extends GridLayoutManager {
public CenteredGridLayoutManager(Context context, AttributeSet attrs, int defStyleAttr, int
defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
public CenteredGridLayoutManager(Context context, int spanCount) {
super(context, spanCount);
}
GoalKicker.com – Android™ Notes for Professionals 144
public CenteredGridLayoutManager(Context context, int spanCount, int orientation, boolean
reverseLayout) {
super(context, spanCount, orientation, reverseLayout);
}
@Override
public int getPaddingLeft() {
final int totalItemWidth = columnWidth * getSpanCount();
if (totalItemWidth >= AutofitRecyclerView.this.getMeasuredWidth()) {
return super.getPaddingLeft(); // do nothing
} else {
return Math.round((AutofitRecyclerView.this.getMeasuredWidth() / (1f +
getSpanCount())) - (totalItemWidth / (1f + getSpanCount())));
}
}
@Override
public int getPaddingRight() {
return getPaddingLeft();
}
}
}
Then when you set the LayoutManager in the AutofitRecyclerView use the CenteredGridLayoutManager as follows:
private void init(Context context, AttributeSet attrs) {
if (attrs != null) {
int[] attrsArray = {
android.R.attr.columnWidth
};
TypedArray array = context.obtainStyledAttributes(attrs, attrsArray);
columnWidth = array.getDimensionPixelSize(0, -1);
array.recycle();
}
manager = new CenteredGridLayoutManager(getContext(), 1);
setLayoutManager(manager);
}
And that's it! You have a dynamic spancount, center aligned gridlayoutmanager based recyclerview.
Sources:
Chiu-Ki Chan's Square Island blog
StackOverflow
Section 19.3: Simple list with LinearLayoutManager
This example adds a list of places with image and name by using an ArrayList of custom Place objects as dataset.
Activity layout
The layout of the activity / fragment or where the RecyclerView is used only has to contain the RecyclerView. There
is no ScrollView or a specific layout needed.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
GoalKicker.com – Android™ Notes for Professionals 145
<android.support.v7.widget.RecyclerView
android:id="@+id/my_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
Define the data model
You could use any class or primitive data type as a model, like int, String, float[] or CustomObject. The
RecyclerView will refer to a List of this objects / primitives.
When a list item refers to different data types like text, numbers, images (as in this example with places), it is often
a good idea to use a custom object.
public class Place {
// these fields will be shown in a list item
private Bitmap image;
private String name;
// typical constructor
public Place(Bitmap image, String name) {
this.image = image;
this.name = name;
}
// getters
public Bitmap getImage() {
return image;
}
public String getName() {
return name;
}
}
List item layout
You have to specify a xml layout file that will be used for each list item. In this example, an ImageView is used for the
image and a TextView for the name. The LinearLayout positions the ImageView at the left and the TextView right to
the image.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:id="@+id/image"
android:layout_width="36dp"
android:layout_height="36dp"
android:layout_marginEnd="8dp"
android:layout_marginRight="8dp" />
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
GoalKicker.com – Android™ Notes for Professionals 146
</LinearLayout>
Create a RecyclerView adapter and ViewHolder
Next, you have to inherit the RecyclerView.Adapter and the RecyclerView.ViewHolder. A usual class structure
would be:
public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
// ...
public class ViewHolder extends RecyclerView.ViewHolder {
// ...
}
}
First, we implement the ViewHolder. It only inherits the default constructor and saves the needed views into some
fields:
public class ViewHolder extends RecyclerView.ViewHolder {
private ImageView imageView;
private TextView nameView;
public ViewHolder(View itemView) {
super(itemView);
imageView = (ImageView) itemView.findViewById(R.id.image);
nameView = (TextView) itemView.findViewById(R.id.name);
}
}
The adapter's constructor sets the used dataset:
public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
private List<Place> mPlaces;
public PlaceListAdapter(List<Place> contacts) {
mPlaces = contacts;
}
// ...
}
To use our custom list item layout, we override the method onCreateViewHolder(...). In this example, the layout
file is called place_list_item.xml.
public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
// ...
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(
R.layout.place_list_item,
parent,
false
);
return new ViewHolder(view);
}
// ...
GoalKicker.com – Android™ Notes for Professionals 147
}
In the onBindViewHolder(...), we actually set the views' contents. We get the used model by finding it in the List
at the given position and then set image and name on the ViewHolder's views.
public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
// ...
@Override
public void onBindViewHolder(PlaceListAdapter.ViewHolder viewHolder, int position) {
Place place = mPlaces.get(position);
viewHolder.nameView.setText(place.getName());
viewHolder.imageView.setImageBitmap(place.getImage());
}
// ...
}
We also need to implement getItemCount(), which simply return the List's size.
public class PlaceListAdapter extends RecyclerView.Adapter<PlaceListAdapter.ViewHolder> {
// ...
@Override
public int getItemCount() {
return mPlaces.size();
}
// ...
}
(Generate random data)
For this example, we'll generate some random places.
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
List<Place> places = randomPlaces(5);
// ...
}
private List<Place> randomPlaces(int amount) {
List<Place> places = new ArrayList<>();
for (int i = 0; i < amount; i++) {
places.add(new Place(
BitmapFactory.decodeResource(getResources(), Math.random() > 0.5 ?
R.drawable.ic_account_grey600_36dp :
R.drawable.ic_android_grey600_36dp
),
"Place #" + (int) (Math.random() * 1000)
));
}
return places;
}
Connect the RecyclerView with the PlaceListAdapter and the dataset
GoalKicker.com – Android™ Notes for Professionals 148
Connecting a RecyclerView with an adapter is very easy. You have to set the LinearLayoutManager as layout
manager to achieve the list layout.
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
recyclerView.setAdapter(new PlaceListAdapter(places));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
Done!
Section 19.4: StaggeredGridLayoutManager
1. Create your RecyclerView in your layout xml file:
<android.support.v7.widget.RecyclerView
android:id="@+id/recycleView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
2. Create your Model class for holding your data:
public class PintrestItem {
String url;
public PintrestItem(String url,String name){
this.url=url;
this.name=name;
}
public String getUrl() {
return url;
}
public String getName(){
return name;
}
String name;
}
3. Create a layout file to hold RecyclerView items:
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:id="@+id/imageView"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:id="@+id/name"
android:layout_gravity="center"
android:textColor="@android:color/white"/>
4. Create the adapter class for the RecyclerView:
GoalKicker.com – Android™ Notes for Professionals 149
public class PintrestAdapter extends
RecyclerView.Adapter<PintrestAdapter.PintrestViewHolder>{
private ArrayList<PintrestItem>images;
Picasso picasso;
Context context;
public PintrestAdapter(ArrayList<PintrestItem>images,Context context){
this.images=images;
picasso=Picasso.with(context);
this.context=context;
}
@Override
public PintrestViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view=
LayoutInflater.from(parent.getContext()).inflate(R.layout.pintrest_layout_item,parent,false);
return new PintrestViewHolder(view);
}
@Override
public void onBindViewHolder(PintrestViewHolder holder, int position) {
picasso.load(images.get(position).getUrl()).into(holder.imageView);
holder.tv.setText(images.get(position).getName());
}
@Override
public int getItemCount() {
return images.size();
}
public class PintrestViewHolder extends RecyclerView.ViewHolder{
ImageView imageView;
TextView tv;
public PintrestViewHolder(View itemView) {
super(itemView);
imageView=(ImageView)itemView.findViewById(R.id.imageView);
tv=(TextView)itemView.findViewById(R.id.name);
}
}
}
5. Instantiate the RecyclerView in your activity or fragment:
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.recyclerView);
//Create the instance of StaggeredGridLayoutManager with 2 rows i.e the span count and provide
the orientation
StaggeredGridLayoutManager layoutManager=new new StaggeredGridLayoutManager(2,
StaggeredGridLayoutManager.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
// Create Dummy Data and Add to your List<PintrestItem>
List<PintrestItem>items=new ArrayList<PintrestItem>
items.add(new PintrestItem("url of image you want to show","imagename"));
items.add(new PintrestItem("url of image you want to show","imagename"));
items.add(new PintrestItem("url of image you want to show","imagename"));
recyclerView.setAdapter(new PintrestAdapter(items,getContext() );
Don't forgot to add the Picasso dependency in your build.gradle file:
GoalKicker.com – Android™ Notes for Professionals 150
compile 'com.squareup.picasso:picasso:2.5.2'
GoalKicker.com – Android™ Notes for Professionals 151
Chapter 20: Pagination in RecyclerView
Pagination is a common issue with for a lot of mobile apps that need to deal with lists of data. Most of the mobile
apps are now starting to take up the "endless page" model, where scrolling automatically loads in new content.
CWAC Endless Adapter makes it really easy to use this pattern in Android applications
Section 20.1: MainActivity.java
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.widget.TextView;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private Toolbar toolbar;
private TextView tvEmptyView;
private RecyclerView mRecyclerView;
private DataAdapter mAdapter;
private LinearLayoutManager mLayoutManager;
private int mStart=0,mEnd=20;
private List<Student> studentList;
private List<Student> mTempCheck;
public static int pageNumber;
public int total_size=0;
protected Handler handler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pageNumber = 1;
toolbar = (Toolbar) findViewById(R.id.toolbar);
tvEmptyView = (TextView) findViewById(R.id.empty_view);
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
studentList = new ArrayList<>();
mTempCheck=new ArrayList<>();
GoalKicker.com – Android™ Notes for Professionals 152
handler = new Handler();
if (toolbar != null) {
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("Android Students");
}
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new DataAdapter(studentList, mRecyclerView);
mRecyclerView.setAdapter(mAdapter);
GetGroupData("" + mStart, "" + mEnd);
mAdapter.setOnLoadMoreListener(new OnLoadMoreListener() {
@Override
public void onLoadMore() {
if( mTempCheck.size()> 0) {
studentList.add(null);
mAdapter.notifyItemInserted(studentList.size() - 1);
int start = pageNumber * 20;
start = start + 1;
++ pageNumber;
mTempCheck.clear();
GetData("" + start,""+ mEnd);
}
}
});
}
public void GetData(final String LimitStart, final String LimitEnd) {
Map<String, String> params = new HashMap<>();
params.put("LimitStart", LimitStart);
params.put("Limit", LimitEnd);
Custom_Volly_Request jsonObjReq = new Custom_Volly_Request(Request.Method.POST,
"Your php file link", params,
new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
Log.d("ResponseSuccess",response.toString());
// handle the data from the servoce
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
VolleyLog.d("ResponseErrorVolly: " + error.getMessage());
}});
}
// load initial data
private void loadData(int start,int end,boolean notifyadapter) {
for (int i = start; i <= end; i++) {
studentList.add(new Student("Student " + i, "androidstudent" + i + "@gmail.com"));
if(notifyadapter)
mAdapter.notifyItemInserted(studentList.size());
}
}
}
OnLoadMoreListener.java
GoalKicker.com – Android™ Notes for Professionals 153
public interface OnLoadMoreListener { void onLoadMore(); }
DataAdapter.java
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
public class DataAdapter extends RecyclerView.Adapter {
private final int VIEW_ITEM = 1;
private final int VIEW_PROG = 0;
private List<Student> studentList;
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
private boolean loading;
private OnLoadMoreListener onLoadMoreListener;
public DataAdapter(List<Student> students, RecyclerView recyclerView) {
studentList = students;
if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) {
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager)
recyclerView.getLayoutManager();
recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
totalItemCount = linearLayoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition();
if (! loading && totalItemCount <= (lastVisibleItem +
visibleThreshold)) {
if (onLoadMoreListener != null) {
onLoadMoreListener.onLoadMore();
}
loading = true;
}
}
});
}
}
@Override
public int getItemViewType(int position) {
return studentList.get(position) != null ? VIEW_ITEM : VIEW_PROG;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
GoalKicker.com – Android™ Notes for Professionals 154
RecyclerView.ViewHolder vh;
if (viewType == VIEW_ITEM) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_row, parent,
false);
vh = new StudentViewHolder(v);
} else {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.progress_item,
parent, false);
vh = new ProgressViewHolder(v);
}
return vh;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof StudentViewHolder) {
Student singleStudent=studentList.get(position);
((StudentViewHolder) holder).tvName.setText(singleStudent.getName());
((StudentViewHolder) holder).tvEmailId.setText(singleStudent.getEmailId());
((StudentViewHolder) holder).student= singleStudent;
} else {
((ProgressViewHolder) holder).progressBar.setIndeterminate(true);
}
}
public void setLoaded(boolean state) {
loading = state;
}
@Override
public int getItemCount() {
return studentList.size();
}
public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {
this.onLoadMoreListener = onLoadMoreListener;
}
//
public static class StudentViewHolder extends RecyclerView.ViewHolder {
public TextView tvName;
public TextView tvEmailId;
public Student student;
public StudentViewHolder(View v) {
super(v);
tvName = (TextView) v.findViewById(R.id.tvName);
tvEmailId = (TextView) v.findViewById(R.id.tvEmailId);
}
}
public static class ProgressViewHolder extends RecyclerView.ViewHolder {
public ProgressBar progressBar;
public ProgressViewHolder(View v) {
super(v);
progressBar = (ProgressBar) v.findViewById(R.id.progressBar1);
GoalKicker.com – Android™ Notes for Professionals 155
}
}
}
GoalKicker.com – Android™ Notes for Professionals 156
Chapter 21: ImageView
Parameter Description
resId your Image file name in the res folder (usually in drawable folder)
ImageView (android.widget.ImageView) is a View for displaying and manipulating image resources, such as
Drawables and Bitmaps.
Some effects, discussed in this topic, can be applied to the image. The image source can be set in XML file (layout
folder) or by programmatically in Java code.
Section 21.1: Set tint
Set a tinting color for the image. By default, the tint will blend using SRC_ATOP mode.
set tint using XML attribute:
android:tint="#009c38"
Note: Must be a color value, in the form of "#rgb", "#argb", "#rrggbb", or "#aarrggbb".
set tint programmatically:
imgExample.setColorFilter(Color.argb(255, 0, 156, 38));
and you can clear this color filter:
imgExample.clearColorFilter();
Example:
GoalKicker.com – Android™ Notes for Professionals 157
Section 21.2: Set alpha
"alpha" is used to specify the opacity for an image.
set alpha using XML attribute:
android:alpha="0.5"
Note: takes float value from 0 (transparent) to 1 (fully visible)
set alpha programmatically:
imgExample.setAlpha(0.5f);
Section 21.3: Set Scale Type
Controls how the image should be resized or moved to match the size of ImageView.
GoalKicker.com – Android™ Notes for Professionals 158
XML attribute:
android:scaleType="..."
i will illustrate different scale types with a square ImageView which has a black background and we want to display a
rectangular drawable in white background in ImageView.
<ImageView
android:id="@+id/imgExample"
android:layout_width="200dp"
android:layout_height="200dp"
android:background="#000"
android:src="@drawable/android2"
android:scaleType="..."/>
scaleType must be one of the following values:
1. center:Center the image in the view, but perform no scaling.
2. centerCrop: Scale the image uniformly (maintain the image's aspect ratio) so both dimensions (width and
height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
The image is then centered in the view.
GoalKicker.com – Android™ Notes for Professionals 159
3. centerInside: Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width
and height) of the image will be equal to or less than the corresponding dimension of the view (minus
padding). The image is then centered in the view.
4. matrix : Scale using the image matrix when drawing.
GoalKicker.com – Android™ Notes for Professionals 160
5. fitXY: Scale the image using FILL.
6. fitStart: Scale the image using START.
GoalKicker.com – Android™ Notes for Professionals 161
7. fitCenter: Scale the image using CENTER.
8. fitEnd: Scale the image using END.
GoalKicker.com – Android™ Notes for Professionals 162
Section 21.4: ImageView ScaleType - Center
The image contained in the ImageView may not fit the exact size given to the container. In that case, the framework
allows you to resize the image in a number of ways.
Center
<ImageView android:layout_width="20dp"
android:layout_height="20dp"
android:src="@mipmap/ic_launcher"
android:id="@+id/imageView"
android:scaleType="center"
android:background="@android:color/holo_orange_light"/>
This will not resize the image, and it will center it inside the container (Orange = container)
GoalKicker.com – Android™ Notes for Professionals 163
In case that the ImageView is smaller than the image, the image will not be resized and you will only be able to see
a part of it
GoalKicker.com – Android™ Notes for Professionals 164
strong text
Section 21.5: ImageView ScaleType - CenterCrop
Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the
image will be equal to or larger than the corresponding dimension of the view (minus padding).
Official Docs
When the image matches the proportions of the container:
GoalKicker.com – Android™ Notes for Professionals 165
When the image is wider than the container it will expand it to the bigger size (in this case height) and adjust the
width of the image without changing it's proportions, causing it to crop.
GoalKicker.com – Android™ Notes for Professionals 166
Section 21.6: ImageView ScaleType - CenterInside
Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the
image will be equal to or less than the corresponding dimension of the view (minus padding).
Official Docs
It will center the image and resize it to the smaller size, if both container sizes are bigger it will act the same as
center.
GoalKicker.com – Android™ Notes for Professionals 167
But if one of the sizes are small, it will fit to that size.
GoalKicker.com – Android™ Notes for Professionals 168
Section 21.7: ImageView ScaleType - FitStart and FitEnd
Scale the image using START.
Scale the image using END.
Official Docs
FitStart
This will fit to the smallest size of the container, and it will align it to the start.
<ImageView android:layout_width="200dp"
android:layout_height="200dp"
GoalKicker.com – Android™ Notes for Professionals 169
android:src="@mipmap/ic_launcher"
android:id="@+id/imageView"
android:scaleType="fitStart"
android:layout_gravity="center"
android:background="@android:color/holo_orange_light"/>
GoalKicker.com – Android™ Notes for Professionals 170
FitEnd
This will fit to the smallest size of the container, and it will align it to the end.
<ImageView android:layout_width="200dp"
android:layout_height="100dp"
android:src="@mipmap/ic_launcher"
android:id="@+id/imageView"
android:scaleType="fitEnd"
android:layout_gravity="center"
android:background="@android:color/holo_orange_light"/>
GoalKicker.com – Android™ Notes for Professionals 171
GoalKicker.com – Android™ Notes for Professionals 172
Section 21.8: ImageView ScaleType - FitCenter
Scale the image using CENTER.
Official Docs
This expands the image to try to match the container and it will align it to the center, it will fit to the smaller size.
Bigger height ( fit to width )
GoalKicker.com – Android™ Notes for Professionals 173
Same width and height.
GoalKicker.com – Android™ Notes for Professionals 174
Section 21.9: Set Image Resource
<ImageView
android:id="@+id/imgExample"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
...
/>
set a drawable as content of ImageView using XML attribute:
android:src="@drawable/android2"
set a drawable programmatically:
ImageView imgExample = (ImageView) findViewById(R.id.imgExample);
GoalKicker.com – Android™ Notes for Professionals 175
imgExample.setImageResource(R.drawable.android2);
Section 21.10: ImageView ScaleType - FitXy
Scale the image using FILL.
Official Docs
<ImageView android:layout_width="100dp"
android:layout_height="200dp"
android:src="@mipmap/ic_launcher"
android:id="@+id/imageView"
android:scaleType="fitXY"
android:layout_gravity="center"
android:background="@android:color/holo_orange_light"/>
GoalKicker.com – Android™ Notes for Professionals 176
GoalKicker.com – Android™ Notes for Professionals 177
Section 21.11: MLRoundedImageView.java
Copy and Paste following class in your package:
public class MLRoundedImageView extends ImageView {
public MLRoundedImageView(Context context) {
super(context);
}
public MLRoundedImageView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public MLRoundedImageView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
GoalKicker.com – Android™ Notes for Professionals 178
@Override
protected void onDraw(Canvas canvas) {
Drawable drawable = getDrawable();
if (drawable == null) {
return;
}
if (getWidth() == 0 || getHeight() == 0) {
return;
}
Bitmap b = ((BitmapDrawable) drawable).getBitmap();
Bitmap bitmap = b.copy(Bitmap.Config.ARGB_8888, true);
int w = getWidth(), h = getHeight();
Bitmap roundBitmap = getCroppedBitmap(bitmap, w);
canvas.drawBitmap(roundBitmap, 0, 0, null);
}
public static Bitmap getCroppedBitmap(Bitmap bmp, int radius) {
Bitmap sbmp;
if (bmp.getWidth() != radius || bmp.getHeight() != radius) {
float smallest = Math.min(bmp.getWidth(), bmp.getHeight());
float factor = smallest / radius;
sbmp = Bitmap.createScaledBitmap(bmp, (int)(bmp.getWidth() / factor),
(int)(bmp.getHeight() / factor), false);
} else {
sbmp = bmp;
}
Bitmap output = Bitmap.createBitmap(radius, radius,
Config.ARGB_8888);
Canvas canvas = new Canvas(output);
final int color = 0xffa19774;
final Paint paint = new Paint();
final Rect rect = new Rect(0, 0, radius, radius);
paint.setAntiAlias(true);
paint.setFilterBitmap(true);
paint.setDither(true);
canvas.drawARGB(0, 0, 0, 0);
paint.setColor(Color.parseColor("#BAB399"));
canvas.drawCircle(radius / 2 + 0.7f,
radius / 2 + 0.7f, radius / 2 + 0.1f, paint);
paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
canvas.drawBitmap(sbmp, rect, rect, paint);
return output;
}
}
Use this Class in XML with package name instead of ImageView
<com.androidbuts.example.MLRoundedImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
GoalKicker.com – Android™ Notes for Professionals 179
android:src="@mipmap/ic_launcher" />
GoalKicker.com – Android™ Notes for Professionals 180
Chapter 22: VideoView
Section 22.1: Play video from URL with using VideoView
videoView.setVideoURI(Uri.parse("http://example.com/examplevideo.mp4"));
videoView.requestFocus();
videoView.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(MediaPlayer mediaPlayer) {
}
});
videoView.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mediaPlayer) {
videoView.start();
mediaPlayer.setOnVideoSizeChangedListener(new MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
MediaController mediaController = new MediaController(ActivityName.this);
videoView.setMediaController(mediaController);
mediaController.setAnchorView(videoView);
}
});
}
});
videoView.setOnErrorListener(new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(MediaPlayer mediaPlayer, int i, int i1) {
return false;
}
});
Section 22.2: VideoView Create
Find VideoView in Activity and add video into it.
VideoView videoView = (VideoView) .findViewById(R.id.videoView);
videoView.setVideoPath(pathToVideo);
Start playing video.
videoView.start();
Define VideoView in XML Layout file.
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center" />
GoalKicker.com – Android™ Notes for Professionals 181
Chapter 23: Optimized VideoView
Playing a video using a VideoView which extends SurfaceView inside of a row of a ListView seems to work at first,
until the user tries to scroll the list. As soon as the list starts to scroll, the video turns black (sometimes displays
white). It keeps playing in the background but you can’t see it anymore because it renders the rest of the video as a
black box. With the custom Optimized VideoView, the videos will play on scroll in the ListView just like our
Instagram, Facebook, Twitter.
Section 23.1: Optimized VideoView in ListView
This the custom VideoView that you need to have it in your package.
Custom VideoView Layout:
<your.packagename.VideoView
android:id="@+id/video_view"
android:layout_width="300dp"
android:layout_height="300dp" />
Code for custom Optimized VideoView:
package your.package.com.whateveritis;
import android.content.Context;
import android.content.Intent;
import android.graphics.SurfaceTexture;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnErrorListener;
import android.media.MediaPlayer.OnInfoListener;
import android.net.Uri;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.MediaController;
import android.widget.MediaController.MediaPlayerControl;
import java.io.IOException;
/**
* VideoView is used to play video, just like
* {@link android.widget.VideoView VideoView}. We define a custom view, because
* we could not use {@link android.widget.VideoView VideoView} in ListView. <br/>
* VideoViews inside ScrollViews do not scroll properly. Even if you use the
* workaround to set the background color, the MediaController does not scroll
* along with the VideoView. Also, the scrolling video looks horrendous with the
* workaround, lots of flickering.
*
* @author leo
*/
public class VideoView extends TextureView implements MediaPlayerControl {
GoalKicker.com – Android™ Notes for Professionals 182
private static final String TAG = "tag";
// all possible internal states
private static final int STATE_ERROR = -1;
private static final int STATE_IDLE = 0;
private static final int STATE_PREPARING = 1;
private static final int STATE_PREPARED = 2;
private static final int STATE_PLAYING = 3;
private static final int STATE_PAUSED = 4;
private static final int STATE_PLAYBACK_COMPLETED = 5;
// currentState is a VideoView object's current state.
// targetState is the state that a method caller intends to reach.
// For instance, regardless the VideoView object's current state,
// calling pause() intends to bring the object to a target state
// of STATE_PAUSED.
private int mCurrentState = STATE_IDLE;
private int mTargetState = STATE_IDLE;
// Stuff we need for playing and showing a video
private MediaPlayer mMediaPlayer;
private int mVideoWidth;
private int mVideoHeight;
private int mSurfaceWidth;
private int mSurfaceHeight;
private SurfaceTexture mSurfaceTexture;
private Surface mSurface;
private MediaController mMediaController;
private MediaPlayer.OnCompletionListener mOnCompletionListener;
private MediaPlayer.OnPreparedListener mOnPreparedListener;
private MediaPlayer.OnErrorListener mOnErrorListener;
private MediaPlayer.OnInfoListener mOnInfoListener;
private int mSeekWhenPrepared; // recording the seek position while
// preparing
private int mCurrentBufferPercentage;
private int mAudioSession;
private Uri mUri;
private Context mContext;
public VideoView(final Context context) {
super(context);
mContext = context;
initVideoView();
}
public VideoView(final Context context, final AttributeSet attrs) {
super(context, attrs);
mContext = context;
initVideoView();
}
public VideoView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
mContext = context;
initVideoView();
}
public void initVideoView() {
mVideoHeight = 0;
GoalKicker.com – Android™ Notes for Professionals 183
mVideoWidth = 0;
setFocusable(false);
setSurfaceTextureListener(mSurfaceTextureListener);
}
public int resolveAdjustedSize(int desiredSize, int measureSpec) {
int result = desiredSize;
int specMode = MeasureSpec.getMode(measureSpec);
int specSize = MeasureSpec.getSize(measureSpec);
switch (specMode) {
case MeasureSpec.UNSPECIFIED:
/*
* Parent says we can be as big as we want. Just don't be larger
* than max size imposed on ourselves.
*/
result = desiredSize;
break;
case MeasureSpec.AT_MOST:
/*
* Parent says we can be as big as we want, up to specSize. Don't be
* larger than specSize, and don't be larger than the max size
* imposed on ourselves.
*/
result = Math.min(desiredSize, specSize);
break;
case MeasureSpec.EXACTLY:
// No choice. Do what we are told.
result = specSize;
break;
}
return result;
}
public void setVideoPath(String path) {
Log.d(TAG, "Setting video path to: " + path);
setVideoURI(Uri.parse(path));
}
public void setVideoURI(Uri _videoURI) {
mUri = _videoURI;
mSeekWhenPrepared = 0;
requestLayout();
invalidate();
openVideo();
}
public Uri getUri() {
return mUri;
}
public void setSurfaceTexture(SurfaceTexture _surfaceTexture) {
mSurfaceTexture = _surfaceTexture;
}
public void openVideo() {
if ((mUri == null) || (mSurfaceTexture == null)) {
Log.d(TAG, "Cannot open video, uri or surface texture is null.");
return;
}
GoalKicker.com – Android™ Notes for Professionals 184
// Tell the music playback service to pause
// TODO: these constants need to be published somewhere in the
// framework.
Intent i = new Intent("com.android.music.musicservicecommand");
i.putExtra("command", "pause");
mContext.sendBroadcast(i);
release(false);
try {
mSurface = new Surface(mSurfaceTexture);
mMediaPlayer = new MediaPlayer();
if (mAudioSession != 0) {
mMediaPlayer.setAudioSessionId(mAudioSession);
} else {
mAudioSession = mMediaPlayer.getAudioSessionId();
}
mMediaPlayer.setOnBufferingUpdateListener(mBufferingUpdateListener);
mMediaPlayer.setOnCompletionListener(mCompleteListener);
mMediaPlayer.setOnPreparedListener(mPreparedListener);
mMediaPlayer.setOnErrorListener(mErrorListener);
mMediaPlayer.setOnInfoListener(mOnInfoListener);
mMediaPlayer.setOnVideoSizeChangedListener(mVideoSizeChangedListener);
mMediaPlayer.setSurface(mSurface);
mCurrentBufferPercentage = 0;
mMediaPlayer.setDataSource(mContext, mUri);
mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
mMediaPlayer.setScreenOnWhilePlaying(true);
mMediaPlayer.prepareAsync();
mCurrentState = STATE_PREPARING;
} catch (IllegalStateException e) {
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
String msg = (e.getMessage()==null)?"":e.getMessage();
Log.i("",msg); // TODO auto-generated catch block
} catch (IOException e) {
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
String msg = (e.getMessage()==null)?"":e.getMessage();
Log.i("",msg); // TODO auto-generated catch block
}
}
public void stopPlayback() {
if (mMediaPlayer != null) {
mMediaPlayer.stop();
mMediaPlayer.release();
mMediaPlayer = null;
if (null != mMediaControllListener) {
mMediaControllListener.onStop();
}
}
}
public void setMediaController(MediaController controller) {
if (mMediaController != null) {
mMediaController.hide();
}
mMediaController = controller;
attachMediaController();
GoalKicker.com – Android™ Notes for Professionals 185
}
private void attachMediaController() {
if (mMediaPlayer != null && mMediaController != null) {
mMediaController.setMediaPlayer(this);
View anchorView = this.getParent() instanceof View ? (View) this.getParent() : this;
mMediaController.setAnchorView(anchorView);
mMediaController.setEnabled(isInPlaybackState());
}
}
private void release(boolean cleartargetstate) {
Log.d(TAG, "Releasing media player.");
if (mMediaPlayer != null) {
mMediaPlayer.reset();
mMediaPlayer.release();
mMediaPlayer = null;
mCurrentState = STATE_IDLE;
if (cleartargetstate) {
mTargetState = STATE_IDLE;
}
} else {
Log.d(TAG, "Media player was null, did not release.");
}
}
@Override
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
// Will resize the view if the video dimensions have been found.
// video dimensions are found after onPrepared has been called by
// MediaPlayer
int width = getDefaultSize(mVideoWidth, widthMeasureSpec);
int height = getDefaultSize(mVideoHeight, heightMeasureSpec);
if ((mVideoWidth > 0) && (mVideoHeight > 0)) {
if ((mVideoWidth * height) > (width * mVideoHeight)) {
Log.d(TAG, "Video too tall, change size.");
height = (width * mVideoHeight) / mVideoWidth;
} else if ((mVideoWidth * height) < (width * mVideoHeight)) {
Log.d(TAG, "Video too wide, change size.");
width = (height * mVideoWidth) / mVideoHeight;
} else {
Log.d(TAG, "Aspect ratio is correct.");
}
}
setMeasuredDimension(width, height);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (isInPlaybackState() && mMediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
}
@Override
public boolean onTrackballEvent(MotionEvent ev) {
if (isInPlaybackState() && mMediaController != null) {
toggleMediaControlsVisiblity();
}
return false;
}
GoalKicker.com – Android™ Notes for Professionals 186
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
boolean isKeyCodeSupported = keyCode != KeyEvent.KEYCODE_BACK && keyCode !=
KeyEvent.KEYCODE_VOLUME_UP && keyCode != KeyEvent.KEYCODE_VOLUME_DOWN
&& keyCode != KeyEvent.KEYCODE_VOLUME_MUTE && keyCode != KeyEvent.KEYCODE_MENU &&
keyCode != KeyEvent.KEYCODE_CALL
&& keyCode != KeyEvent.KEYCODE_ENDCALL;
if (isInPlaybackState() && isKeyCodeSupported && mMediaController != null) {
if (keyCode == KeyEvent.KEYCODE_HEADSETHOOK || keyCode ==
KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE) {
if (mMediaPlayer.isPlaying()) {
pause();
mMediaController.show();
} else {
start();
mMediaController.hide();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_PLAY) {
if (!mMediaPlayer.isPlaying()) {
start();
mMediaController.hide();
}
return true;
} else if (keyCode == KeyEvent.KEYCODE_MEDIA_STOP || keyCode ==
KeyEvent.KEYCODE_MEDIA_PAUSE) {
if (mMediaPlayer.isPlaying()) {
pause();
mMediaController.show();
}
return true;
} else {
toggleMediaControlsVisiblity();
}
}
return super.onKeyDown(keyCode, event);
}
private void toggleMediaControlsVisiblity() {
if (mMediaController.isShowing()) {
mMediaController.hide();
} else {
mMediaController.show();
}
}
public void start() {
// This can potentially be called at several points, it will go through
// when all conditions are ready
// 1. When setting the video URI
// 2. When the surface becomes available
// 3. From the activity
if (isInPlaybackState()) {
mMediaPlayer.start();
mCurrentState = STATE_PLAYING;
if (null != mMediaControllListener) {
mMediaControllListener.onStart();
}
} else {
Log.d(TAG, "Could not start. Current state " + mCurrentState);
}
GoalKicker.com – Android™ Notes for Professionals 187
mTargetState = STATE_PLAYING;
}
public void pause() {
if (isInPlaybackState()) {
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
mCurrentState = STATE_PAUSED;
if (null != mMediaControllListener) {
mMediaControllListener.onPause();
}
}
}
mTargetState = STATE_PAUSED;
}
public void suspend() {
release(false);
}
public void resume() {
openVideo();
}
@Override
public int getDuration() {
if (isInPlaybackState()) {
return mMediaPlayer.getDuration();
}
return -1;
}
@Override
public int getCurrentPosition() {
if (isInPlaybackState()) {
return mMediaPlayer.getCurrentPosition();
}
return 0;
}
@Override
public void seekTo(int msec) {
if (isInPlaybackState()) {
mMediaPlayer.seekTo(msec);
mSeekWhenPrepared = 0;
} else {
mSeekWhenPrepared = msec;
}
}
@Override
public boolean isPlaying() {
return isInPlaybackState() && mMediaPlayer.isPlaying();
}
@Override
public int getBufferPercentage() {
if (mMediaPlayer != null) {
return mCurrentBufferPercentage;
}
return 0;
GoalKicker.com – Android™ Notes for Professionals 188
}
private boolean isInPlaybackState() {
return ((mMediaPlayer != null) && (mCurrentState != STATE_ERROR) && (mCurrentState !=
STATE_IDLE) && (mCurrentState != STATE_PREPARING));
}
@Override
public boolean canPause() {
return false;
}
@Override
public boolean canSeekBackward() {
return false;
}
@Override
public boolean canSeekForward() {
return false;
}
@Override
public int getAudioSessionId() {
if (mAudioSession == 0) {
MediaPlayer foo = new MediaPlayer();
mAudioSession = foo.getAudioSessionId();
foo.release();
}
return mAudioSession;
}
// Listeners
private MediaPlayer.OnBufferingUpdateListener mBufferingUpdateListener = new
MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(final MediaPlayer mp, final int percent) {
mCurrentBufferPercentage = percent;
}
};
private MediaPlayer.OnCompletionListener mCompleteListener = new
MediaPlayer.OnCompletionListener() {
@Override
public void onCompletion(final MediaPlayer mp) {
mCurrentState = STATE_PLAYBACK_COMPLETED;
mTargetState = STATE_PLAYBACK_COMPLETED;
mSurface.release();
if (mMediaController != null) {
mMediaController.hide();
}
if (mOnCompletionListener != null) {
mOnCompletionListener.onCompletion(mp);
}
if (mMediaControllListener != null) {
mMediaControllListener.onComplete();
}
}
};
GoalKicker.com – Android™ Notes for Professionals 189
private MediaPlayer.OnPreparedListener mPreparedListener = new MediaPlayer.OnPreparedListener()
{
@Override
public void onPrepared(final MediaPlayer mp) {
mCurrentState = STATE_PREPARED;
mMediaController = new MediaController(getContext());
if (mOnPreparedListener != null) {
mOnPreparedListener.onPrepared(mMediaPlayer);
}
if (mMediaController != null) {
mMediaController.setEnabled(true);
//mMediaController.setAnchorView(getRootView());
}
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
int seekToPosition = mSeekWhenPrepared; // mSeekWhenPrepared may be
// changed after seekTo()
// call
if (seekToPosition != 0) {
seekTo(seekToPosition);
}
requestLayout();
invalidate();
if ((mVideoWidth != 0) && (mVideoHeight != 0)) {
if (mTargetState == STATE_PLAYING) {
mMediaPlayer.start();
if (null != mMediaControllListener) {
mMediaControllListener.onStart();
}
}
} else {
if (mTargetState == STATE_PLAYING) {
mMediaPlayer.start();
if (null != mMediaControllListener) {
mMediaControllListener.onStart();
}
}
}
}
};
private MediaPlayer.OnVideoSizeChangedListener mVideoSizeChangedListener = new
MediaPlayer.OnVideoSizeChangedListener() {
@Override
public void onVideoSizeChanged(final MediaPlayer mp, final int width, final int height) {
mVideoWidth = mp.getVideoWidth();
mVideoHeight = mp.getVideoHeight();
if (mVideoWidth != 0 && mVideoHeight != 0) {
requestLayout();
}
}
};
private MediaPlayer.OnErrorListener mErrorListener = new MediaPlayer.OnErrorListener() {
@Override
public boolean onError(final MediaPlayer mp, final int what, final int extra) {
Log.d(TAG, "Error: " + what + "," + extra);
GoalKicker.com – Android™ Notes for Professionals 190
mCurrentState = STATE_ERROR;
mTargetState = STATE_ERROR;
if (mMediaController != null) {
mMediaController.hide();
}
/* If an error handler has been supplied, use it and finish. */
if (mOnErrorListener != null) {
if (mOnErrorListener.onError(mMediaPlayer, what, extra)) {
return true;
}
}
/*
* Otherwise, pop up an error dialog so the user knows that
* something bad has happened. Only try and pop up the dialog if
* we're attached to a window. When we're going away and no longer
* have a window, don't bother showing the user an error.
*/
if (getWindowToken() != null) {
// new AlertDialog.Builder(mContext).setMessage("Error: " + what + "," +
extra).setPositiveButton("OK", new DialogInterface.OnClickListener() {
// public void onClick(DialogInterface dialog, int whichButton) {
// /*
// * If we get here, there is no onError listener, so at
// * least inform them that the video is over.
// */
// if (mOnCompletionListener != null) {
// mOnCompletionListener.onCompletion(mMediaPlayer);
// }
// }
// }).setCancelable(false).show();
}
return true;
}
};
SurfaceTextureListener mSurfaceTextureListener = new SurfaceTextureListener() {
@Override
public void onSurfaceTextureAvailable(final SurfaceTexture surface, final int width, final
int height) {
Log.d(TAG, "onSurfaceTextureAvailable.");
mSurfaceTexture = surface;
openVideo();
}
@Override
public void onSurfaceTextureSizeChanged(final SurfaceTexture surface, final int width,
final int height) {
Log.d(TAG, "onSurfaceTextureSizeChanged: " + width + '/' + height);
mSurfaceWidth = width;
mSurfaceHeight = height;
boolean isValidState = (mTargetState == STATE_PLAYING);
boolean hasValidSize = (mVideoWidth == width && mVideoHeight == height);
if (mMediaPlayer != null && isValidState && hasValidSize) {
if (mSeekWhenPrepared != 0) {
seekTo(mSeekWhenPrepared);
}
start();
}
GoalKicker.com – Android™ Notes for Professionals 191
}
@Override
public boolean onSurfaceTextureDestroyed(final SurfaceTexture surface) {
mSurface = null;
if (mMediaController != null)
mMediaController.hide();
release(true);
return true;
}
@Override
public void onSurfaceTextureUpdated(final SurfaceTexture surface) {
}
};
/**
* Register a callback to be invoked when the media file is loaded and ready
* to go.
*
* @param l The callback that will be run
*/
public void setOnPreparedListener(MediaPlayer.OnPreparedListener l) {
mOnPreparedListener = l;
}
/**
* Register a callback to be invoked when the end of a media file has been
* reached during playback.
*
* @param l The callback that will be run
*/
public void setOnCompletionListener(OnCompletionListener l) {
mOnCompletionListener = l;
}
/**
* Register a callback to be invoked when an error occurs during playback or
* setup. If no listener is specified, or if the listener returned false,
* VideoView will inform the user of any errors.
*
* @param l The callback that will be run
*/
public void setOnErrorListener(OnErrorListener l) {
mOnErrorListener = l;
}
/**
* Register a callback to be invoked when an informational event occurs
* during playback or setup.
*
* @param l The callback that will be run
*/
public void setOnInfoListener(OnInfoListener l) {
mOnInfoListener = l;
}
public static interface MediaControllListener {
public void onStart();
GoalKicker.com – Android™ Notes for Professionals 192
public void onPause();
public void onStop();
public void onComplete();
}
MediaControllListener mMediaControllListener;
public void setMediaControllListener(MediaControllListener mediaControllListener) {
mMediaControllListener = mediaControllListener;
}
@Override
public void setVisibility(int visibility) {
System.out.println("setVisibility: " + visibility);
super.setVisibility(visibility);
}
}
Help from this gitub repository. Though It has some issues as it was written 3 years ago I managed to fix them on
my own as written above.
GoalKicker.com – Android™ Notes for Professionals 193
Chapter 24: WebView
WebView is a view that display web pages inside your application. By this you can add your own URL.
Section 24.1: Troubleshooting WebView by printing console
messages or by remote debugging
Printing webview console messages to logcat
To handle console messages from web page you can override onConsoleMessage in WebChromeClient:
final class ChromeClient extends WebChromeClient {
@Override
public boolean onConsoleMessage(ConsoleMessage msg) {
Log.d(
"WebView",
String.format("%s %s:%d", msg.message(), msg.lineNumber(), msg.sourceId())
);
return true;
}
}
And set it in your activity or fragment:
webView.setWebChromeClient(new ChromeClient());
So this sample page:
<html>
<head>
<script type="text/javascript">
console.log('test message');
</script>
</head>
<body>
</body>
</html>
will write log 'test message' to logcat:
WebView: test message sample.html:4
console.info(), console.warn() and console.error() are also supported by chrome-client.
Remote debugging android devices with Chrome
Your can remote debug webview based application from you desktop Chrome.
Enable USB debugging on your Android device
On your Android device, open up Settings, find the Developer options section, and enable USB debugging.
Connect and discover your Android device
GoalKicker.com – Android™ Notes for Professionals 194
Open page in chrome following page: chrome://inspect/#devices
From the Inspect Devices dialog, select your device and press inspect. A new instance of Chrome's DevTools opens
up on your development machine.
More detailed guideline and description of DevTools can be found on developers.google.com
Section 24.2: Communication from Javascript to Java
(Android)
Android Activity
package com.example.myapp;
import android.os.Bundle;
import android.app.Activity;
import android.webkit.WebView;
public class WebViewActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WebView webView = new WebView(this);
setContentView(webView);
/*
* Note the label Android, this is used in the Javascript side of things
* You can of course change this.
*/
webView.addJavascriptInterface(new JavascriptHandler(), "Android");
webView.loadUrl("http://example.com");
}
}
Java Javascript Handler
import android.webkit.JavascriptInterface;
public class JavascriptHandler {
/**
* Key point here is the annotation @JavascriptInterface
*
*/
@JavascriptInterface
public void jsCallback() {
// Do something
}
@JavascriptInterface
public void jsCallbackTwo(String dummyData) {
// Do something
}
}
Web Page, Javascript call
GoalKicker.com – Android™ Notes for Professionals 195
<script>
...
Android.jsCallback();
...
Android.jsCallback('hello test');
...
</script>
Extra Tip
Passing in a complex data structure, a possible solution is use JSON.
Android.jsCallback('{ "fake-var" : "fake-value", "fake-array" : [0,1,2] }');
On the Android side use your favorite JSON parser ie: JSONObject
Section 24.3: Communication from Java to Javascript
Basic Example
package com.example.myapp;
import android.os.Bundle;
import android.app.Activity;
import android.webkit.WebView;
public class WebViewActivity extends Activity {
private Webview webView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
webView = new WebView(this);
webView.getSettings().setJavaScriptEnabled(true);
setContentView(webView);
webView.loadUrl("http://example.com");
/*
* Invoke Javascript function
*/
webView.loadUrl("javascript:testJsFunction('Hello World!')");
}
/**
* Invoking a Javascript function
*/
public void doSomething() {
this.webView.loadUrl("javascript:testAnotherFunction('Hello World Again!')");
}
}
Section 24.4: Open dialer example
If the web page a contains phone number you can make a call using your phone's dialer. This code checks for the
GoalKicker.com – Android™ Notes for Professionals 196
url which starts with tel: then make an intent to open dialer and you can make a call to the clicked phone number:
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.startsWith("tel:")) {
Intent intent = new Intent(Intent.ACTION_DIAL,
Uri.parse(url));
startActivity(intent);
}else if(url.startsWith("http:") || url.startsWith("https:")) {
view.loadUrl(url);
}
return true;
}
Section 24.5: Open Local File / Create dynamic content in
Webview
Layout.xml
<WebView
android:id="@+id/WebViewToDisplay"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:fadeScrollbars="false" />
Load data into WebViewToDisplay
WebView webViewDisplay;
StringBuffer LoadWEb1;
webViewDisplay = (WebView) findViewById(R.id.WebViewToDisplay);
LoadWEb1 = new StringBuffer();
LoadWEb1.append("<html><body><h1>My First Heading</h1><p>My first paragraph.</p>");
//Sample code to read parameters at run time
String strName = "Test Paragraph";
LoadWEb1.append("<br/><p>"+strName+"</p>");
String result = LoadWEb1.append("</body></html>").toString();
WebSettings webSettings = webViewDisplay.getSettings();
webSettings.setJavaScriptEnabled(true);
webViewDisplay.getSettings().setBuiltInZoomControls(true);
if (android.os.Build.VERSION.SDK_INT >= 11){
webViewDisplay.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
webViewDisplay.getSettings().setDisplayZoomControls(false);
}
webViewDisplay.loadDataWithBaseURL(null, result, "text/html", "utf-8",
null);
//To load local file directly from assets folder use below code
//webViewDisplay.loadUrl("file:///android_asset/aboutapp.html");
Section 24.6: JavaScript alert dialogs in WebView - How to
make them work
By default, WebView does not implement JavaScript alert dialogs, ie. alert() will do nothing. In order to make you
need to firstly enable JavaScript (obviously..), and then set a WebChromeClient to handle requests for alert dialogs
from the page:
GoalKicker.com – Android™ Notes for Professionals 197
webView.setWebChromeClient(new WebChromeClient() {
//Other methods for your WebChromeClient here, if needed..
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
return super.onJsAlert(view, url, message, result);
}
});
Here, we override onJsAlert, and then we call through to the super implementation, which gives us a standard
Android dialog. You can also use the message and URL yourself, for example if you want to create a custom styled
dialog or if you want to log them.
GoalKicker.com – Android™ Notes for Professionals 198
Chapter 25: SearchView
Section 25.1: Setting Theme for SearchView
Basically to apply a theme for SearchView extracted as app:actionViewClass from the menu.xml, we need
understand that it depends completely on the style applied to the underlying Toolbar. To achieve themeing the
Toolbar apply the following steps.
Create a style in the styles.xml
<style name="ActionBarThemeOverlay">
<item name="android:textColorPrimary">@color/prim_color</item>
<item name="colorControlNormal">@color/normal_color</item>
<item name="colorControlHighlight">@color/high_color</item>
<item name="android:textColorHint">@color/hint_color</item>
</style>
Apply the style to the Toolbar.
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
app:theme="@style/ActionBarThemeOverlay"
app:popupTheme="@style/ActionBarThemeOverlay"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="@color/colorPrimary"
android:title="@string/title"
tools:targetApi="m" />
This gives the desired color to the all the views corresponding to the Toolbar (back button, Menu icons and
SearchView).
Section 25.2: SearchView in Toolbar with Fragment
menu.xml - (res -> menu)
<menu 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"
tools:context=".HomeActivity">
<item
android:id="@+id/action_search"
android:icon="@android:drawable/ic_menu_search"
android:title="Search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always" />
</menu>
MainFragment.java
public class MainFragment extends Fragment {
private SearchView searchView = null;
private SearchView.OnQueryTextListener queryTextListener;
GoalKicker.com – Android™ Notes for Professionals 199
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle
savedInstanceState) {
return inflater.inflate(R.layout.fragment_main, container, false);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchManager searchManager = (SearchManager)
getActivity().getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) {
searchView = (SearchView) searchItem.getActionView();
}
if (searchView != null) {
searchView.setSearchableInfo(searchManager.getSearchableInfo(getActivity().getComponentName()));
queryTextListener = new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextChange(String newText) {
Log.i("onQueryTextChange", newText);
return true;
}
@Override
public boolean onQueryTextSubmit(String query) {
Log.i("onQueryTextSubmit", query);
return true;
}
};
searchView.setOnQueryTextListener(queryTextListener);
}
super.onCreateOptionsMenu(menu, inflater);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_search:
// Not implemented here
return false;
default:
break;
}
searchView.setOnQueryTextListener(queryTextListener);
return super.onOptionsItemSelected(item);
}
}
Reference screenshot:
GoalKicker.com – Android™ Notes for Professionals 200
Section 25.3: Appcompat SearchView with RxBindings watcher
build.gradle:
dependencies {
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.jakewharton.rxbinding:rxbinding-appcompat-v7:0.4.0'
}
menu/menu.xml:
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item android:id="@+id/action_search" android:title="Search"
android:icon="@android:drawable/ic_menu_search"
app:actionViewClass="android.support.v7.widget.SearchView"
app:showAsAction="always"/>
</menu>
MainActivity.java:
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.menu, menu);
MenuItem searchMenuItem = menu.findItem(R.id.action_search);
setupSearchView(searchMenuItem );
return true;
}
private void setupSearchView(MenuItem searchMenuItem) {
SearchView searchView = (SearchView) searchMenuItem.getActionView();
searchView.setQueryHint(getString(R.string.search_hint)); // your hint here
SearchAdapter searchAdapter = new SearchAdapter(this);
searchView.setSuggestionsAdapter(searchAdapter);
// optional: set the letters count after which the search will begin to 1
// the default is 2
try {
int autoCompleteTextViewID = getResources().getIdentifier("android:id/search_src_text",
null, null);
GoalKicker.com – Android™ Notes for Professionals 201
AutoCompleteTextView searchAutoCompleteTextView = (AutoCompleteTextView)
searchView.findViewById(autoCompleteTextViewID);
searchAutoCompleteTextView.setThreshold(1);
} catch (Exception e) {
Logs.e(TAG, "failed to set search view letters threshold");
}
searchView.setOnSearchClickListener(v -> {
// optional actions to search view expand
});
searchView.setOnCloseListener(() -> {
// optional actions to search view close
return false;
});
RxSearchView.queryTextChanges(searchView)
.doOnEach(notification -> {
CharSequence query = (CharSequence) notification.getValue();
searchAdapter.filter(query);
})
.debounce(300, TimeUnit.MILLISECONDS) // to skip intermediate letters
.flatMap(query -> MyWebService.search(query)) // make a search request
.retry(3)
.subscribe(results -> {
searchAdapter.populateAdapter(results);
});
//optional: collapse the searchView on close
searchView.setOnQueryTextFocusChangeListener((view, queryTextFocused) -> {
if (!queryTextFocused) {
collapseSearchView();
}
});
}
SearchAdapter.java
public class SearchAdapter extends CursorAdapter {
private List<SearchResult> items = Collections.emptyList();
public SearchAdapter(Activity activity) {
super(activity, null, CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
}
public void populateAdapter(List<SearchResult> items) {
this.items = items;
final MatrixCursor c = new MatrixCursor(new String[]{BaseColumns._ID});
for (int i = 0; i < items.size(); i++) {
c.addRow(new Object[]{i});
}
changeCursor(c);
notifyDataSetChanged();
}
public void filter(CharSequence query) {
final MatrixCursor c = new MatrixCursor(new String[]{BaseColumns._ID});
for (int i = 0; i < items.size(); i++) {
SearchResult result = items.get(i);
if (result.getText().startsWith(query.toString())) {
c.addRow(new Object[]{i});
}
GoalKicker.com – Android™ Notes for Professionals 202
}
changeCursor(c);
notifyDataSetChanged();
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
ViewHolder holder = (ViewHolder) view.getTag();
int position = cursor.getPosition();
if (position < items.size()) {
SearchResult result = items.get(position);
// bind your view here
}
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = inflater.inflate(R.layout.search_list_item, parent, false);
ViewHolder holder = new ViewHolder(v);
v.setTag(holder);
return v;
}
private static class ViewHolder {
public final TextView text;
public ViewHolder(View v) {
this.text= (TextView) v.findViewById(R.id.text);
}
}
}
GoalKicker.com – Android™ Notes for Professionals 203
Chapter 26: BottomNavigationView
The Bottom Navigation View has been in the material design guidelines for some time, but it hasn’t been easy for us
to implement it into our apps.
Some applications have built their own solutions, whilst others have relied on third-party open-source libraries to
get the job done.
Now the design support library is seeing the addition of this bottom navigation bar, let’s take a dive into how we
can use it!
Section 26.1: Basic implemetation
To add the BottomNavigationView follow these steps:
1. Add in your build.gradle the dependency:
compile 'com.android.support:design:25.1.0'
2. Add the BottomNavigationView in your layout:
<android.support.design.widget.BottomNavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_navigation_menu"/>
3. Create the menu to populate the view:
<!-- res/menu/bottom_navigation_menu.xml -->
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/my_action1"
android:enabled="true"
android:icon="@drawable/my_drawable"
android:title="@string/text"
app:showAsAction="ifRoom" />
....
</menu>
4. Attach a listener for the click events:
//Get the view
BottomNavigationView bottomNavigationView = (BottomNavigationView)
findViewById(R.id.bottom_navigation);
//Attach the listener
bottomNavigationView.setOnNavigationItemSelectedListener(
new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()) {
case R.id.my_action1:
GoalKicker.com – Android™ Notes for Professionals 204
//Do something...
break;
//...
}
return true;//returning false disables the Navigation bar animations
}
});
Checkout demo code at BottomNavigation-Demo
Section 26.2: Customization of BottomNavigationView
Note : I am assuming that you know about how to use BottomNavigationView.
This example I will explain how to add selector for BottomNavigationView. So you can state on UI for icons and
texts.
Create drawable bottom_navigation_view_selector.xml as
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/bottom_nv_menu_selected" android:state_checked="true" />
<item android:color="@color/bottom_nv_menu_default" />
</selector>
And use below attributes into BottomNavigationView in layout file
app:itemIconTint="@drawable/bottom_navigation_view_selector"
app:itemTextColor="@drawable/bottom_navigation_view_selector"
In above example, I have used same selector bottom_navigation_view_selector for app:itemIconTint
and app:itemTextColor both to keep text and icon colors same. But if your design has different color for
text and icon, you can define 2 different selectors and use them.
Output will be similar to below
Section 26.3: Handling Enabled / Disabled states
Create Selector for Enable/Disable Menu Item.
selector.xml
GoalKicker.com – Android™ Notes for Professionals 205
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:color="@color/white" android:state_enabled="true" />
<item android:color="@color/colorPrimaryDark" android:state_enabled="false" />
</selector>
design.xml
<android.support.design.widget.BottomNavigationView
android:id="@+id/bottom_navigation"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
app:itemBackground="@color/colorPrimary"
app:itemIconTint="@drawable/nav_item_color_state"
app:itemTextColor="@drawable/nav_item_color_state"
app:menu="@menu/bottom_navigation_main" />
Section 26.4: Allowing more than 3 menus
This example is strictly a workaround since, currently there is no way to disable a behaviour known as ShiftMode.
Create a function as such.
public static void disableMenuShiftMode(BottomNavigationView view) {
BottomNavigationMenuView menuView = (BottomNavigationMenuView) view.getChildAt(0);
try {
Field shiftingMode = menuView.getClass().getDeclaredField("mShiftingMode");
shiftingMode.setAccessible(true);
shiftingMode.setBoolean(menuView, false);
shiftingMode.setAccessible(false);
for (int i = 0; i < menuView.getChildCount(); i++) {
BottomNavigationItemView item = (BottomNavigationItemView) menuView.getChildAt(i);
//noinspection RestrictedApi
item.setShiftingMode(false);
// set once again checked value, so view will be updated
//noinspection RestrictedApi
item.setChecked(item.getItemData().isChecked());
}
} catch (NoSuchFieldException e) {
Log.e("BNVHelper", "Unable to get shift mode field", e);
} catch (IllegalAccessException e) {
Log.e("BNVHelper", "Unable to change value of shift mode", e);
}
}
This disables the Shifting behaviour of the menu when item count exceeds 3 nos.
USAGE
BottomNavigationView navView = (BottomNavigationView) findViewById(R.id.bottom_navigation_bar);
disableMenuShiftMode(navView);
Proguard Issue : Add following line proguard configuration file as well else, this wouldn't work.
-keepclassmembers class android.support.design.internal.BottomNavigationMenuView {
boolean mShiftingMode;
}
GoalKicker.com – Android™ Notes for Professionals 206
Alternatively, you can create a Class and access this method from there. See Original Reply Here
NOTE : This is a Reflection based HOTFIX, please update this once Google's support library is updated with a direct
function call.
GoalKicker.com – Android™ Notes for Professionals 207
Chapter 27: Canvas drawing using
SurfaceView
Section 27.1: SurfaceView with drawing thread
This example describes how to create a SurfaceView with a dedicated drawing thread. This implementation also
handles edge cases such as manufacture specific issues as well as starting/stopping the thread to save cpu time.
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
/**
* Defines a custom SurfaceView class which handles the drawing thread
**/
public class BaseSurface extends SurfaceView implements SurfaceHolder.Callback,
View.OnTouchListener, Runnable
{
/**
* Holds the surface frame
*/
private SurfaceHolder holder;
/**
* Draw thread
*/
private Thread drawThread;
/**
* True when the surface is ready to draw
*/
private boolean surfaceReady = false;
/**
* Drawing thread flag
*/
private boolean drawingActive = false;
/**
* Paint for drawing the sample rectangle
*/
private Paint samplePaint = new Paint();
/**
* Time per frame for 60 FPS
*/
private static final int MAX_FRAME_TIME = (int) (1000.0 / 60.0);
private static final String LOGTAG = "surface";
public BaseSurface(Context context, AttributeSet attrs)
GoalKicker.com – Android™ Notes for Professionals 208
{
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
setOnTouchListener(this);
// red
samplePaint.setColor(0xffff0000);
// smooth edges
samplePaint.setAntiAlias(true);
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
if (width == 0 || height == 0)
{
return;
}
// resize your UI
}
@Override
public void surfaceCreated(SurfaceHolder holder)
{
this.holder = holder;
if (drawThread != null)
{
Log.d(LOGTAG, "draw thread still active..");
drawingActive = false;
try
{
drawThread.join();
} catch (InterruptedException e)
{ // do nothing
}
}
surfaceReady = true;
startDrawThread();
Log.d(LOGTAG, "Created");
}
@Override
public void surfaceDestroyed(SurfaceHolder holder)
{
// Surface is not used anymore - stop the drawing thread
stopDrawThread();
// and release the surface
holder.getSurface().release();
this.holder = null;
surfaceReady = false;
Log.d(LOGTAG, "Destroyed");
}
@Override
public boolean onTouch(View v, MotionEvent event)
{
// Handle touch events
GoalKicker.com – Android™ Notes for Professionals 209
return true;
}
/**
* Stops the drawing thread
*/
public void stopDrawThread()
{
if (drawThread == null)
{
Log.d(LOGTAG, "DrawThread is null");
return;
}
drawingActive = false;
while (true)
{
try
{
Log.d(LOGTAG, "Request last frame");
drawThread.join(5000);
break;
} catch (Exception e)
{
Log.e(LOGTAG, "Could not join with draw thread");
}
}
drawThread = null;
}
/**
* Creates a new draw thread and starts it.
*/
public void startDrawThread()
{
if (surfaceReady && drawThread == null)
{
drawThread = new Thread(this, "Draw thread");
drawingActive = true;
drawThread.start();
}
}
@Override
public void run()
{
Log.d(LOGTAG, "Draw thread started");
long frameStartTime;
long frameTime;
/*
* In order to work reliable on Nexus 7, we place ~500ms delay at the start of drawing thread
* (AOSP - Issue 58385)
*/
if (android.os.Build.BRAND.equalsIgnoreCase("google") &&
android.os.Build.MANUFACTURER.equalsIgnoreCase("asus") &&
android.os.Build.MODEL.equalsIgnoreCase("Nexus 7"))
{
Log.w(LOGTAG, "Sleep 500ms (Device: Asus Nexus 7)");
try
{
Thread.sleep(500);
} catch (InterruptedException ignored)
GoalKicker.com – Android™ Notes for Professionals 210
{
}
}
try
{
while (drawingActive)
{
if (holder == null)
{
return;
}
frameStartTime = System.nanoTime();
Canvas canvas = holder.lockCanvas();
if (canvas != null)
{
// clear the screen using black
canvas.drawARGB(255, 0, 0, 0);
try
{
// Your drawing here
canvas.drawRect(0, 0, getWidth() / 2, getHeight() / 2, samplePaint);
} finally
{
holder.unlockCanvasAndPost(canvas);
}
}
// calculate the time required to draw the frame in ms
frameTime = (System.nanoTime() - frameStartTime) / 1000000;
if (frameTime < MAX_FRAME_TIME) // faster than the max fps - limit the FPS
{
try
{
Thread.sleep(MAX_FRAME_TIME - frameTime);
} catch (InterruptedException e)
{
// ignore
}
}
}
} catch (Exception e)
{
Log.w(LOGTAG, "Exception while locking/unlocking");
}
Log.d(LOGTAG, "Draw thread finished");
}
}
This layout only contains the custom SurfaceView and maximizes it to the screen size.
<?xml version="1.0" encoding="utf-8"?>
<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"
tools:context="sample.devcore.org.surfaceviewsample.MainActivity">
GoalKicker.com – Android™ Notes for Professionals 211
<sample.devcore.org.surfaceviewsample.BaseSurface
android:id="@+id/baseSurface"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
The activity which uses the SurfaceView is responsible for starting and stopping the drawing thread. This approach
saves battery as the drawing is stopped as soon as the activity gets in the background.
import android.app.Activity;
import android.os.Bundle;
public class MainActivity extends Activity
{
/**
* Surface object
*/
private BaseSurface surface;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
surface = (BaseSurface) findViewById(R.id.baseSurface);
}
@Override
protected void onResume()
{
super.onResume();
// start the drawing
surface.startDrawThread();
}
@Override
protected void onPause()
{
// stop the drawing to save cpu time
surface.stopDrawThread();
super.onPause();
}
}
GoalKicker.com – Android™ Notes for Professionals 212
Chapter 28: Creating Custom Views
Section 28.1: Creating Custom Views
If you need a completely customized view, you'll need to subclass View (the superclass of all Android views) and
provide your custom sizing (onMeasure(...)) and drawing (onDraw(...)) methods:
1. Create your custom view skeleton: this is basically the same for every custom view. Here we create the
skeleton for a custom view that can draw a smiley, called SmileyView:
public class SmileyView extends View {
private Paint mCirclePaint;
private Paint mEyeAndMouthPaint;
private float mCenterX;
private float mCenterY;
private float mRadius;
private RectF mArcBounds = new RectF();
public SmileyView(Context context) {
this(context, null, 0);
}
public SmileyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SmileyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
initPaints();
}
private void initPaints() {/* ... */}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {/* ... */}
@Override
protected void onDraw(Canvas canvas) {/* ... */}
}
2. Initialize your paints: the Paint objects are the brushes of your virtual canvas defining how your geometric
objects are rendered (e.g. color, fill and stroke style, etc.). Here we create two Paints, one yellow filled paint
for the circle and one black stroke paint for the eyes and the mouth:
private void initPaints() {
mCirclePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaint.setStyle(Paint.Style.FILL);
mCirclePaint.setColor(Color.YELLOW);
mEyeAndMouthPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mEyeAndMouthPaint.setStyle(Paint.Style.STROKE);
mEyeAndMouthPaint.setStrokeWidth(16 * getResources().getDisplayMetrics().density);
mEyeAndMouthPaint.setStrokeCap(Paint.Cap.ROUND);
mEyeAndMouthPaint.setColor(Color.BLACK);
}
3. Implement your own onMeasure(...) method: this is required so that the parent layouts (e.g.
GoalKicker.com – Android™ Notes for Professionals 213
FrameLayout) can properly align your custom view. It provides a set of measureSpecs that you can use to
determine your view's height and width. Here we create a square by making sure that the height and width
are the same:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int w = MeasureSpec.getSize(widthMeasureSpec);
int h = MeasureSpec.getSize(heightMeasureSpec);
int size = Math.min(w, h);
setMeasuredDimension(size, size);
}
Note that onMeasure(...) must contain at least one call to setMeasuredDimension(..) or else your custom
view will crash with an IllegalStateException.
4. Implement your own onSizeChanged(...) method: this allows you to catch the current height and width of
your custom view to properly adjust your rendering code. Here we just calculate our center and our radius:
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
mCenterX = w / 2f;
mCenterY = h / 2f;
mRadius = Math.min(w, h) / 2f;
}
5. Implement your own onDraw(...) method: this is where you implement the actual rendering of your view.
It provides a Canvas object that you can draw on (see the official Canvas documentation for all drawing
methods available).
@Override
protected void onDraw(Canvas canvas) {
// draw face
canvas.drawCircle(mCenterX, mCenterY, mRadius, mCirclePaint);
// draw eyes
float eyeRadius = mRadius / 5f;
float eyeOffsetX = mRadius / 3f;
float eyeOffsetY = mRadius / 3f;
canvas.drawCircle(mCenterX - eyeOffsetX, mCenterY - eyeOffsetY, eyeRadius,
mEyeAndMouthPaint);
canvas.drawCircle(mCenterX + eyeOffsetX, mCenterY - eyeOffsetY, eyeRadius,
mEyeAndMouthPaint);
// draw mouth
float mouthInset = mRadius /3f;
mArcBounds.set(mouthInset, mouthInset, mRadius * 2 - mouthInset, mRadius * 2 -
mouthInset);
canvas.drawArc(mArcBounds, 45f, 90f, false, mEyeAndMouthPaint);
}
6. Add your custom view to a layout: the custom view can now be included in any layout files that you have.
Here we just wrap it inside a FrameLayout:
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
GoalKicker.com – Android™ Notes for Professionals 214
<com.example.app.SmileyView
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
Note that it is recommended to build your project after the view code is finished. Without building it you won't be
able to see the view on a preview screen in Android Studio.
After putting everything together, you should be greeted with the following screen after launching the activity
containing the above layout:
Section 28.2: Adding attributes to views
Custom views can also take custom attributes which can be used in Android layout resource files. To add attributes
to your custom view you need to do the following:
1. Define the name and type of your attributes: this is done inside res/values/attrs.xml (create it if
necessary). The following file defines a color attribute for our smiley's face color and an enum attribute for
the smiley's expression:
<resources>
<declare-styleable name="SmileyView">
<attr name="smileyColor" format="color" />
<attr name="smileyExpression" format="enum">
<enum name="happy" value="0"/>
<enum name="sad" value="1"/>
</attr>
</declare-styleable>
<!-- attributes for other views -->
</resources>
2. Use your attributes inside your layout: this can be done inside any layout files that use your custom view.
The following layout file creates a screen with a happy yellow smiley:
GoalKicker.com – Android™ Notes for Professionals 215
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_height="match_parent"
android:layout_width="match_parent">
<com.example.app.SmileyView
android:layout_height="56dp"
android:layout_width="56dp"
app:smileyColor="#ffff00"
app:smileyExpression="happy" />
</FrameLayout>
Tip: Custom attributes do not work with the tools: prefix in Android Studio 2.1 and older (and possibly in
future versions). In this example, replacing app:smileyColor with tools:smileyColor would result in
smileyColor neither being set during runtime nor at design time.
3. Read your attributes: this is done inside your custom view source code. The following snippet of
SmileyView demonstrates how the attributes can be extracted:
public class SmileyView extends View {
// ...
public SmileyView(Context context) {
this(context, null);
}
public SmileyView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public SmileyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SmileyView,
defStyleAttr, 0);
mFaceColor = a.getColor(R.styleable.SmileyView_smileyColor, Color.TRANSPARENT);
mFaceExpression = a.getInteger(R.styleable.SmileyView_smileyExpression,
Expression.HAPPY);
// Important: always recycle the TypedArray
a.recycle();
// initPaints(); ...
}
}
4. (Optional) Add default style: this is done by adding a style with the default values and loading it inside your
custom view. The following default smiley style represents a happy yellow one:
<!-- styles.xml -->
<style name="DefaultSmileyStyle">
<item name="smileyColor">#ffff00</item>
<item name="smileyExpression">happy</item>
</style>
Which gets applied in our SmileyView by adding it as the last parameter of the call to
obtainStyledAttributes (see code in step 3):
GoalKicker.com – Android™ Notes for Professionals 216
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.SmileyView, defStyleAttr,
R.style.DefaultSmileyViewStyle);
Note that any attribute values set in the inflated layout file (see code in step 2) will override the
corresponding values of the default style.
5. (Optional) Provide styles inside themes: this is done by adding a new style reference attribute which can
be used inside your themes and providing a style for that attribute. Here we simply name our reference
attribute smileyStyle:
<!-- attrs.xml -->
<attr name="smileyStyle" format="reference" />
Which we then provide a style for in our app theme (here we just reuse the default style from step 4):
<!-- themes.xml -->
<style name="AppTheme" parent="AppBaseTheme">
<item name="smileyStyle">@style/DefaultSmileyStyle</item>
</style>
Section 28.3: CustomView performance tips
Do not allocate new objects in onDraw
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Paint paint = new Paint(); //Do not allocate here
}
Instead of drawing drawables in canvas...
drawable.setBounds(boundsRect);
drawable.draw(canvas);
Use a Bitmap for faster drawing:
canvas.drawBitmap(bitmap, srcRect, boundsRect, paint);
Do not redraw the entire view to update just a small part of it. Instead redraw the specific part of view.
invalidate(boundToBeRefreshed);
If your view is doing some continuous animation, for instance a watch-face showing each and every second, at least
stop the animation at onStop() of the activity and start it back on onStart() of the activity.
Comments
Post a Comment