Image 1

Android

Notes for Professionals

Android™

Notes for Professionals

1000+ pages

of professional hints and tricks

GoalKicker.com

Disclaimer

This is an unocial free book created for educational purposes and is

Free Programming Books

not aliated with ocial Android™ group(s) or company(s).

All trademarks and registered trademarks are

the property of their respective owners

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 dierent Textsize ............................................................................................................ 39

Section 4.7: Theme and Style customization ............................................................................................................ 39

Section 4.8: TextView customization ......................................................................................................................... 41

Section 4.9: Single TextView with two dierent 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: ItemOsetDecoration 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 Dierent 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 dierent 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: Dierent 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 dierent 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 dierent 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 Dierent priorities in notification ......................................................................................... 486

Section 69.7: Set custom notification icon using `Picassò 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 dierent 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 Buer 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 PorterDuXfermode ..................................... 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 oine 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: Ecient 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: ìnputypeàttribute ............................................................................................................................ 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 Buers ................................................................................................................... 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 Oset ................................................................................................................................ 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 Eectively ................................................................................................ 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

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 [email protected]

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:

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.

Image 2

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

Image 3

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.

Image 4

Image 5

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.

Image 6

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.

Image 7

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>

Image 8

</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

// 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)

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

Image 9

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/...

Image 10

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.

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;

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

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:

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

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

Image 11

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 room-

service 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:

Image 12

Image 13

3. Now click the + Create Virtual Device... button. This will bring up Virtual Device Configuration Dialog:

Image 14

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.

Image 15

Image 16

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.

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

Image 17

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

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

Image 18

Image 19

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

Image 20

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:

Image 21

Image 22

Choose the appropriate color:

Section 2.8: Filter logs from UI

Android logs can be filtered directly from the UI. Using this code

Image 23

Image 24

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

Image 25

Image 26

Image 27

Image 28

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.

Image 29

Image 30

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?

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

Image 31

Image 32

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);

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

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"

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:

Image 33

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);

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 dierent 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"

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:

<?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 {

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) {

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" >

<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 dierent 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:

Image 34

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);

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() {

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) {

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.

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 auto-

sizing 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”

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.

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;

}

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);

}

});

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) {

}

});

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="https://b.horje.com/android/@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

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);

}

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

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" >

<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:

Image 35

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"

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:

Image 36

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:

<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="https://b.horje.com/android/@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"

Image 37

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

- 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:

Image 38

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

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="https://b.horje.com/android/@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:

Image 39

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="https://b.horje.com/android/@drawable/nougat"

android:scaleType="fitCenter"

android:layout_height="match_parent"

android:layout_width="match_parent" />

Image 40

<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"

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>

Image 41

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:

<?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="https://b.horje.com/android/@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"

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"

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.

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);

Image 42

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>

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"

>

<android.support.design.widget.TextInputEditText

android:id="@+id/description"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

</android.support.design.widget.TextInputLayout>

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="...."

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> {...}

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);

}

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) {

}

});

Image 43

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" />

<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" />

</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);

}

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() {

// 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:

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

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

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;

}

}

}

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" ?>

<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

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"

Image 44

Image 45

android:scaleType="centerCrop"

android:src="https://b.horje.com/android/@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)

Image 46

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);

}

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="https://b.horje.com/android/@android:drawable/sym_def_app_icon"

android:id="@+id/imageView" />

<TextView

android:layout_width="match_parent"

android:layout_height="wrap_content"

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="[email protected]"

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="https://b.horje.com/android/@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"

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);

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);

Image 47

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" >

Image 48

<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

Image 49

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);

Image 50

navMenuView.addItemDecoration(new DividerItemDecoration(context,DividerItemDecoration.VERTICAL));

Preview :

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

A view previously used to display data for a specific adapter position may be placed in a cache for

Recycle (view) later reuse to display the same type of data again later. This can drastically improve performance by

skipping initial layout inflation or construction

A child view that has entered into a temporarily detached state during layout. Scrap views may be

Scrap (view) 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);

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 on-

screen:

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,

* 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"

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;

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);

}

}

}

}

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...

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

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

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) {

Image 51

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) {

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();

}

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` tòtoPosìn 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:

Image 52

@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());

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"

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:[email protected]'

compile 'com.mikepenz:iconics-core:[email protected]'

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.

@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) {

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'

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

Image 53

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);

Image 54

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 :

Image 55

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 .

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);

}

}

}

}

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:

// in your onCreate()

RecyclerView rv = (RecyclerView) findItemById(R.id.myList);

rv.addItemDecoration(new MyItemDecoration(context));

Section 17.5: ItemOsetDecoration 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

<dimen name="item_offset" > 5dp</dimen>

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

}

}

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) {

}

@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;

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

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]);

}

// 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;

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) {

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();

}

});

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);

}

@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;

}

});

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

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();

}

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);

}

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" >

<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" />

</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);

}

// ...

}

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

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:

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:

compile 'com.squareup.picasso:picasso:2.5.2'

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<>();

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

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) {

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);

}

}

}

Image 56

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:

Image 57

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.

Image 58

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="https://b.horje.com/android/@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.

Image 59

Image 60

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.

Image 61

Image 62

5. fitXY: Scale the image using FILL.

6. fitStart: Scale the image using START.

Image 63

Image 64

7. fitCenter: Scale the image using CENTER.

8. fitEnd: Scale the image using END.

Image 65

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="https://b.horje.com/android/@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)

Image 66

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

Image 67

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:

Image 68

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.

Image 69

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.

Image 70

But if one of the sizes are small, it will fit to that size.

Image 71

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"

Image 72

android:src="https://b.horje.com/android/@mipmap/ic_launcher"

android:id="@+id/imageView"

android:scaleType="fitStart"

android:layout_gravity="center"

android:background="@android:color/holo_orange_light" />

Image 73

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="https://b.horje.com/android/@mipmap/ic_launcher"

android:id="@+id/imageView"

android:scaleType="fitEnd"

android:layout_gravity="center"

android:background="@android:color/holo_orange_light" />

Image 74

Image 75

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 )

Image 76

Same width and height.

Image 77

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="https://b.horje.com/android/@drawable/android2"

set a drawable programmatically:

ImageView imgExample = (ImageView) findViewById(R.id.imgExample);

Image 78

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="https://b.horje.com/android/@mipmap/ic_launcher"

android:id="@+id/imageView"

android:scaleType="fitXY"

android:layout_gravity="center"

android:background="@android:color/holo_orange_light" />

Image 79

Image 80

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);

}

@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"

android:src="https://b.horje.com/android/@mipmap/ic_launcher" />

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" />

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 {

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;

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;

}

// 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();

}

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;

}

@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);

}

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;

}

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();

}

}

};

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);

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();

}

}

@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();

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.

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

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

<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

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:

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.

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;

@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:

Image 81

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);

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});

}

}

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);

}

}

}

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:

Image 82

Image 83

//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

<?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;

}

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.

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)

{

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

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)

{

}

}

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" >

<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();

}

}

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.

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" >

Image 84

<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:

<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):

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.

Do not do any calculations inside the onDraw method of a view, you should instead finish drawing before calling

invalidate(). By using this technique you can avoid frame dropping in your view.

Rotations

The basic operations of a view are translate, rotate, etc... Almost every developer has faced this problem when they

use bitmap or gradients in their custom view. If the view is going to show a rotated view and the bitmap has to be rotated in that custom view, many of us will think that it will be expensive. Many think that rotating a bitmap is very

expensive because in order to do that, you need to translate the bitmap's pixel matrix. But the truth is that it is not

that tough! Instead of rotating the bitmap, just rotate the canvas itself!

// Save the canvas state

int save = canvas.save();

// Rotate the canvas by providing the center point as pivot and angle

canvas.rotate(pivotX, pivotY, angle);

// Draw whatever you want

// Basically whatever you draw here will be drawn as per the angle you rotated the canvas

canvas.drawBitmap(...);

// Now restore your your canvas to its original state

canvas.restore(save);

// Unless canvas is restored to its original state, further draw will also be rotated.

Section 28.4: Creating a compound view

A compound view is a custom ViewGroup that's treated as a single view by the surrounding program code. Such a

ViewGroup can be really useful in DDD-like design, because it can correspond to an aggregate, in this example, a Contact. It can be reused everywhere that contact is displayed.

This means that the surrounding controller code, an Activity, Fragment or Adapter, can simply pass the data object

to the view without picking it apart into a number of different UI widgets.

This facilitates code reuse and makes for a better design according to SOLID priciples.

The layout XML

This is usually where you start. You have an existing bit of XML that you find yourself reusing, perhaps as an

<include/> . Extract it into a separate XML file and wrap the root tag in a <merge> element:

<?xml version="1.0" encoding="utf-8" ?>

<merge xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent" >

<ImageView

android:id="@+id/photo"

android:layout_width="48dp"

android:layout_height="48dp"

android:layout_alignParentRight="true" />

<TextView

android:id="@+id/name"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_toLeftOf="@id/photo" />

<TextView

android:id="@+id/phone_number"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@id/name"

android:layout_toLeftOf="@id/photo" />

</merge>

This XML file keeps working in the Layout Editor in Android Studio perfectly fine. You can treat it like any other

layout.

The compound ViewGroup

Once you have the XML file, create the custom view group.

import android.annotation.TargetApi;

import android.content.Context;

import android.os.Build;

import android.util.AttributeSet;

import android.view.LayoutInflater;

import android.view.View;

import android.widget.RelativeLayout;

import android.widget.ImageView;

import android.widget.TextView;

import myapp.R;

/**

* A compound view to show contacts.

*

* This class can be put into an XML layout or instantiated programmatically, it

* will work correctly either way.

*/

public class ContactView extends RelativeLayout {

// This class extends RelativeLayout because that comes with an automatic

// (MATCH_PARENT, MATCH_PARENT) layout for its child item. You can extend

// the raw android.view.ViewGroup class if you want more control. See the

// note in the layout XML why you wouldn't want to extend a complex view

// such as RelativeLayout.

// 1. Implement superclass constructors.

public ContactView(Context context) {

super(context);

init(context, null);

}

// two extra constructors left out to keep the example shorter

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

public ContactView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

init(context, attrs);

}

// 2. Initialize the view by inflating an XML using `thisàs parent

private TextView mName;

private TextView mPhoneNumber;

private ImageView mPhoto;

private void init(Context context, AttributeSet attrs) {

LayoutInflater.from(context).inflate(R.layout.contact_view, this, true);

mName = (TextView) findViewById(R.id.name);

mPhoneNumber = (TextView) findViewById(R.id.phone_number);

mPhoto = (ImageView) findViewById(R.id.photo);

}

// 3. Define a setter that's expressed in your domain model. This is what the example is

// all about. All controller code can just invoke this setter instead of fiddling with

// lots of strings, visibility options, colors, animations, etc. If you don't use a

// custom view, this code will usually end up in a static helper method (bad) or copies

// of this code will be copy-pasted all over the place (worse).

public void setContact(Contact contact) {

mName.setText(contact.getName());

mPhoneNumber.setText(contact.getPhoneNumber());

if (contact.hasPhoto()) {

mPhoto.setVisibility(View.VISIBLE);

mPhoto.setImageBitmap(contact.getPhoto());

} else {

mPhoto.setVisibility(View.GONE);

}

}

}

The init(Context, AttributeSet) method is where you would read any custom XML attributes as explained in

Adding Attributes to Views.

With these pieces in place, you can use it in your app.

Usage in XML

Here's an example fragment_contact_info.xml that illustrates how you'd put a single ContactView on top of a list

of messages:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical" >

<!-- The compound view becomes like any other view XML element -->

<myapp.ContactView

android:id="@+id/contact"

android:layout_width="match_parent"

android:layout_height="wrap_content" />

<android.support.v7.widget.RecyclerView

android:id="@+id/message_list"

android:layout_width="match_parent"

android:layout_height="0dp"

android:layout_weight="1" />

</LinearLayout>

Usage in Code

Here's an example RecyclerView.Adapter that shows a list of contacts. This example illustrates just how much

cleaner the controller code gets when it's completely free of View manipulation.

package myapp;

import android.content.Context;

import android.support.v7.widget.RecyclerView;

import android.view.ViewGroup;

public class ContactsAdapter extends RecyclerView.Adapter<ContactsViewHolder> {

private final Context context;

public ContactsAdapter(final Context context) {

this.context = context;

}

@Override

public ContactsViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {

ContactView v = new ContactView(context); // <--- this

return new ContactsViewHolder(v);

}

@Override

public void onBindViewHolder(ContactsViewHolder holder, int position) {

Contact contact = this.getItem(position);

holder.setContact(contact); // <--- this

}

static class ContactsViewHolder extends RecyclerView.ViewHolder {

public ContactsViewHolder(ContactView itemView) {

super(itemView);

}

public void setContact(Contact contact) {

((ContactView) itemView).setContact(contact); // <--- this

}

}

}

Section 28.5: Compound view for SVG/VectorDrawable as

drawableRight

Main motive to develop this compound view is, below 5.0 devices does not support svg in drawable inside

TextView/EditText. One more pros is, we can set height and width of drawableRight inside EditText. I have

separated it from my project and created in separate module. Module Name : custom_edit_drawable (short

name for prefix- c_d_e)

"c_d_e_" prefix to use so that app module resources should not override them by mistake. Example : "abc" prefix is used by google in support library.

build.gradle

dependencies {

compile 'com.android.support:appcompat-v7:25.3.1'

}

use AppCompat >= 23

Layout file : c_e_d_compound_view.xml

<?xml version="1.0" encoding="utf-8" ?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="wrap_content" >

<EditText

android:id="@+id/edt_search"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:inputType="text"

android:maxLines="1"

android:paddingEnd="40dp"

android:paddingLeft="5dp"

android:paddingRight="40dp"

android:paddingStart="5dp" />

<!--make sure you are not using ImageView instead of this-->

<android.support.v7.widget.AppCompatImageView

android:id="@+id/drawbleRight_search"

android:layout_width="30dp"

android:layout_height="30dp"

android:layout_gravity="right|center_vertical"

android:layout_marginLeft="8dp"

android:layout_marginRight="8dp" />

</FrameLayout>

Custom Attributes : attrs.xml

<?xml version="1.0" encoding="utf-8" ?>

<resources>

<declare-styleable name="EditTextWithDrawable" >

<attr name="c_e_d_drawableRightSVG" format="reference" />

<attr name="c_e_d_hint" format="string" />

<attr name="c_e_d_textSize" format="dimension" />

<attr name="c_e_d_textColor" format="color" />

</declare-styleable>

</resources>

Code : EditTextWithDrawable.java

public class EditTextWithDrawable extends FrameLayout {

public AppCompatImageView mDrawableRight;

public EditText mEditText;

public EditTextWithDrawable(Context context) {

super(context);

init(null);

}

public EditTextWithDrawable(Context context, AttributeSet attrs) {

super(context, attrs);

init(attrs);

}

public EditTextWithDrawable(Context context, AttributeSet attrs, int defStyleAttr) {

super(context, attrs, defStyleAttr);

init(attrs);

}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)

public EditTextWithDrawable(Context context, AttributeSet attrs, int defStyleAttr, int

defStyleRes) {

super(context, attrs, defStyleAttr, defStyleRes);

init(attrs);

}

private void init(AttributeSet attrs) {

if (attrs != null && !isInEditMode()) {

LayoutInflater inflater = (LayoutInflater) getContext()

.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

inflater.inflate(R.layout.c_e_d_compound_view, this, true);

mDrawableRight = (AppCompatImageView) ((FrameLayout) getChildAt(0)).getChildAt(1);

mEditText = (EditText) ((FrameLayout) getChildAt(0)).getChildAt(0);

TypedArray attributeArray = getContext().obtainStyledAttributes(

attrs,

R.styleable.EditTextWithDrawable);

int drawableRes =

attributeArray.getResourceId(

R.styleable.EditTextWithDrawable_c_e_d_drawableRightSVG, -1);

if (drawableRes != -1) {

mDrawableRight.setImageResource(drawableRes);

}

mEditText.setHint(attributeArray.getString(

R.styleable.EditTextWithDrawable_c_e_d_hint));

mEditText.setTextColor(attributeArray.getColor(

R.styleable.EditTextWithDrawable_c_e_d_textColor, Color.BLACK));

int textSize =

attributeArray.getDimensionPixelSize(R.styleable.EditTextWithDrawable_c_e_d_textSize, 15);

mEditText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);

android.view.ViewGroup.LayoutParams layoutParams = mDrawableRight.getLayoutParams();

layoutParams.width = (textSize * 3) / 2;

layoutParams.height = (textSize * 3) / 2;

mDrawableRight.setLayoutParams(layoutParams);

attributeArray.recycle();

}

}

}

Example : How to use above view

Layout : activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:orientation="vertical" >

<com.customeditdrawable.AppEditTextWithDrawable

android:id="@+id/edt_search_emp"

android:layout_width="match_parent"

android:layout_height="wrap_content"

app:c_e_d_drawableRightSVG="@drawable/ic_svg_search"

app:c_e_d_hint="@string/hint_search_here"

app:c_e_d_textColor="@color/text_color_dark_on_light_bg"

app:c_e_d_textSize="@dimen/text_size_small" />

</LinearLayout>

Activity : MainActivity.java

public class MainActivity extends AppCompatActivity {

EditTextWithDrawable mEditTextWithDrawable;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mEditTextWithDrawable= (EditTextWithDrawable) findViewById(R.id.edt_search_emp);

}

}

Section 28.6: Responding to Touch Events

Many custom views need to accept user interaction in the form of touch events. You can get access to touch events

by overriding onTouchEvent. There are a number of actions you can filter out. The main ones are

ACTION_DOWN: This is triggered once when your finger first touches the view.

ACTION_MOVE: This is called every time your finger moves a little across the view. It gets called many times.

ACTION_UP: This is the last action to be called as you lift your finger off the screen.

You can add the following method to your view and then observe the log output when you touch and move your

finger around your view.

@Override

public boolean onTouchEvent(MotionEvent event) {

int x = (int) event.getX();

int y = (int) event.getY();

int action = event.getAction();

switch (action) {

case MotionEvent.ACTION_DOWN:

Log.i("CustomView", "onTouchEvent: ACTION_DOWN: x = " + x + ", y = " + y);

break;

case MotionEvent.ACTION_MOVE:

Log.i("CustomView", "onTouchEvent: ACTION_MOVE: x = " + x + ", y = " + y);

break;

case MotionEvent.ACTION_UP:

Log.i("CustomView", "onTouchEvent: ACTION_UP: x = " + x + ", y = " + y);

break;

}

return true;

}

Further reading:

Android official documentation: Responding to Touch Events

Chapter 29: Getting Calculated View

Dimensions

Section 29.1: Calculating initial View dimensions in an Activity

package com.example;

import android.os.Bundle;

import android.support.annotation.Nullable;

import android.util.Log;

import android.view.View;

import android.view.ViewTreeObserver;

public class ExampleActivity extends Activity {

@Override

protected void onCreate(@Nullable final Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_example);

final View viewToMeasure = findViewById(R.id.view_to_measure);

// viewToMeasure dimensions are not known at this point.

// viewToMeasure.getWidth() and viewToMeasure.getHeight() both return 0,

// regardless of on-screen size.

viewToMeasure.getViewTreeObserver().addOnPreDrawListener(new

ViewTreeObserver.OnPreDrawListener() {

@Override

public boolean onPreDraw() {

// viewToMeasure is now measured and laid out, and displayed dimensions are known.

logComputedViewDimensions(viewToMeasure.getWidth(), viewToMeasure.getHeight());

// Remove this listener, as we have now successfully calculated the desired

dimensions.

viewToMeasure.getViewTreeObserver().removeOnPreDrawListener(this);

// Always return true to continue drawing.

return true;

}

});

}

private void logComputedViewDimensions(final int width, final int height) {

Log.d("example", "viewToMeasure has width " + width);

Log.d("example", "viewToMeasure has height " + height);

}

}

Chapter 30: Adding a FuseView to an

Android Project

Export a Fuse.View from fusetools and use it inside an existing android project.

Our goal is to export the entire hikr sample app and use it inside an Activity.

Final work can be found @lucamtudor/hikr-fuse-view

Section 30.1: hikr app, just another android.view.View

Prerequisites

you should have fuse installed (https://www.fusetools.com/downloads)

you should have done the introduction tutorial

in terminal: fuse install android

in terminal: uno install Fuse.Views

Step 1

git clone https: //github.com/fusetools/hikr

Step 2 : Add package reference to Fuse.Views

Find hikr.unoproj file inside the project root folder and add "Fuse.Views" to the "Packages" array.

{

"RootNamespace":"",

"Packages": [

"Fuse",

"FuseJS",

"Fuse.Views"

],

"Includes": [

"*",

"Modules/*.js:Bundle"

]

}

Step 3 : Make HikrApp component to hold the entire app

3.1 In the project root folder make a new file called HikrApp.ux and paste the contents of MainView.ux.

HikrApp.ux

<App Background="#022328" >

<iOS.StatusBarConfig Style="Light" />

<Android.StatusBarConfig Color="#022328" />

<Router ux:Name="router" />

<ClientPanel>

<Navigator DefaultPath="splash" >

<SplashPage ux:Template="splash" router="router" />

<HomePage ux:Template="home" router="router" />

<EditHikePage ux:Template="editHike" router="router" />

</Navigator>

</ClientPanel>

</App>

3.2 In HikrApp.ux

replace the <App> tags with <Page>

add ux:Class="HikrApp" to the opening <Page>

remove <ClientPanel> , we don't have to worry anymore about the status bar or the bottom nav buttons

HikrApp.ux

<Page ux:Class="HikrApp" Background="#022328" >

<iOS.StatusBarConfig Style="Light" />

<Android.StatusBarConfig Color="#022328" />

<Router ux:Name="router" />

<Navigator DefaultPath="splash" >

<SplashPage ux:Template="splash" router="router" />

<HomePage ux:Template="home" router="router" />

<EditHikePage ux:Template="editHike" router="router" />

</Navigator>

</Page>

3.3 Use the newly created HikrApp component inside MainView.ux

Replace the content of MainView.ux file with:

<App>

<HikrApp/>

</App>

Our app is back to its normal behavior, but we now have extracted it to a separate component called HikrApp

Step 4 Inside MainView.ux replace the <App> tags with <ExportedViews> and add ux:Template="HikrAppView" to

<HikrApp />

<ExportedViews>

<HikrApp ux:Template="HikrAppView" />

</ExportedViews>

Remember the template HikrAppView, because we'll need it to get a reference to our view from Java.

Note. From the fuse docs:

ExportedViews will behave as App when doing normal fuse preview and uno build

Not true. You will get this error when previewing from Fuse Studio:

Error: Couldn't find an App tag in any of the included UX files. Have you forgot to include the UX file that contains the app tag?

Step 5 Wrap SplashPage.ux's <DockPanel> in a <GraphicsView>

<Page ux:Class="SplashPage" >

<Router ux:Dependency="router" />

<JavaScript File="SplashPage.js" />

<GraphicsView>

<DockPanel ClipToBounds="true" >

<Video Layer="Background" File="../Assets/nature.mp4" IsLooping="true" AutoPlay="true"

StretchMode="UniformToFill" Opacity="0.5" >

<Blur Radius="4.75" />

</Video>

<hikr.Text Dock="Bottom" Margin="10" Opacity=".5" TextAlignment="Center"

FontSize="12" > original video by Graham Uhelski</hikr.Text>

<Grid RowCount="2" >

<StackPanel Alignment="VerticalCenter" >

<hikr.Text Alignment="HorizontalCenter" FontSize="70" > hikr</hikr.Text>

<hikr.Text Alignment="HorizontalCenter" Opacity=".5" > get out there</hikr.Text>

</StackPanel>

<hikr.Button Text="Get Started" FontSize="18" Margin="50,0"

Alignment="VerticalCenter" Clicked="{goToHomePage}" />

</Grid>

</DockPanel>

</GraphicsView>

</Page>

Step 6 Export the fuse project as an aar library

in terminal, in root project folder: uno clean

in terminal, in root project folder: uno build -t=android -DLIBRARY

Step 7 Prepare your android project

copy the aar from .../rootHikeProject/build/Android/Debug/app/build/outputs/aar/app-debug.aar to

.../androidRootProject/app/libs

add flatDir { dirs 'libs' } to the root build.gradle file

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript { ... }

...

allprojects {

repositories {

jcenter()

flatDir {

dirs 'libs'

}

}

}

...

add compile(name: 'app-debug', ext: 'aar') to dependencies in app/build.gradle

apply plugin: 'com.android.application'

android {

compileSdkVersion 25

buildToolsVersion "25.0.2"

defaultConfig {

applicationId "com.shiftstudio.fuseviewtest"

minSdkVersion 16

targetSdkVersion 25

versionCode 1

versionName "1.0"

testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"

}

buildTypes {

release {

minifyEnabled false

proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'

}

}

}

dependencies {

compile(name: 'app-debug', ext: 'aar')

compile fileTree(dir: 'libs', include: ['*.jar'])

androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {

exclude group: 'com.android.support', module: 'support-annotations'

})

compile 'com.android.support:appcompat-v7:25.3.1'

testCompile 'junit:junit:4.12'

}

add the following properties to the activity inside AndroidManifest.xml

android:launchMode="singleTask"

android:taskAffinity=""

android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize"

Your AndroidManifest.xml will look like this:

<?xml version="1.0" encoding="utf-8" ?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

package="com.shiftstudio.fuseviewtest" >

<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"

android:launchMode="singleTask"

android:taskAffinity=""

android:configChanges="orientation|keyboardHidden|screenSize|smallestScreenSize" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

</application>

</manifest>

Step 8: Show the Fuse.View HikrAppView in your Activity

note that your Activity needs to inherit FuseViewsActivity

public class MainActivity extends FuseViewsActivity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

final ViewHandle fuseHandle = ExportedViews.instantiate("HikrAppView");

final FrameLayout root = (FrameLayout) findViewById(R.id.fuse_root);

final View fuseApp = fuseHandle.getView();

root.addView(fuseApp);

}

}

activity_main.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:id="@+id/activity_main"

android:layout_width="match_parent"

android:layout_height="match_parent"

android:orientation="vertical"

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.shiftstudio.fuseviewtest.MainActivity" >

<TextView

android:layout_width="wrap_content"

android:layout_gravity="center_horizontal"

android:textSize="24sp"

android:textStyle="bold"

android:layout_height="wrap_content"

android:text="Hello World, from Kotlin" />

<FrameLayout

android:id="@+id/fuse_root"

android:layout_width="match_parent"

android:layout_height="match_parent" >

<TextView

android:layout_width="wrap_content"

android:text="THIS IS FROM NATIVE.\nBEHIND FUSE VIEW"

android:layout_gravity="center"

android:textStyle="bold"

android:textSize="30sp"

android:background="@color/colorAccent"

android:textAlignment="center"

android:layout_height="wrap_content" />

</FrameLayout>

</LinearLayout>

Note

When you press the back button, on android, the app crashes. You can follow the issue on the fuse forum.

A/libc: Fatal signal 11 (SIGSEGV), code 1, fault addr 0xdeadcab1 in tid 18026 (io.fuseviewtest)

[ 05-25 11:52:33.658 16567:16567 W/ ]

debuggerd: handling request: pid=18026 uid=10236 gid=10236 tid=18026

And the final result is something like this. You can also find a short clip on github.

Image 85

Chapter 31: Supporting Screens With

Dierent Resolutions, Sizes

Section 31.1: Using configuration qualifiers

Android supports several configuration qualifiers that allow you to control how the system selects your alternative

resources based on the characteristics of the current device screen. A configuration qualifier is a string that you can

append to a resource directory in your Android project and specifies the configuration for which the resources

inside are designed.

To use a configuration qualifier:

1. Create a new directory in your project's res/ directory and name it using the format: <resources_name> -

<qualifier> . <resources_name> is the standard resource name (such as drawable or layout).

2. <qualifier> is a configuration qualifier, specifying the screen configuration for which these resources are to be used (such as hdpi or xlarge).

For example, the following application resource directories provide different layout designs for different screen

sizes and different drawables. Use the mipmap/ folders for launcher icons.

res/layout/my_layout.xml // layout for normal screen size ("default")

res/layout-large/my_layout.xml // layout for large screen size

res/layout-xlarge/my_layout.xml // layout for extra-large screen size

res/layout-xlarge-land/my_layout.xml // layout for extra-large in landscape orientation

res/drawable-mdpi/graphic.png // bitmap for medium-density

res/drawable-hdpi/graphic.png // bitmap for high-density

res/drawable-xhdpi/graphic.png // bitmap for extra-high-density

res/drawable-xxhdpi/graphic.png // bitmap for extra-extra-high-density

res/mipmap-mdpi/my_icon.png // launcher icon for medium-density

res/mipmap-hdpi/my_icon.png // launcher icon for high-density

res/mipmap-xhdpi/my_icon.png // launcher icon for extra-high-density

res/mipmap-xxhdpi/my_icon.png // launcher icon for extra-extra-high-density

res/mipmap-xxxhdpi/my_icon.png // launcher icon for extra-extra-extra-high-density

Section 31.2: Converting dp and sp to pixels

When you need to set a pixel value for something like Paint.setTextSize but still want it be scaled based on the

device, you can convert dp and sp values.

DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();

float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 12f, metrics);

DisplayMetrics metrics = Resources.getSystem().getDisplayMetrics();

float pixels = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12f, metrics);

Alternatively, you can convert a dimension resource to pixels if you have a context to load the resource from.

<?xml version="1.0" encoding="utf-8" ?>

<resources>

<dimen name="size_in_sp" > 12sp</dimen>

<dimen name="size_in_dp" > 12dp</dimen>

</resources>

// Get the exact dimension specified by the resource

float pixels = context.getResources().getDimension(R.dimen.size_in_sp);

float pixels = context.getResources().getDimension(R.dimen.size_in_dp);

// Get the dimension specified by the resource for use as a size.

// The value is rounded down to the nearest integer but is at least 1px.

int pixels = context.getResources().getDimensionPixelSize(R.dimen.size_in_sp);

int pixels = context.getResources().getDimensionPixelSize(R.dimen.size_in_dp);

// Get the dimension specified by the resource for use as an offset.

// The value is rounded down to the nearest integer and can be 0px.

int pixels = context.getResources().getDimensionPixelOffset(R.dimen.size_in_sp);

int pixels = context.getResources().getDimensionPixelOffset(R.dimen.size_in_dp);

Section 31.3: Text size and dierent android screen sizes

Sometimes, it's better to have only three options

style="@android:style/TextAppearance.Small"

style="@android:style/TextAppearance.Medium"

style="@android:style/TextAppearance.Large"

Use small and large to differentiate from normal screen size.

<TextView

android:id="@+id/TextViewTopBarTitle"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

style="@android:style/TextAppearance.Small" />

For normal, you don't have to specify anything.

<TextView

android:id="@+id/TextViewTopBarTitle"

android:layout_width="wrap_content"

android:layout_height="wrap_content" />

Using this, you can avoid testing and specifying dimensions for different screen sizes.

Chapter 32: ViewFlipper

A ViewFlipper is a ViewAnimator that switches between two or more views that have been added to it. Only one

child is shown at a time. If requested, the ViewFlipper can automatically flip between each child at a regular

interval.

Section 32.1: ViewFlipper with image sliding

XML file:

<ViewFlipper

android:id="@+id/viewflip"

android:layout_width="match_parent"

android:layout_height="250dp"

android:layout_weight="1"

/>

Java code:

public class BlankFragment extends Fragment{

ViewFlipper viewFlipper;

FragmentManager fragmentManager;

int gallery_grid_Images[] = {drawable.image1, drawable.image2, drawable.image3,

drawable.image1, drawable.image2, drawable.image3, drawable.image1,

drawable.image2, drawable.image3, drawable.image1

};

@Override

public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle

savedInstanceState){

View rootView = inflater.inflate(fragment_blank, container, false);

viewFlipper = (ViewFlipper)rootView.findViewById(R.id.viewflip);

for(int i=0; i<gallery_grid_Images.length; i++){

// This will create dynamic image views and add them to the ViewFlipper.

setFlipperImage(gallery_grid_Images[i]);

}

return rootView;

}

private void setFlipperImage(int res) {

Log.i("Set Filpper Called", res+"");

ImageView image = new ImageView(getContext());

image.setBackgroundResource(res);

viewFlipper.addView(image);

viewFlipper.setFlipInterval(1000);

viewFlipper.setAutoStart(true);

}

}

Chapter 33: Design Patterns

Design patterns are formalized best practices that the programmer can use to solve common problems when

designing an application or system.

Design patterns can speed up the development process by providing tested, proven development paradigms.

Reusing design patterns helps to prevent subtle issues that can cause major problems, and it also improves code

readability for coders and architects who are familiar with the patterns.

Section 33.1: Observer pattern

The observer pattern is a common pattern, which is widely used in many contexts. A real example can be taken

from YouTube: When you like a channel and want to get all news and watch new videos from this channel, you have

to subscribe to that channel. Then, whenever this channel publishes any news, you (and all other subscribers) will

receive a notification.

An observer will have two components. One is a broadcaster (channel) and the other is a receiver (you or any other

subscriber). The broadcaster will handle all receiver instances that subscribed to it. When the broadcaster fires a

new event, it will announce this to all receiver instances. When the receiver receives an event, it will have to react to

that event, for example, by turning on YouTube and playing the new video.

Implementing the observer pattern

1. The broadcaster has to provide methods that permit receivers to subscribe and unsubscribe to it. When the

broadcaster fires an event, subscribers need to be notified that an event has occurred:

class Channel{

private List<Subscriber> subscribers;

public void subscribe(Subscriber sub) {

// Add new subscriber.

}

public void unsubscribe(Subscriber sub) {

// Remove subscriber.

}

public void newEvent() {

// Notification event for all subscribers.

}

}

2. The receiver needs to implement a method that handles the event from the broadcaster:

interface Subscriber {

void doSubscribe(Channel channel);

void doUnsubscribe(Channel channel);

void handleEvent(); // Process the new event.

}

Section 33.2: Singleton Class Example

Java Singleton Pattern

To implement Singleton pattern, we have different approaches but all of them have following common concepts.

Private constructor to restrict instantiation of the class from other classes.

Private static variable of the same class that is the only instance of the class.

Public static method that returns the instance of the class, this is the global access

point for outer world to get the instance of the singleton class.

/**

* Singleton class.

*/

public final class Singleton {

/**

* Private constructor so nobody can instantiate the class.

*/

private Singleton() {}

/**

* Static to class instance of the class.

*/

private static final Singleton INSTANCE = new Singleton();

/**

* To be called by user to obtain instance of the class.

*

* @return instance of the singleton.

*/

public static Singleton getInstance() {

return INSTANCE;

}

}

Chapter 34: Activity

Parameter

Details

Intent

Can be used with startActivity to launch an Activity

Bundle

A mapping from String keys to various Parcelable values.

Context

Interface to global information about an application environment.

An Activity represents a single screen with a user interface(UI). An Android App may have more than one Activity,

for example, An email App can have one activity to list all the emails, another activity to show email contents, yet

another activity to compose new email. All the activities in an App work together to create perfect user experience.

Section 34.1: Activity launchMode

Launch mode defines the behaviour of new or existing activity in the task.

There are possible launch modes:

standard

singleTop

singleTask

singleInstance

It should be defined in android manifest in <activity/> element as android:launchMode attribute.

<activity

android:launchMode=["standard" | "singleTop" | "singleTask" | "singleInstance"] /> Standard:

Default value. If this mode set, new activity will always be created for each new intent. So it's possible to get many

activities of same type. New activity will be placed on the top of the task. There is some difference for different

android version: if activity is starting from another application, on androids <= 4.4 it will be placed on same task as

starter application, but on >= 5.0 new task will be created.

SingleTop:

This mode is almost the same as standard. Many instances of singleTop activity could be created. The difference is,

if an instance of activity already exists on the top of the current stack, onNewIntent() will be called instead of

creating new instance.

SingleTask:

Activity with this launch mode can have only one instance in the system. New task for activity will be created, if it doesn't exist. Otherwise, task with activity will be moved to front and onNewIntent will be called.

SingleInstance:

This mode is similar to singleTask. The difference is task that holds an activity with singleInstance could have

only this activity and nothing more. When singleInstance activity create another activity, new task will be created

to place that activity.

Image 86

Section 34.2: Exclude an activity from back-stack history

Let there be Activity B that can be opened, and can further start more Activities. But, user should not encounter it

when navigating back in task activities.

The simplest solution is to set the attribute noHistory to true for that <activity> tag in AndroidManifest.xml:

<activity

android:name=".B"

android:noHistory="true" >

This same behavior is also possible from code if B calls finish() before starting the next activity:

finish();

startActivity(new Intent(context, C. class));

Typical usage of noHistory flag is with "Splash Screen" or Login Activities.

Section 34.3: Android Activity LifeCycle Explained

Assume an application with a MainActivity which can call the Next Activity using a button click.

public class MainActivity extends AppCompatActivity {

private final String LOG_TAG = MainActivity. class.getSimpleName();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

Log.d(LOG_TAG, "calling onCreate from MainActivity");

}

@Override

protected void onStart() {

super.onStart();

Log.d(LOG_TAG, "calling onStart from MainActivity");

}

@Override

protected void onResume() {

super.onResume();

Log.d(LOG_TAG, "calling onResume from MainActivity");

}

@Override

protected void onPause() {

super.onPause();

Log.d(LOG_TAG, "calling onPause from MainActivity");

}

@Override

protected void onStop() {

super.onStop();

Log.d(LOG_TAG, "calling onStop from MainActivity");

}

@Override

protected void onDestroy() {

super.onDestroy();

Log.d(LOG_TAG, "calling onDestroy from MainActivity");

}

@Override

protected void onRestart() {

super.onRestart();

Log.d(LOG_TAG, "calling onRestart from MainActivity");

}

public void toNextActivity(){

Log.d(LOG_TAG, "calling Next Activity");

Intent intent = new Intent(this, NextActivity. class);

startActivity(intent);

} }

and

public class NextActivity extends AppCompatActivity {

private final String LOG_TAG = NextActivity. class.getSimpleName();

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_next);

Log.d(LOG_TAG, "calling onCreate from Next Activity");

}

@Override

protected void onStart() {

super.onStart();

Log.d(LOG_TAG, "calling onStart from Next Activity");

}

@Override

protected void onResume() {

super.onResume();

Log.d(LOG_TAG, "calling onResume from Next Activity");

}

@Override

protected void onPause() {

super.onPause();

Log.d(LOG_TAG, "calling onPause from Next Activity");

}

@Override

protected void onStop() {

super.onStop();

Log.d(LOG_TAG, "calling onStop from Next Activity");

}

@Override

protected void onDestroy() {

super.onDestroy();

Log.d(LOG_TAG, "calling onDestroy from Next Activity");

}

@Override

protected void onRestart() {

super.onRestart();

Log.d(LOG_TAG, "calling onRestart from Next Activity");

} }

When app is first created

D/MainActivity: calling onCreate from MainActivity

D/MainActivity: calling onStart from MainActivity

D/MainActivity: calling onResume from MainActivity

are called

When screen sleeps

08:11:03.142 D/MainActivity: calling onPause from MainActivity

08:11:03.192 D/MainActivity: calling onStop from MainActivity

are called. And again when it wakes up

08:11:55.922 D/MainActivity: calling onRestart from MainActivity

08:11:55.962 D/MainActivity: calling onStart from MainActivity

08:11:55.962 D/MainActivity: calling onResume from MainActivity

are called

Case1: When Next Activity is called from Main Activity

D/MainActivity: calling Next Activity

D/MainActivity: calling onPause from MainActivity

D/NextActivity: calling onCreate from Next Activity

D/NextActivity: calling onStart from Next Activity

D/NextActivity: calling onResume from Next Activity

D/MainActivity: calling onStop from MainActivity

When Returning back to the Main Activity from Next Activity using back button

D/NextActivity: calling onPause from Next Activity

D/MainActivity: calling onRestart from MainActivity

D/MainActivity: calling onStart from MainActivity

D/MainActivity: calling onResume from MainActivity

D/NextActivity: calling onStop from Next Activity

D/NextActivity: calling onDestroy from Next Activity

Case2: When Activity is partially obscured (When overview button is pressed) or When app goes to background and another app completely obscures it

D/MainActivity: calling onPause from MainActivity

D/MainActivity: calling onStop from MainActivity

and when the app is back in the foreground ready to accept User inputs,

D/MainActivity: calling onRestart from MainActivity

D/MainActivity: calling onStart from MainActivity

D/MainActivity: calling onResume from MainActivity

are called

Case3: When an activity is called to fulfill implicit intent and user has make a selection. For eg., when share button is pressed and user has to select an app from the list of applications shown

D/MainActivity: calling onPause from MainActivity

The activity is visible but not active now. When the selection is done and app is active

D/MainActivity: calling onResume from MainActivity

is called

Case4:

When the app is killed in the background(to free resources for another foreground app), onPause(for pre-

honeycomb device) or onStop(for since honeycomb device) will be the last to be called before the app is terminated.

onCreate and onDestroy will be called utmost once each time the application is run. But the onPause, onStop,

onRestart, onStart, onResume maybe called many times during the lifecycle.

Section 34.4: End Application with exclude from Recents

First define an ExitActivity in the AndroidManifest.xml

<activity

android:name="com.your_example_app.activities.ExitActivity"

android:autoRemoveFromRecents="true"

android:theme="@android:style/Theme.NoDisplay" />

Afterwards the ExitActivity-class

/**

* Activity to exit Application without staying in the stack of last opened applications

*/

public class ExitActivity extends Activity {

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

if (Utils.hasLollipop()) {

finishAndRemoveTask();

} else if (Utils.hasJellyBean()) {

finishAffinity();

} else {

finish();

}

}

/**

* Exit Application and Exclude from Recents

*

* @param context Context to use

*/

public static void exitApplication(ApplicationContext context) {

Intent intent = new Intent(context, ExitActivity. class);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK |

Intent.FLAG_ACTIVITY_NO_ANIMATION | Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

context.startActivity(intent);

}

}

Section 34.5: Presenting UI with setContentView

Activity class takes care of creating a window for you in which you can place your UI with setContentView.

There are three setContentView methods:

setContentView(int layoutResID) - Set the activity content from a layout resource.

setContentView(View view) - Set the activity content to an explicit view.

setContentView(View view, ViewGroup.LayoutParams params) - Set the activity content to an explicit view

with provided params.

When setContentView is called, this view is placed directly into the activity's view hierarchy. It can itself be a

complex view hierarchy.

Examples

Set content from resource file:

Add resource file (main.xml in this example) with view hierarchy:

<?xml version="1.0" encoding="utf-8" ?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

android:layout_width="match_parent"

android:layout_height="match_parent" >

<TextView android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:text="Hello" />

</FrameLayout>

Set it as content in activity:

public final class MainActivity extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// The resource will be inflated,

// adding all top-level views to the activity.

setContentView(R.layout.main);

}

}

Set content to an explicit view:

public final class MainActivity extends Activity {

@Override

public void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

// Creating view with container

final FrameLayout root = new FrameLayout(this);

final TextView text = new TextView(this);

text.setText("Hello");

root.addView(text);

// Set container as content view

setContentView(root);

}

}

Section 34.6: Up Navigation for Activities

Up navigation is done in android by adding android:parentActivityName="" in Manifest.xml to the activity tag.

Basically with this tag you tell the system about the parent activity of a activity.

How is it done?

<uses-permission android:name="android.permission.INTERNET" />

<application

android:name=".SkillSchoolApplication"

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:supportsRtl="true"

android:theme="@style/AppTheme" >

<activity

android:name=".ui.activities.SplashActivity"

android:theme="@style/SplashTheme" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<activity android:name=".ui.activities.MainActivity" />

<activity android:name=".ui.activities.HomeActivity"

android:parentActivityName=".ui.activities.MainActivity/> // HERE I JUST TOLD THE SYSTEM THAT

MainActivity is the parent of HomeActivity

</application>

Now when I will click on the arrow inside the toolbar of HomeActivity it will take me back to the parent activity.

Java Code

Here I will write the appropriate Java code required for this functionality.

public class HomeActivity extends AppCompatActivity {

@BindView(R.id.toolbar)

Toolbar toolbar;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_home);

ButterKnife.bind(this);

//Since i am using custom tool bar i am setting refernce of that toolbar to Actionbar. If you

are not using custom then you can simple leave this and move to next line

setSupportActionBar(toolbar);

getSupportActionBar.setDisplayHomeAsUpEnabled(true); // this will show the back arrow in

the tool bar.

}

}

If you run this code you will see when you press back button it will take you back to MainActivity. For futher

understanding of Up Navigation i would recommend reading docs

You can more customize this behaviour upon your needs by overriding

@Override

public boolean onOptionsItemSelected(MenuItem item) {

switch (item.getItemId()) {

// Respond to the action bar's Up/Home button

case android.R.id.home:

NavUtils.navigateUpFromSameTask(this); // Here you will write your logic for handling up

navigation

return true;

}

return super.onOptionsItemSelected(item);

}

Simple Hack

This is simple hack which is mostly used to navigate to parent activity if parent is in backstack. By calling

onBackPressed() if id is equal to android.R.id.home

@Override

public boolean onOptionsItemSelected(MenuItem item) {

int id = item.getItemId();

switch (id) {

case android.R.id.home:

onBackPressed();

return true;

}

return super.onOptionsItemSelected(item);

}

Section 34.7: Clear your current Activity stack and launch a

new Activity

If you want to clear your current Activity stack and launch a new Activity (for example, logging out of the app and

launching a log in Activity), there appears to be two approaches.

1. Target (API >= 16)

Calling finishAffinity() from an Activity

2. Target (11 <= API < 16)

Intent intent = new Intent(this, LoginActivity. class);

intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK

|Intent.FLAG_ACTIVITY_CLEAR_TOP);

startActivity(intent);

finish();

Chapter 35: Activity Recognition

Activity recognition is the detection of a user's physical activity in order to perform certain actions on the device,

such as taking points when a drive is detected, turn wifi off when a phone is still, or putting the ring volume to max

when the user is walking.

Section 35.1: Google Play ActivityRecognitionAPI

This is a just a simple example of how to use GooglePlay Service's ActivityRecognitionApi. Although this is a great

library, it does not work on devices that do not have Google Play Services installed.

Docs for ActivityRecognition API

Manifest

<!-- This is needed to use Activity Recognition! -->

<uses-permission android:name="com.google.android.gms.permission.ACTIVITY_RECOGNITION" />

<application

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/AppTheme" >

<activity android:name=".MainActivity" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<receiver android:name=".ActivityReceiver" />

</application>

MainActivity.java

public class MainActivity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

private GoogleApiClient apiClient;

private LocalBroadcastManager localBroadcastManager;

private BroadcastReceiver localActivityReceiver;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

apiClient = new GoogleApiClient.Builder(this)

.addApi(ActivityRecognition.API)

.addConnectionCallbacks(this)

.addOnConnectionFailedListener(this)

.build();

//This just gets the activity intent from the ActivityReceiver class

localBroadcastManager = LocalBroadcastManager.getInstance(this);

localActivityReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

ActivityRecognitionResult recognitionResult =

ActivityRecognitionResult.extractResult(intent);

TextView textView = (TextView) findViewById(R.id.activityText);

//This is just to get the activity name. Use at your own risk.

textView.setText(DetectedActivity.zzkf(recognitionResult.getMostProbableActivity().getType()));

}

};

}

@Override

protected void onResume() {

super.onResume();

//Register local broadcast receiver

localBroadcastManager.registerReceiver(localActivityReceiver, new

IntentFilter("activity"));

//Connect google api client

apiClient.connect();

}

@Override

protected void onPause() {

super.onPause();

//Unregister for activity recognition

ActivityRecognition.ActivityRecognitionApi.removeActivityUpdates(apiClient,

PendingIntent.getBroadcast(this, 0, new Intent(this, ActivityReceiver. class),

PendingIntent.FLAG_UPDATE_CURRENT));

//Disconnects api client

apiClient.disconnect();

//Unregister local receiver

localBroadcastManager.unregisterReceiver(localActivityReceiver);

}

@Override

public void onConnected(@Nullable Bundle bundle) {

//Only register for activity recognition if google api client has connected

ActivityRecognition.ActivityRecognitionApi.requestActivityUpdates(apiClient, 0,

PendingIntent.getBroadcast(this, 0, new Intent(this, ActivityReceiver. class),

PendingIntent.FLAG_UPDATE_CURRENT));

}

@Override

public void onConnectionSuspended(int i) {

}

@Override

public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {

}

}

ActivityReceiver

public class ActivityReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {

LocalBroadcastManager.getInstance(context).sendBroadcast(intent.setAction("activity"));

}

}

Section 35.2: PathSense Activity Recognition

PathSense activity recognition is another good library for devices which don't have Google Play Services, as they

have built their own activity recognition model, but requires developers register at http://developer.pathsense.com

to get an API key and Client ID.

Manifest

<application

android:allowBackup="true"

android:icon="@mipmap/ic_launcher"

android:label="@string/app_name"

android:roundIcon="@mipmap/ic_launcher_round"

android:supportsRtl="true"

android:theme="@style/AppTheme" >

<activity android:name=".MainActivity" >

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

</activity>

<receiver android:name=".ActivityReceiver" />

<!-- You need to acquire these from their website (http://developer.pathsense.com) -->

<meta-data

android:name="com.pathsense.android.sdk.CLIENT_ID"

android:value="YOUR_CLIENT_ID" />

<meta-data

android:name="com.pathsense.android.sdk.API_KEY"

android:value="YOUR_API_KEY" />

</application>

MainActivity.java

public class MainActivity extends AppCompatActivity {

private PathsenseLocationProviderApi pathsenseLocationProviderApi;

private LocalBroadcastManager localBroadcastManager;

private BroadcastReceiver localActivityReceiver;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

pathsenseLocationProviderApi = PathsenseLocationProviderApi.getInstance(this);

//This just gets the activity intent from the ActivityReceiver class

localBroadcastManager = LocalBroadcastManager.getInstance(this);

localActivityReceiver = new BroadcastReceiver() {

@Override

public void onReceive(Context context, Intent intent) {

//The detectedActivities object is passed as a serializable

PathsenseDetectedActivities detectedActivities = (PathsenseDetectedActivities)

intent.getSerializableExtra("ps");

TextView textView = (TextView) findViewById(R.id.activityText);

textView.setText(detectedActivities.getMostProbableActivity().getDetectedActivity().name());

}

};

}

@Override

protected void onResume() {

super.onResume();

//Register local broadcast receiver

localBroadcastManager.registerReceiver(localActivityReceiver, new

IntentFilter("activity"));

//This gives an update every time it receives one, even if it was the same as the last update

pathsenseLocationProviderApi.requestActivityUpdates(ActivityReceiver. class);

// This gives updates only when it changes (ON_FOOT -> IN_VEHICLE for example)

// pathsenseLocationProviderApi.requestActivityChanges(ActivityReceiver.class);

}

@Override

protected void onPause() {

super.onPause();

pathsenseLocationProviderApi.removeActivityUpdates();

// pathsenseLocationProviderApi.removeActivityChanges();

//Unregister local receiver

localBroadcastManager.unregisterReceiver(localActivityReceiver);

}

}

ActivityReceiver.java

// You don't have to use their broadcastreceiver, but it's best to do so, and just pass the result

// as needed to another class.

public class ActivityReceiver extends PathsenseActivityRecognitionReceiver {

@Override

protected void onDetectedActivities(Context context, PathsenseDetectedActivities

pathsenseDetectedActivities) {

Intent intent = new Intent("activity").putExtra("ps", pathsenseDetectedActivities);

LocalBroadcastManager.getInstance(context).sendBroadcast(intent);

}

}

Chapter 36: Split Screen / Multi-Screen

Activities

Section 36.1: Split Screen introduced in Android Nougat

implemented

Set this attribute in your manifest's or element to enable or disable multi-window display:

android:resizeableActivity=["true" | "false"]

If this attribute is set to true, the activity can be launched in split-screen and freeform modes. If the attribute is set

to false, the activity does not support multi-window mode. If this value is false, and the user attempts to launch the

activity in multi-window mode, the activity takes over the full screen.

If your app targets API level 24, but you do not specify a value for this attribute, the attribute's value defaults to

true.

The following code shows how to specify an activity's default size and location, and its minimum size, when the

activity is displayed in freeform mode:

<--These are default values suggested by google.-->

<activity android:name=".MyActivity" >

<layout android:defaultHeight="500dp"

android:defaultWidth="600dp"

android:gravity="top|end"

android:minHeight="450dp"

android:minWidth="300dp" />

</activity>

Disabled features in multi-window mode

Certain features are disabled or ignored when a device is in multi-window mode, because they don’t make sense

for an activity which may be sharing the device screen with other activities or apps. Such features include:

1. Some System UI customization options are disabled; for example, apps cannot hide the status bar if they are

not running in full-screen mode.

2. The system ignores changes to the android:screenOrientation attribute.

If your app targets API level 23 or lower

If your app targets API level 23 or lower and the user attempts to use the app in multi-window mode, the system

forcibly resizes the app unless the app declares a fixed orientation.

If your app does not declare a fixed orientation, you should launch your app on a device running Android 7.0 or

higher and attempt to put the app in split-screen mode. Verify that the user experience is acceptable when the app

is forcibly resized.

If the app declares a fixed orientation, you should attempt to put the app in multi-window mode. Verify that when

you do so, the app remains in full-screen mode.

Chapter 37: Material Design

Material Design is a comprehensive guide for visual, motion, and interaction design across platforms and devices.

Section 37.1: Adding a Toolbar

A Toolbar is a generalization of ActionBar for use within application layouts. While an ActionBar is traditionally

part of an Activity's opaque window decor controlled by the framework, a Toolbar may be placed at any

arbitrary level of nesting within a view hierarchy. It can be added by performing the following steps:

1. Make sure the following dependency is added to your module's (e.g. app's) build.gradle file under

dependencies:

compile 'com.android.support:appcompat-v7:25.3.1'

2. Set the theme for your app to one that does not have an ActionBar. To do that, edit your styles.xml file

under res/values, and set a Theme.AppCompat theme.

In this example we are using Theme.AppCompat.NoActionBar as parent of your AppTheme:

<style name="AppTheme" parent="Theme.AppCompat.NoActionBar" >

<item name="colorPrimary" > @color/primary</item>

<item name="colorPrimaryDark" > @color/primaryDark</item>

<item name="colorAccent" > @color/accent</item>

</style>

You can also use Theme.AppCompat.Light.NoActionBar or Theme.AppCompat.DayNight.NoActionBar, or any

other theme that does not inherently have an ActionBar

3. Add the Toolbar to your activity layout:

<android.support.v7.widget.Toolbar

android:id="@+id/toolbar"

android:layout_width="match_parent"

android:layout_height="?attr/actionBarSize"

android:background="?attr/colorPrimary"

android:elevation="4dp" />

Below the Toolbar you can add the rest of your layout.

4. In your Activity, set the Toolbar as the ActionBar for this Activity. Provided that you're using the

appcompat library and an AppCompatActivity, you would use the setSupportActionBar() method:

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

final Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);

setSupportActionBar(toolbar);

//...

Image 87

Image 88

}

After performing the above steps, you can use the getSupportActionBar() method to manipulate the Toolbar that

is set as the ActionBar.

For example, you can set the title as shown below:

getSupportActionBar().setTitle("Activity Title");

For example, you can also set title and background color as shown below:

CharSequence title = "Your App Name";

SpannableString s = new SpannableString(title);

s.setSpan(new ForegroundColorSpan(Color.RED), 0, title.length(),

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

getSupportActionBar().setTitle(s);

getSupportActionBar().setBackgroundDrawable(new ColorDrawable(Color.argb(128, 0, 0, 0)));

Section 37.2: Buttons styled with Material Design

The AppCompat Support Library defines several useful styles for Buttons, each of which extend a base Widget.AppCompat.Button style that is applied to all buttons by default if you are using an AppCompat theme. This

style helps ensure that all buttons look the same by default following the Material Design specification.

In this case the accent color is pink.

1. Simple Button: @style/Widget.AppCompat.Button

<Button

style="@style/Widget.AppCompat.Button"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="16dp"

android:text="@string/simple_button" />

2. Colored Button: @style/Widget.AppCompat.Button.Colored

The Widget.AppCompat.Button.Colored style extends the Widget.AppCompat.Button style and applies

automatically the accent color you selected in your app theme.

<Button

style="@style/Widget.AppCompat.Button.Colored"

android:layout_width="match_parent"

Image 89

Image 90

android:layout_height="wrap_content"

android:layout_margin="16dp"

android:text="@string/colored_button" />

If you want to customize the background color without changing the accent color in your main theme you can

create a custom theme (extending the ThemeOverlay theme) for your Button and assign it to the button's

android:theme attribute:

<Button

style="@style/Widget.AppCompat.Button.Colored"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="16dp"

android:theme="@style/MyButtonTheme" />

Define the theme in res/values/themes.xml:

<style name="MyButtonTheme" parent="ThemeOverlay.AppCompat.Light" >

<item name="colorAccent" > @color/my_color</item>

</style>

3. Borderless Button: @style/Widget.AppCompat.Button.Borderless

<Button

style="@style/Widget.AppCompat.Button.Borderless"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="16dp"

android:text="@string/borderless_button" />

4. Borderless Colored Button: @style/Widget.AppCompat.Button.Borderless.Colored

<Button

style="@style/Widget.AppCompat.Button.Borderless.Colored"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_margin="16dp"

android:text="@string/borderless_colored_button" />

Section 37.3: Adding a FloatingActionButton (FAB)

In the material design, a Floating action button represents the primary action in an Activity.

They are distinguished by a circled icon floating above the UI and have motion behaviors that include morphing,

Image 91

launching, and a transferring anchor point.

Make sure the following dependency is added to your app's build.gradle file under dependencies:

compile 'com.android.support:design:25.3.1'

Now add the FloatingActionButton to your layout file:

<android.support.design.widget.FloatingActionButton

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:layout_margin="16dp"

android:src="https://b.horje.com/android/@drawable/some_icon" />

where the src attribute references the icon that should be used for the floating action.

The result should look something like this (presuming your accent color is Material Pink):

By default, the background color of your FloatingActionButton will be set to your theme's accent color. Also, note

that a FloatingActionButton requires a margin around it to work properly. The recommended margin for the

bottom is 16dp for phones and 24dp for tablets.

Here are properties which you can use to customize the FloatingActionButton further (assuming

xmlns:app="http://schemas.android.com/apk/res-auto is declared as namespace the top of your layout):

app:fabSize: Can be set to normal or mini to switch between a normal sized or a smaller version.

app:rippleColor: Sets the color of the ripple effect of your FloatingActionButton. Can be a color resource or hex string.

app:elevation: Can be a string, integer, boolean, color value, floating point, dimension value.

app:useCompatPadding: Enable compat padding. Maybe a boolean value, such as true or false. Set to true to use compat padding on api-21 and later, in order to maintain a consistent look with older api levels.

You can find more examples about FAB here.

Section 37.4: RippleDrawable

Ripple touch effect was introduced with material design in Android 5.0 (API level 21) and the animation is

implemented by the new RippleDrawable class.

Drawable that shows a ripple effect in response to state changes. The anchoring position of the ripple for

a given state may be specified by calling setHotspot(float x, float y) with the corresponding state

attribute identifier.

Version ≥ 5.0

In general, ripple effect for regular buttons works by default in API 21 and above, and for other touchable views,

it can be achieved by specifying:

android:background="?android:attr/selectableItemBackground">

for ripples contained within the view or:

android:background="?android:attr/selectableItemBackgroundBorderless"

for ripples that extend beyond the view's bounds.

For example, in the image below,

B1 is a button that does not have any background,

B2 is set up with android:background="android:attr/selectableItemBackground"

B3 is set up with android:background="android:attr/selectableItemBackgroundBorderless"

Image 92

(Image courtesy: http://blog.csdn.net/a396901990/article/details/40187203 )

You can achieve the same in code using:

int[] attrs = new int[]{R.attr.selectableItemBackground};

TypedArray typedArray = getActivity().obtainStyledAttributes(attrs);

int backgroundResource = typedArray.getResourceId(0, 0);

myView.setBackgroundResource(backgroundResource);

Ripples can also be added to a view using the android:foreground attribute the same way as above. As the name

suggests, in case the ripple is added to the foreground, the ripple will show up above any view it is added to (e.g.

ImageView, a LinearLayout containing multiple views, etc).

If you want to customize the ripple effect into a view, you need to create a new XML file, inside the drawable

directory.

Here are few examples:

Example 1: An unbounded ripple

<ripple xmlns:android="http://schemas.android.com/apk/res/android"

android:color="#ffff0000" />

Example 2: Ripple with mask and background color

<ripple android:color="#7777777"

xmlns:android="http://schemas.android.com/apk/res/android" >

<item android:id="@android:id/mask"

android:drawable="#ffff00" />

<item android:drawable="@android:color/white" />

</ripple>

If there is view with a background already specified with a shape, corners