#Custom GridView in android
Explore tagged Tumblr posts
intelliontechnologies · 3 months ago
Text
Understanding Flutter Widgets: The Building Blocks of UI
Tumblr media
Introduction
Flutter has rapidly emerged as one of the most popular frameworks for cross-platform app development. Known for its fast development cycle, beautiful UI components, and seamless performance, Flutter is widely adopted by developers worldwide. At the core of Flutter’s functionality lies its powerful widget-based architecture.
Whether you are building a simple application or a complex one, Flutter widgets play a crucial role in shaping the user interface (UI). In this article, we will explore what Flutter widgets are, their types, and why they are essential for app development. If you’re looking to master Flutter development, consider Flutter Training in Chennai, which provides hands-on experience in building UI with widgets.
What Are Flutter Widgets?
A widget in Flutter is a UI component that controls a part of the screen. Every UI element in a Flutter app, from a simple button to a complete screen layout, is made up of widgets. Flutter follows a widget tree structure, meaning widgets are nested within each other to create complex user interfaces.
Why Widgets Are Important in Flutter
Reusability – Widgets can be used multiple times across different parts of the app.
Customization – Widgets allow developers to create unique UI experiences.
Hot Reload – Changes made to widgets can be instantly reflected in the app.
Cross-Platform Development – Widgets enable seamless UI creation for Android, iOS, web, and desktop.
Types of Flutter Widgets
Flutter offers a rich set of widgets that developers use to build stunning interfaces. These widgets are primarily classified into two categories: Stateless Widgets and Stateful Widgets.
1. Stateless Widgets
Stateless widgets are immutable, meaning their properties do not change once they are created. They are used when the UI does not require updates based on user interaction or dynamic data changes.
Examples of Stateless Widgets:
Text Widget – Displays text on the screen.
Image Widget – Loads images from assets, network, or file.
Icon Widget – Displays icons from Flutter’s icon library.
RaisedButton – A simple button with elevation.
2. Stateful Widgets
Stateful widgets are dynamic and can change based on user interactions, API responses, or other factors. They maintain a state that can be modified during the app’s lifecycle.
Examples of Stateful Widgets:
TextField – Accepts user input dynamically.
Checkbox – Allows toggling between checked and unchecked states.
Slider – Provides a sliding control for setting values.
ListView – Displays a scrollable list of widgets.
Key Flutter Widget Categories
Apart from Stateless and Stateful widgets, Flutter provides several widget categories to enhance app development.
1. Layout Widgets
Layout widgets help structure the UI elements effectively.
Column – Arranges widgets vertically.
Row – Arranges widgets horizontally.
Stack – Overlaps widgets on top of each other.
Container – Provides padding, margins, and background properties.
2. Input Widgets
These widgets facilitate user interaction.
TextField – Enables text input.
DropdownButton – Displays a list of selectable options.
Switch – Toggles between on/off states.
3. Styling Widgets
Styling widgets enhance the visual appearance of the UI.
Padding – Adds space around a widget.
Align – Aligns widgets within their parent container.
DecoratedBox – Applies decorations like colors, gradients, and borders.
4. Scrolling Widgets
Scrolling widgets help manage content overflow.
ListView – Creates a scrollable list.
GridView – Arranges widgets in a grid format.
SingleChildScrollView – Allows a single widget to be scrollable.
5. Interactive Widgets
These widgets enable user interaction.
GestureDetector – Detects gestures like taps and swipes.
InkWell – Provides visual feedback on touch.
FloatingActionButton – A button that performs primary app actions.
How Flutter Widgets Improve UI Development
1. Faster Development with Hot Reload
One of the biggest advantages of Flutter’s widget system is Hot Reload, which allows developers to instantly see the changes they make without restarting the app.
2. Consistent UI Across Platforms
Flutter widgets ensure a native-like UI experience across Android, iOS, web, and desktop platforms, making cross-platform development seamless.
3. Customization and Theming
Flutter allows extensive customization of widgets through properties like colors, shapes, and animations. Themingenables developers to apply a consistent design across the app.
Future of Flutter Widgets
As Flutter continues to evolve, its widget ecosystem is expanding with new features and optimizations. Some trends in Flutter widget development include:
Adaptive Widgets – Widgets that adjust automatically based on the platform.
Flutter Web Widgets – Enhancing Flutter’s web development capabilities.
Enhanced Performance Widgets – More efficient state management and rendering improvements.
Conclusion
Flutter widgets are the core foundation of UI development, enabling developers to create stunning, responsive, and dynamic applications. Whether you are a beginner or an experienced developer, mastering Flutter widgets is essential for building robust applications.
If you’re looking to enhance your Flutter skills and become proficient in UI development, consider Flutter Training in Chennai. With expert-led training, hands-on projects, and real-world applications, you can accelerate your journey to becoming a skilled Flutter developer.
By understanding and effectively utilizing Flutter widgets, you can unlock the full potential of cross-platform app development and deliver high-quality applications effortlessly.
0 notes
syncsas · 3 years ago
Text
How to create Custom Grid View in Android
Custom Grid View in Android
Yesterday I have written a post on Simple Grid View with single text view only. Now I am writing for the Custom Grid View having Image and Text View in each of its grids. Adapter loads the Grid View with the data from data sources. For grid view with a single text, we used ArrayAdapter of String type. For a Grid View with more than one widget, you need to create a Custom Adapter that is a user…
Tumblr media
View On WordPress
0 notes
shophub · 6 years ago
Text
Material Design UI Android Template App
Tumblr media
Material Design UI Android Template App
This delightful Android UI Design with thought to give engineers a simple and viable approach to make their applications additionally lovely. With this Android UI Design layout, you don't have to free your valuable time to set up pre-structured realistic –   it did for you from the beginning of this android UI kit! All components are enlivened with Android Material Design Template and made by their directions. Additionally, all components are accessible to be utilized in more seasoned variants of Android so you don't need a costly cell phone to have a great Material plan. You can without much of a stretch execute parts from Android UI kit just by following our gigantic and efficient documentation. Your's is simply to code, this app design template will do the structure. Simple as cake. Glad coding!
Tumblr media
Full component list Tabs – Five subjects of tabs, and five new sections prepared to utilize. Open Source ventures utilized in these components: Universal Image Loader, Pager Sliding Tab Strip. Wizards – Five topics of wizards and five new parts prepared to utilize. Open Source ventures utilized in these components: Universal Image Loader. Custom Dialogs – Six subjects of custom exchanges, prepared to utilize. Open Source ventures utilized in these components: Universal Image Loader. ListViews – Six renditions of ListViews, as Expandable rundown, Drag&Drop, Swipe-to-expel, Appearance movement, Sticky rundown headers, Google Cards. All prepared for use in a delightful Material plan style. Open Source ventures utilized in this component: Universal Image Loader, Ken Burns View, Material Ripple Layout, ListView Animations, Sticky List Headers, Animated Expandable ListView. Parallax Effect – Parallax picture impact joined with rundown see with Ken Burns impact. Open Source ventures utilized in this component: Universal Image Loader, Ken Burns View, Material Ripple Layout, Pull Zoom View, Not Boring ActionBar. Left Menu – Two adaptations of the left menu with Material structure, prepared to utilize. Open Source ventures utilized: Universal Image Loader, Material Ripple Layout. Login Page – Login page in dull and light forms, with vivified letters, prepared to utilize. Open Source ventures utilized: Float Labeled Text Field, Material Ripple Layout. Picture Gallery – Two kinds of GridViews with pictures for display, with fresh out of the plastic new plan and delightful selector. Open Source ventures utilized: Universal Image Loader, Material Ripple Layout. Shape Image Views – Eight present-day states of picture sees for your symbols, profile pictures, etc. Open Source ventures utilized: Universal Image Loader, Shape Image View. Advancement Bars – 14 sorts of round and catch advance bars and loaders arranged for your application. Open Source ventures utilized: Progress Wheel, Circular Progress Button. . Check Buttons – Dark and light forms of checkboxes enlivened by Material structure. Open Source ventures utilized: Material Ripple Layout. Sprinkle Screen – Three forms of lovely planned and enlivened sprinkle screen. Open Source ventures utilized: Universal Image Loader, Ken Burns View. Content perspectives – Prepared typography by Google guidelines for TextView. Hunt bars – Dark and light pursuit bar with inquiry recommendations arranged to put in your application. Open Source ventures utilized: Material Ripple Layout. Symbols – a wide scope of free Fontello symbols. Symbols are included by means of Fontello – not any more four distinctive measured PNGs. In our task is 46 symbol in .svg design. Bound together realistic – every single realistic component is motivated by Android Lollipop Material Design. All components arranged in one shading style to finish your application. Simple hues changing – hues are variable in one XML and essential shading for all designs and components are alterable in one line. Completed components and formats prepared to utilize – prepared XML documents and drawables for use in your application. Numerous components have activity as well as straightforwardness – wonderful straightforward movements which are increasingly prominent. All components and designs take a shot at old variants of Android (from 4.4 rendition) as well – each component has its very own AndroidMainfest.xml document with characterized minSDK. Characterize typefaces and textual styles through XMLs – no more need to make text styles from resources organizer.
Tumblr media
Read the full article
0 notes
prevajconsultants · 7 years ago
Text
Android Clean News UI Template (Templates)
ANDROID CLEAN NEWS UI TEMPLATE
It is a template for Android developer that want to create News application with clean design. The template is only layouting without data flow and communicition with backend system. This UI Template can reduce your development time and will loved by developer that hate layouting design!
FEATURES
20 Layout Pages
17 Activity
14 different Layout Pages
Custom Bottom Navigation
Custom Toolbar
Custom effects when open and close activity
using 3 type of data list, there are Gridview, ListView and RecycleView
All layout using ConstraintLayout
Using Webview for the Term Condition and Privacy Policy
Custom font for all layout
Clean architecture of code
DEMO
Download APK Demo
DOCUMENTATION
View Documentation
OPEN SOURCE SUPPORT LIBRARY
com.makeramen for the roundedimageview
PRODUCT LOG
#1.0 - (26 April 2018) - Initial Release
from CodeCanyon new items https://ift.tt/2vOH1S7 via IFTTT https://goo.gl/zxKHwc
0 notes
mobilenamic · 6 years ago
Text
How to avoid C++ models in Qt and why you should care
Many tools rely on web technologies like JavaScript and HTML for mobile app development. But a web view does not offer the performance, features and user experience of native apps.
While the Qt framework is C++ based, you can also code with QML and JavaScript. In fact, you can create full apps without even touching C++.
By reading this guide, you will learn how to avoid C++ models in Qt and develop mobile apps using QML and JavaScript only. These are the main topics covered:
How does the Qt architecture, rendering and compilation work?
How does Qt separate models and views?
Why to use a QML model instead of C++ when working with REST services?
How to add features like offline caching, file downloads or native integrations in QML?
When to use C++ and when QML?
How to structure apps that heavily rely on QML for app logic, models and views?
The Qt Architecture: Why use QML for iOS or Android Apps?
In case you have never heard of Qt: It is a powerful and feature-rich C++ framework used in many different industries. It supports development of apps for Desktop, mobile platforms and embedded systems – all from a single code base.
  One of the best things about Qt is QML, a reactive programming language (sometimes also referred a declarative language) that extends JavaScript. It allows to create stunning apps that save up to 90% of code compared to native development for iOS or Android. With less code and a single code base for iOS, Android and Desktop, your maintenance costs decrease dramatically. You can release updates to different platforms faster and have one team sharing the knowledge.
Custom Rendering and QML Item Trees
In contrast to many other cross-platform solutions, Qt offers an architecture that does not rely on native platform rendering or a web view. It moves all controls and the rendering into the app itself. To show items on the device screen, it only requires a native view with a canvas to draw onto.
This architecture breaks away from the so-called “cookie cutter” apps that have been common in the past. Instead of the native platform renderer, Qt uses app-driven custom rendering. This allows for a unified renderer and app experience across all supported platforms.
But don’t let the fact that Qt relies on C++ mislead you. Since the introduction of QML and JavaScript for rapid UI development, you can create item trees in a customizable and extensible way. You can combine and nest individual QML Items to form a tree that describes your UI. There’s no need to dive into complex C++ code!
This is how the code for a simple QML app with a “Hello World!” page looks like:
import VPlayApps 1.0 import QtQuick 2.0 App { NavigationStack { Page { title: "My First App" AppText { text: "Hello World!" anchors.centerIn: parent } } } }
Native Performance and Compilation of View Code
In the background, each QML Item uses a performant native C++ implementation. When the Qt runtime parses your QML code, it creates all QML Items as C++ objects. With your QML markup and JavaScript logic, you can control and combine them. This makes it easy to build your UI.
There’s no need to create your UI with C++ widgets. Apps created with QML offer the same performance. Qt compiles your QML tree as soon as it parses the code the first time. You get this Just-in-Time (JIT) compilation of QML apps out-of-the-box.
With the Qt Quick Compiler, you can also compile your QML code Ahead-of-Time (AOT). It transforms your QML and JavaScript directly into bytecode. This architecture makes apps powered by QML super fast and performant.
Qt MVC: Models and Views in QML
For most apps, it is a basic task to populate UI views based on some application data. Qt offers a built-in separation into model, view and delegate components. The following example visualizes a set of data records in a list:
import VPlayApps 1.0 import QtQuick 2.0 App { // data model ListModel { id: fruitModel ListElement { name: "Banana" cost: 1.95 } ListElement { name: "Apple" cost: 2.45 } ListElement { name: "Orange" cost: 3.25 } } // list page NavigationStack { Page { title: "List Page" AppListView { anchors.fill: parent model: fruitModel delegate: SimpleRow { text: name detailText: "cost: "+cost } } // AppListView } // Page } // NavigationStack } // App
The AppListView presents you with a scrollable list view. For each ListElement in your ListModel, the view instantiates the delegate Item to visualize each element in your list. In this case, a SimpleRow item represents each list element.
The ListModel type is actually a C++ QAbstractListModel implementation exposed to QML. The above code does not only create a UI tree of C++ objects. It also handles the list data in a C++ data structure – pretty nice!
It is very fast to develop user interfaces this way. And as C++ is actually used under the hood, there is no performance drawback. Still, for long-running, heavy-weight and data-intense calculations it makes sense to move away from QML. In such cases, C++ will outperform JavaScript. For more examples when mixing both languages is worth the extra effort, keep on reading this article. We’ve got you covered with details how to combine C++ code with QML as well!
Why Choose a QML ListModel instead of a Qt C++ Model?
When using QML, many Qt developers tend to believe they should at least code the model in C++. This is not the case. QML is optimized to integrate seamlessly with C++.
All QML code gets compiled to native code with native performance. And when using the Qt Quick Compiler, this already happens during compilation of the app. The QML ListModel offers a simple API and perfectly works together with view types like ListView, GridView or Repeater.
QML Best Practice: Use REST Services and JSON for your ListView
There is another big advantage of using QML and JavaScript as your main coding language: It is super easy to work with REST services and JSON data.
The application logic for QML gets written in JavaScript. QML thus has built-in support to handle variant data types like JSON structures. With a simple HTTP request, you can fetch JSON data and use it in your views.
The following code snippet retrieves and shows a list of todo entries from a REST service:
import VPlayApps 1.0 import QtQuick 2.0 App { // on app start: fetch data from REST api Component.onCompleted: { HttpRequest.get("https://jsonplaceholder.typicode.com/todos") .timeout(5000) .then(function(res) { dataFetched(res.body) }) .catch(function(err) { console.err("Fetch failed:"+err) }); } // dataFetched gets called on success of http request function dataFetched(jsonData) { listView.model = jsonData // set retrieved json data as model for list } // list page NavigationStack { Page { title: "Todo List" AppListView { id: listView anchors.fill: parent delegate: SimpleRow { text: modelData.title } } } } }
Instead of a ListModel, QML also allows you to assign JSON data structures as the model. This is very convenient when working with REST services. You can directly use the retrieved JSON result to display your data.
Drawbacks of Using JSON data for the ListView Model
A JSON structure is no ListModel and thus no QAbstractListModel implementation. You do not have the benefits of a performant C++ model in this case. Also, a JSON array is a variant type. The list can thus not expect a defined data structure to create its elements.
This results in performance and usability drawbacks. For example, when you change or replace the JSON data. The view then parses the whole model again and redraws all items from scratch. This full redraw can take a while and is noticeable by the user. You also lose the current scroll position and advanced features like transition animations are not supported.
At this point, you could think: Let’s create a ListModel and fill it with the JSON data. While this solves the performance problem, another issue quickly pops up: How do you update the model when you fetch new data from the API at a later point?
If you re-create the ListModel from scratch, the view again requires a full redraw. To avoid this, we could compare each entry of the latest JSON data with the current state of the ListModel. This allows to only synchronize changed or new data entries to the model.
But such a manual synchronization requires a lot of extra effort. It also comes with some overhead, especially when you start to compare large data sets. JavaScript and QML are not well suited to perform such data-intense operations.
But don’t worry: The next section introduces a QML component that covers exactly this synchronization. The JsonListModel is a special ListModel implementation that can handle JSON data.
How Does the JsonListModel Work?
The JsonListModel offers an easy way to transform JSON data into a QML ListModel for usage with e.g. an AppListView. This is how you can use the model for our todo list example:
import VPlayApps 1.0 import QtQuick 2.0 App { // on app start: fetch data from REST api Component.onCompleted: { HttpRequest.get("https://jsonplaceholder.typicode.com/todos") .timeout(5000) .then(function(res) { dataFetched(res.body) }) .catch(function(err) { console.err("Fetch failed:"+err) }); } // dataFetched gets called on success of http request function dataFetched(jsonData) { listView.jsonData = jsonData // set retrieved json data as model for list } // list page NavigationStack { Page { title: "Todo List" AppListView { id: listView anchors.fill: parent // property for json data, used as source for JsonListModel property var jsonData: [] // use JsonListModel as model model: JsonListModel { source: listView.jsonData keyField: "id" fields: ["id", "title"] } // delegate delegate: SimpleRow { text: title } } } } }
The JsonListModel holds a local copy of the specified JSON data. Whenever the JSON source changes, the data gets compared to the local copy of the list model. To identify each unique data record, it is important to specify the keyField of your data objects. After diffing the old and new data sets, the JsonListModel applies all detected changes individually. It thus synchronizes the model with the changed JSON data step by step.
The JsonListModel type implements the full QML ListModel API and fires separate events for all changes. The list view can thus only update relevant entries or apply transition animations. This is super useful, as you can e.g. fetch new data and simply replace the old JSON. The JsonListModel will detect all changes, and the ListView updates changed items accordingly – without a full redraw.
Benefits of JsonListModel
You thus get a much better performance and scrolling stays smooth when the list updates:
Json Model: The list jumps to the top after a model update. JsonListModel: The list keeps its scroll position. (the GIF only jumps to the top when it restarts)
To summarize, with the JsonListModel you can:
Fetch JSON data from REST APIs with QML and JavaScript.
Pass your JSON to the model, which synchronizes the data to a ListModel and prepares it for usage in your view.
Show the model data in your QML view, which now only updates items that changed.
You do not require to create a custom model in C++ when working with REST APIs and JSON data. The JsonListModel itself is your C++ model. It is fully usable from QML and can work with JSON objects of any format:
Apart from list views, the JsonListModel also supports the GridView and Repeater types to display model data. It is based on QSyncable, a syncable C++ model implementation by Ben Lau. You can find the full project on GitHub.
The JsonListModel is also available with the free V-Play SDK. The V-Play Apps module used in the above example holds many such useful components. V-Play focuses on making mobile app development with Qt as easy as possible. For example, the HttpRequest type for networking or UI types like NavigationStack are also part of the SDK.
Dynamically Sort or Filter Data with SortFilterProxyModel
To sort and filter list models, C++ Qt offers the QSortFilterProxyModel class. In the same way, you can use the SortFilterProxyModel QML type with any list model in QML. It also works in conjunction with the JsonListModel:
import VPlayApps 1.0 import QtQuick 2.0 App { Page { id: page // property with json data property var jsonData: [ { "id": 1, "title": "Apple", "type": "Fruit" }, { "id": 2, "title": "Ham", "type": "Meat" }, { "id": 3, "title": "Bacon", "type": "Meat" }, { "id": 4, "title": "Banana", "type": "Fruit" } ] // list model for json data JsonListModel { id: jsonModel source: page.jsonData keyField: "id" fields: ["id", "title", "type"] } // SortFilterProxyModel for sorting or filtering lists SortFilterProxyModel { id: sortedModel // use the Component.onCompleted handler to configure SortFilterProxyModel for JsonListModel Component.onCompleted: sourceModel = jsonModel // add a sorter to sort the list by type sorters: StringSorter { id: typeSorter; roleName: "type"; ascendingOrder: true } } // list view AppListView { anchors.fill: parent model: sortedModel delegate: SimpleRow { text: model.title } section.property: "type" section.delegate: SimpleSection { } } // Button change the sorting order AppButton { anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom text: "Change Order" onClicked: typeSorter.ascendingOrder = !typeSorter.ascendingOrder } } // Page }
This example shows a list of different fruit and meat entries. The list entries get sorted by type with the SortFilterProxyModel. You can also change the sorting order by pressing the AppButton.
Similar to JsonListModel, the SortFilterProxyModel is a C++ type exposed to QML. So for this simple QML example, all data and model-related tasks are actually performed by C++ types. When working with REST services and JSON data, you can fully handle all model and view code in QML!
Offline Caching, File Downloads and Native Integrations for your Mobile App
It is very simple to create stunning views and handle application data with QML. But why stop there? Let’s take it even one step further!
Control Your Application from QML
As QML and C++ integrate seamlessly, it is possible to expose any native feature for usage with QML. Available Qt components already allow to work with sensors, SQLite databases and much more. And the V-Play SDK offers lots of additional features. For example to fetch assets at runtime with the DownloadableResource item. It allows you to keep the initial app size small and dynamically load content if required – all with QML.
You can create your own C++ components and register them with QML as well. For iOS and Android apps, you can even add components that
weave-in native iOS code with Obj-C
or run Java Android code over JNI.
Please note that such native code requires custom implementations for each platform then. V-Play already has you covered with the NativeUtils component. It offers lots features like native dialogs, camera and image picker or sharing. The SDK also comes with many V-Play Plugins that integrate 3rd party frameworks for:
server-triggered or local notifications
in-app purchases and monetization
analytics and crash reporting
Firebase authentication and database
and much more.
There is no limit to what you can do – it’s possible to manage your full app logic purely with QML. You can even perform calculations in different threads with a WorkerScript.
App Example with JsonListModel and Offline Caching
Mobile apps have to work properly even without internet access. The Storage component allows to cache data in a simple key-value store. It can save full JSON structures as well. The data gets serialized and converted to string format automatically.
You can thus use the Storage to initialize the JsonListModel with previously cached JSON data. This way, your app can show the latest state of the data even if a fetch request fails:
import VPlayApps 1.0 import VPlay 2.0 import QtQuick 2.0 App { // on app start: fetch data Component.onCompleted: { fetchData() } // list page NavigationStack { Page { title: "Todo List" AppListView { id: listView anchors.fill: parent // property for json data, used as source for JsonListModel property var jsonData: [] // use JsonListModel as model model: JsonListModel { source: listView.jsonData keyField: "id" fields: ["id", "title"] } // delegate delegate: SimpleRow { text: title } } } } // storage for caching Storage { id: cache } // fetch data from cache or from api function fetchData() { // check cached value first var cachedData = cache.getValue("todos") if(cachedData) listView.jsonData = cachedData // load new data from api HttpRequest.get("https://jsonplaceholder.typicode.com/todos") .timeout(5000) .then(function(res) { dataFetched(res.body) }) .catch(function(err) { console.err("Fetch failed:"+err) }); } // dataFetched gets called on success of http request function dataFetched(jsonData) { // cache new data before updating the model cache.setValue("todos", jsonData) listView.jsonData = jsonData // set retrieved json data as model for list } }
In addition to fetched data, you can locally cache new entries as well. As soon as the app has internet connection again, save them to your server and remove the local entries.
We prepared a full demo app for you, which allows to browse and create todo list entries. You can find the full example with caching, local draft entries, list filtering and more on GitHub:
See Full Example on GitHub
When to Use C++ and When to Use QML
Application Development with QML is simple and powerful. But Qt C++ can be more performant, offers many features and is less error-prone. So it’s important to know when to use which.
Coding in QML has several advantages over development with C++:
Coding with QML + JavaScript is very easy to learn and allows to reduce the required amount of code a lot.
Language concepts like states, signals or property bindings are a huge time-saver.
QML makes adding animations simple. You can animate every property of your QML types with simple Animation components.
QML is extensible and flexible. For example, you can extend objects with new properties and features in-line. No need to create a new re-usable type for small extensions.
The QML Rendering Engine offers a great performance. The renderer uses C++ Qt and relies on a hardware accelerated scene graph. This makes it fast enough to power even high-performance games.
Qt app development with C++ has advantages as well. For some scenarios you need features that are only available with Qt C++. Also, C++ is fast and type-safe. This allows to provide the best possible performance for long-running and data-intense calculations.
For these examples, you would choose C++ over QML:
Native C++ code is the right choice for data-intense operations. It will outperform interpreted QML/JavaScript code.
C++ code is type-safe and compiled into object code. For parts where stability and security are important, using C++ helps to make your app less error-prone.
The Qt C++ components offer different and in some cases more features than the QML types. For example, advanced networking features.
It is also possible to mix C++ with native code for Android (over JNI) or iOS (Obj-C or Swift). This allows to provide such native functionality for QML as well.
You might need a 3rd party library that is only available in C++, or have existing code in C++ which you’d like to reuse.
It is possible to code most parts of the application without the need to touch C++. The V-Play SDK and Qt have many QML components available. For a starting point to integrate Qt C++ or make native features available for QML, you can see the guide How to Expose a Qt C++ Class with Signals and Slots to QML.
QML MVC: App Architecture Best Practices and Design Patterns
With all this knowledge and QML benefits in mind, we will use QML for more than only view code. We handle data-related tasks and application logic as well. It thus becomes very important to think about a clean app architecture and component structure for such QML-driven apps. We want to keep our code clean, maintainable and extensible.
Why care about separation of concerns?
The easiness and flexibility of QML can lead to problems. When using signals and property bindings a simple value change can affect many components. Properties that rely on other properties update automatically. They handle the signal and update their value as well. This is even possible across multiple QML Items:
  This doesn’t look complex now. But imagine that we add a few new components with different properties and cross-dependencies:
Different connections between all the items form. You can no longer say for sure what effect a single property change may have for directly or indirectly connected components. In the worst case, this can result in circular dependencies or loops. If you face such issues, this is an indicator for bad component architecture.
This problem gets bigger and bigger the more your project grows. Each component should thus have a clean interface and only manage its own data. This is what separation of concerns means.
Design Patterns like MVC, MVVM or Flux (React Native)
A bad component architecture can quickly lead to unwanted side-effects or corrupted data. Imagine lots of signals firing and event handlers running in unknown order. Your code at different parts of the app changes data seemingly random or with duplicated code. This is a nightmare for debugging, maintenance or refactoring.
For most design patterns, the golden rule is: Keep the code that displays data (view) separate from the code that reads or modifies data (model).
Model-View Separation in QML
Each content view of a V-Play app is usually composed as a Page. The Page type is a view controller, which provides and displays data for the user. By introducing a DataModel component, we can move data handling away from the view:
The DataModel is your central storage for application data. Pages can only access application data with the DataModel. It manages your data in a way that makes sense for your use-case and views. For different views and use-cases, the usage of several DataModel components is possible.
For the app logic, you will also add many functions and signal handlers to your view or model. If not done properly, this results in a lot of fragmented code spread across view items. Once your application gets more complex, it also gets more difficult to maintain your code clean and testable. It gets hard to decide where to perform which action, and duplicate code spread across pages is inevitable.
With the above architecture, the data flow between model and page is bi-directional. This means, pages do not only show model data, but can also write to the model directly. Modern application frameworks like React Native use a different approach. For example, the Flux architecture designed by Facebook favors an unidirectional data flow.
Create a clean Data Flow: QML Architecture inspired by Flux
With Flux, each user interaction propagates the action through a central dispatcher. The dispatcher forwards the action to various stores that hold application data and business logic:
You can read more about a quite sophisticated implementation of such a pattern for QML in this post by Ben Lau: Revised QML Application Architecture Guide with Flux
It’s hard to say if the overhead of a complex solution is worth the effort. For most mobile app projects, a more relaxed implementation with the same advantages is sufficient.
Simple Flux-like Example for Model View Controller Separation in QML
To create a one-directional data flow, we can also take advantage of QML’s built-in signal mechanism. We can ensure a loose coupling between different components. You can find a basic example architecture that applies this pattern in this guide: Separation of Model, View and Logic Code in your Qt App using QML
It introduces a Logic component to dispatch actions from Pages to the DataModel:
Doing a lot of work in QML can quickly result in unreadable and fragmented code. With a clean component architecture and clear responsibilities, you can avoid this. Using an architecture like above helps to provide a consistent app structure that simplifies testing and refactoring.
With the principles shown in this guide, you can create well-structured apps that handle app logic, data-related tasks and view code purely with QML.
  Not sure how to get started? V-Play offers many demos and examples you can use to build a first prototype of your project:
We can also help you out with Qt Trainings and App Development Workshops to get your team started!
  The V-Play SDK is free to use, so make sure to check it out!
Get V-Play Apps
  Do you already have a project or app idea in mind? The V-Play team is here to support you! We can cover the whole process from the first idea up to the release of your app in the stores. Take advantage of our Mobile App Development Services and join the ranks of satisfied V-Play customers:
  If you enjoyed this post, feel free to share it on Facebook or Twitter.
More Relevant App Development Resources
Qt Quick Compiler
How to Expose a Qt C++ Class with Signals and Slots to QML.
Separation of Model, View and Logic Code in your Qt App using QML
Revised QML Application Architecture Guide with Flux
The Best App Development Tutorials & Free App Templates
All of these tutorials come with full source code of the mobile apps! You can copy the code to make your own apps for free!
How to create a mobile app for iOS & Android with a single code base
How to support multiple languages and internationalization in your mobile app
Common Widgets & Controls in a cross-platform App
How to support multiple screen sizes & screen densities – Responsive App Guide
Guide for App Layout
Guide for App Navigation
How to add native code to your mobile App
How to easily style your App with Themes
How to add Animations to your App
How to add a Chat to your Mobile App
How to make a Weather App accessing a REST weather service
Conference App Template
Widget Gallery App Template
Twitter App Template
Messenger App Template
Property Finder App Template
App Development Video Tutorials
Make Cross-Platform Apps with Qt: V-Play Apps
youtube
How to Add In-App Chat or Gamification Features to Your Mobile App
youtube
How to Make a Mobile App with Qt Quick Designer (QML Designer) & V-Play
youtube
  The post How to avoid C++ models in Qt and why you should care appeared first on V-Play Engine.
How to avoid C++ models in Qt and why you should care published first on https://medium.com/@TheTruthSpy
0 notes
skptricks · 7 years ago
Text
Rendering Raw HTML in your React Native application
This tutorial explains how to render raw HTML code in react native application using WebView component. Basically WebView is a system component for the Android operating system (OS) that allows Android apps to display content from the web directly inside an application. In this example we are going to Rendering raw HTML code in android application through WebView component, it does need to be manually or pro-grammatically sized, not something natively taken care of by the component. Additionally, styling the contents of the view, to better align with the rest of the UI would require similar solution, passing style sheets into the WebView container or even worse, having style attributes within the HTML itself. NOTE : In this example we are using source prop of WebView component to display raw HTML code in android or ios screen.
Render Raw HTML Code in React Native Application Using WebView:
Lets follow the below steps to display raw HTML code in android or ios screen using WebView in React Native. Step-1: Create a new react native project, if you don’t know how to create a new project in react native just follow this tutorial. Step-2: Open index.android.js  / index.ios.js  in your favourite code editor and erase all code and follow this tutorial.Step-3: Through react , react-native  packages import all required components.
import React, { Component } from 'react'; import { Platform, StyleSheet, Text, View, WebView, } from 'react-native';
Step-4: Implement render method and place below layout design inside the render block.
htmlContent : Inside the render block,  we have created variable named as htmlContent, in which we are keeping raw HTML code.
Also we have placed the WebView component inside the render block, this will display the raw HTML code in android or ios screen. With the help of source prop, we are mapping raw HTML code with WebView Component. For example :
<WebView style={styles.container} javaScriptEnabled={true} domStorageEnabled={true} source= />
Step-5 : Apply the below style sheet design.
const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: "#e5e5e5", }, });
Complete Source Code for App.js 
Lets see the complete source code that helps to render raw HTML code  in react native application using webview.
/** * Sample React Native App * https://github.com/facebook/react-native * @flow */ import React, { Component } from 'react'; import { Platform, StyleSheet, Text, View, WebView, } from 'react-native'; export default class App extends Component { render() { var htmlContent = '<h1 style="color:red;"> Skptricks Blog </h1>' + '<h3> The Basics Of ES6 Generators - Javascript</h3>' + '<p> With ES6 generators, we have a different kind of function, which may be paused in the middle, one or many times, and resumed later, allowin... </p>' + '<img src="https://3.bp.blogspot.com/-XhR2CaeJE3M/W8oKAFPha_I/AAAAAAAACCs/MnKDQ_jtCjg8kgF9lirPAfa0CupLcsWhQCLcBGAs/s600/gene.png" alt="Image" width="90%" height="200" >' + '<h3> React Native Picker Spinner DropDown Menu List Example - Android</h3>' + '<p> In this tutorial, we are going to discuss how to create simple picker s pinner dropdown menu list in react native application . Picker Spi... </p>' + '<img src="https://4.bp.blogspot.com/-puNk3kY_CaQ/W8yOhWzPiOI/AAAAAAAACDU/VlQ9bzG3x6c_7Vfm8ENo2c3uQh1jvhd0ACLcBGAs/s600/picker.png" alt="Image" width="90%" height="200" >' + '<h3> Create Custom Snackbar Component Example In React Native- Android</h3>' + '<p> This tutorial explains how to create simple Snackbar component in react native application . Snackbars are just like Toast messages except ... </p>' + '<img src="https://2.bp.blogspot.com/-93jY0dxBGR4/W8NnVz92VSI/AAAAAAAACBc/q77WAtv-Xb0LGsSOBxGRrU1d1QXyYVT6ACLcBGAs/s600/snack.png" alt="Image" width="90%" height="200" >' + '<h3> React Native Simple Custom GridView Layout Example Android</h3>' + '<p> This tutorial explains how to create simple custom grid view in react native application. Grid View that displays items in a two-dimension... </p>' + '<img src="https://1.bp.blogspot.com/-U6DxHFlg770/W7ECe9uy4rI/AAAAAAAAB-0/Mumx0xM2APQkq4ynVni17BEo1wK1tU-NgCLcBGAs/s600/grid.png" alt="Image" width="90%" height="200" >'; return ( <WebView style={styles.container} javaScriptEnabled={true} domStorageEnabled={true} source= /> ); } } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: "center", alignItems: "center", backgroundColor: "#e5e5e5", }, });
Screenshot :
This is all about rendering Raw HTML in your React Native application. It does a fantastic job of rendering the HTML natively in the react native layout, with the option to pass in a standard react native styles object referencing standard HTML elements. Thank you for reading this article, and if you have any problem, have a another better useful solution about this article, please write message in the comment section.
via Blogger https://ift.tt/2zqcmcx
0 notes
rajeshkumar00012-blog · 7 years ago
Text
Android Training in Chennai @orangetechnomind
Android Training in Chennai
Android Introduction
Android is a Linux based operating system developed by Google for smart phones and other devices. Android have the powerful features, it is now used for developing apps in television, digital cameras and other electronic devices. One of the most popular mobile app development platform used by many of the smart phone app developers. Android is using in more than billion mobile devices. There is a high demand for Android programmer for new and maintain other products.
Android is fast becoming one of the biggest platforms for programmers today. There is a huge demand for skilled Android Developers all over the world. Most businesses across multiple domains are building Android Apps both for enterprise and retail products. Whether you are student or in the IT industry, possessing Android Development skills will help you take the next big leap in your career.
This course syllabus designed carefully to cover all major and advanced topics for job seekers. We are very sure they can learn all required knowledge Android by this course. We are providing best Android Training Institute in Chennai with industry experienced professionals and enhanced Lap supports.
Audience
This course is designed for Job seekers and technical professionals who wants to learn Android development for their job carriers and own game development.
IBM DataPower Training Syllabus
Introduction to Android
What is Android?
Setting up development environment
Dalvik Virtual Machine & .apk file extension
Fundamentals
Basic Building blocks
UI Components - Views & notifications
Components for communication -Intents & Intent Filters
Android API levels (versions & version names)
Application Structure (in detail)
AndroidManifest.xml
uses-permission & uses-sdk
Resources & R.java
Assets
Layouts & Drawable Resources
Activities and Activity lifecycle
First sample Application
Emulator-Android Virtual Device
Launching emulator
Editing emulator settings
Emulator shortcuts
Logcat usage
Introduction to DDMS
Basic UI design
Form widgets
Text Fields
Layouts
[dip, dp, sip, sp] versus px
Examples
Preferences
Shared Preferences
Preferences from xml
Examples
Menu
Option menu
Context menu
Sub menu
menu from xml
menu via code
Examples
Intents (in detail)
Explicit Intents
Implicit intents
Examples
UI design
Time and Date
Images and media
Composite
AlertDialogs & Toast
Popup
Examples
Tabs and Tab Activity
Tabs
Tab Activity
Examples
Styles & Themes
Styles.xml
drawable resources for shapes, gradients (selectors) using XML
( To design background view using XML)
style attribute in layout file
Applying themes via code and manifest file
Examples
Content Providers
SQLite Programming
SQLiteOpenHelper
SQLiteDatabse
Cursor
Reading and updating Contacts
Reading bookmarks
Example
Linkify
Web URLs, Email address, text, map address, phone numbers
Match Filter & Transform Filter
Examples
Adapters and Widgtes
Adapters
Array Adapters
Base Adapters
ListView and ListActivity
Custom listview
GridView using adapters
Gallery using adapters
Examples
Notifications
Broadcast Receivers
Services and notifications
Toast
Alarms
Examples
Custom components
Custom Tabs
Custom animated popup panels
Other components
Examples
Threads
Threads running on UI thread (run On UiThread)
Worker thread
Handlers & Runnable
AsynTask
Examples
Advanced
Live Folders
Using sdcards
XML Parsing
JSON Parsing
Maps, GPS, Location based Services
Accessing Phone services (Call, SMS, MMS)
Network connectivity services
Sensors
Third Party Api(Google map, Facebook, Google+, Twitter,GCM)
0 notes
iyarpage · 7 years ago
Text
Android App Widgets Tutorial
The most successful applications are often the simplest to use. This means that users want to see the information they need “at-a-glance” without unlocking their phone or launching the related app. On the Android platform you can achieve this in two different ways. The first, and most recent, is Android Wear, and you can learn more about in Getting Started with Android Wear with Kotlin. The second, the topic of this tutorial, is through the implementation of App Widgets. App Widgets have been available in the Android ecosystem since version Android 1.6 (Donut).
In this tutorial you’ll create an App Widget for a Coffee Log application that will allow you to control your daily usage of caffeine right from your home screen. :]
Note: Most developers love coffee, but we also know that health is very important, so I advise you to read the interesting article Health and Fitness for Developers
You’ll follow the typical process for Widget development and learn how to:
Create the Widget user interface
Get up-to-date information in the Widget
Interact with the Widget
If you’re new to Android Development, I recommended that you read Beginning Android Development with Kotlin before you start, as well as Kotlin for Android. For this tutorial you’ll also need Android Studio 3.1.2 or later.
Getting started
The first thing you should do is to download the sample project for this tutorial using the download button at the top or bottom of the tutorial. The zip file contains Android Studio projects for the starter and final versions of the Coffee Log application.
Unzip the file in a folder of your choice, go to File/Open or choose “Open an existing Android Studio project” from the Welcome to Android Studio window, and select the build.gradle file in the root folder of the starter project.
Once the project finishes loading and performing a Gradle build, you can have a look at the file structure, which should be like this:
Now that you are in the project, take a look around, especially in MainActivity, where all the logging happens. CoffeeTypes is a simple enum class with all the coffee types and their caffeine quantity in grams, while the CoffeeLoggerPersistence class is managing persistence using SharedPreferences.
It’s time to start tracking our caffeine consumption! Build and run the app by going to the Build\Make Project or using the green “play” button from the toolbar. The app will appear in your emulator or device, looking like this:
The app allows you to see how many grams of coffee you drank so far today and select new drinks to update your consumption count. Each selection leads to an update of the total displayed.
To use the app to log your coffee consumption, you have to launch the full application. As always, we can do better. What about making your user’s life simpler with an App Widget like this one?
With a Widget, you can access the same information as the application, and display a powerful motivational quote, just by using your device home screen. As you can see the layout is different because the list is now a set of 3 buttons.
There’s a lot to cover to create an App Widegt, so let’s dig in!
App widget anatomy
As the Android documentation says, an App Widget is a component that can be embedded in other applications, typically the Home screen. Security and performance are very important, so the Android platform has defined a very clear protocol that describes how an App Widget communicates with its own app and interacts with the hosting one. This is why the developer has to provide a configuration file with the following information:
The Widget layout
The Widget screen space
Whether the Widget can resize and how
A preview image that users will see when dragging the Widget on the screen
How often refreshing data can happen
An optional Configuration screen
As you’ll see, the Android system uses this information in different stages of the Widget lifecycle. The layout information is useful when the Widget is running and interacting with the user. Resize, preview and screen space required are useful when the user decides to select the Widget and drag it into the Home screen.
User interface
As you’ve seen in the previous images, apps and Widgets have different UIs. This is because the available space is different, as well as the user interaction modes. For both apps and Widgets, you can define the layout using a resource file.
You have to remember that a Widget is running in a different application and so some restrictions are in place for security and performance reasons. This means that you can only use a subset of the standard components, with which you can then interact only using a specific object of type RemoteViews. In particular, you can use only:
AnalogClock
Button
Chronometer
ImageButton
ImageView
ProgressBar
TextView
ViewFlipper
ListView
GridView
StackView
AdapterViewFlipper
Along with ViewStub, which allows a lazy inflation of a layout, you can only use the following containers:
FrameLayout
LinearLayout
RelativeLayout
GridLayout
Extensions of these classes are not allowed.
The check on these constraints is strong. Because of these restrinctions, a Widget layout has to be very simple and only use simple components like TextView, Button or ImageView.
Resizability and preview
The configuration file is the mechanism used to describe your Widget to the Android system. You can use this for setting the supported Widget sizes, telling the system whether the Widget is resizable or not, and providing an image to display when the user decides to add a Widget to their Home screen. You’ll see all of these when you insert your Widget for the first time.
Refreshing the widget
The data the Widget displays must always be up to date without wasting system resources. This means that the UI should be updated only when the data changes, and this can happen for different reasons. If the user interacts with the Widget, you need a way to update the UI and then send the event to the main app. If something is happening in the main app, you need a way to tell the Widget to refresh.
The Android platform also provides a third way, an automatic refresh of the Widget at an interval that can be set using the configuration file. Performance limitations don’t allow an update frequency greater than 30 minutes.
Widget customisation
In the case of Coffee Log, there are just three different type of coffees. But what if the user is not interested in Long coffee or they just want a different drink instead, or what if they want to simply change the quantity of grams. Or maybe the user wants to customise the background color of the Widget. As you’ll see, it’s possible to provide a configuration screen to allow all the needed customisation.
Create your Widget
Enough theory, now you can start creating your Widget. Creating a Widget requires the definition of some code and configuration files according to the specification defined by the Android platform.
Android Studio makes this process very easy, through the usage of a simple wizard, which you can access by selecting New\Widget\App widget from the File menu. You’ll see the following window:
Add the following input to the window:
Class name: CoffeeLoggerWidget
Minimum Width (cells): 3
Minimum Height (cells): 2
Here you can also see how it’s possible to define whether the Widget is resizable and what its possible destinations are. A Widget is usually part of the Home screen, but it could also part of the Keyguard, which is the screen that appears when the phone is locked.
Select Finish, and Android Studio will create three files for you:
CoffeeLoggerWidget.kt: this is a Kotlin class with the same name used in the wizard, and acts as the controller for the Widget. You’ll learn how to change this code in order to access the UI component through the RemoteViews class and how to receive and manage events from the Widget itself.
coffee_logger_widget_info.xml: this is the configuration file we described earlier with information about the refresh rate, resizability, dimensions, etc. This is the file you’re going to edit in order to provide a configuration Activity for the Widget.
coffee_logger_widget.xml: this file contains the widget’s user interface layout.
It’s important to note where all these files are in the project structure:
In particular, you see how the configuration file has been created as an XML resource file.
As you’ll see later, the wizard also made some changes to the app AndroidManifest.xml file.
Customizing the User Interface
In order to customize the UI for the Widget, open coffee_logger_widget.xml in the app\res\layout folder. The Android Studio wizard generated the following layout that you need to update:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#09C" android:padding="@dimen/widget_margin"> <TextView android:id="@+id/appwidget_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:layout_centerVertical="true" android:layout_margin="8dp" android:background="#09C" android:contentDescription="@string/appwidget_text" android:text="@string/appwidget_text" android:textColor="#ffffff" android:textSize="24sp" android:textStyle="bold|italic" /> </RelativeLayout>
Remove the TextView and replace the RelativeLayout with a LinearLayout. In Android Studio, you can do this by double-clicking on the old name and typing the new name in its place. After this change you should have this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#09C" android:padding="@dimen/widget_margin"> </LinearLayout>
Note: You’re going to use styles that are already defined in the sample project. They contain text sizes and colors, heights, widths, alignments, and other style values. If you are curious about them, check out styles.xml in the res/values folder.
Next, add three more attributes to the LinearLayout:
... android:id="@+id/widget_layout" android:orientation="vertical" android:gravity="center" ...
The android:orientation and android:gravity attributes give the LinearLayout information about how to align its content. Providing an id is also important in case we need to get a reference to the layout in the Kotlin code.
To achieve rounded corners, change the android:background attribute to @drawable/background, a drawable available in the starter project. Now the root element of the layout looks like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/widget_layout" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/background" android:gravity="center" android:orientation="vertical" android:padding="@dimen/widget_margin"> </LinearLayout>
Thinking vertically
For the sake of aesthetics, the user interface should look good regardless of the Widget size. It’s best to have the Widget elements spread over the available space. There are many ways to achieve that, but you should go for the simplest which consists of adding some TextView components that will expand in the remaining space between the rest of the elements.
Here’s a schematic of the layout you’ll create:
The green pattern will be a TextView that expands vertically and the blue pattern will be a TextView that expands horizontally. Keep this schematic in mind as you build the layout to understand why you add each element.
Note:If you’re tempted to fill the empty spaces using a Space instead of TextView, remember that a Widget has some UI restrictions and that a Space is not one of the allowed components.
The first element in the LinearLayout is a vertical space that you can define by adding this code as the first child:
<TextView style="@style/WidgetButtonVerticalSpace" />
Now you can add the TextView components for the amout of coffee:
<TextView android:id="@+id/appwidget_text" style="@style/WidgetTextView.Big" /> <TextView style="@style/WidgetTextView" android:text="@string/grams" />
Then add another TextView for the next vertical space before the buttons:
<TextView style="@style/WidgetButtonVerticalSpace" />
Notice that the first text view needs to have an id because you will need to change the text later on from the Kotlin code. The second one is fixed text. You’re using the predefined styles on the text views.
Next, add a container for the buttons as a LinearLayout with horizontal orientation:
<LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <!-- Buttons go here --> </LinearLayout>
Then a TextView for the quote after the last vertical space.
<TextView style="@style/WidgetButtonVerticalSpace" /> <TextView android:id="@+id/coffee_quote" style="@style/WidgetQuote" />
Adding buttons
Now the green part of the layout is fnished and you have to deal with the blue part for the buttons following this schematic:
You’ve already created a container for them so you just need to start with a TextView that expands horizontally and will keep the first button at a distance from the left margin:
<TextView style="@style/WidgetButtonHorizontalSpace" />
Then you can add the first button for smallest coffee in the world:
<LinearLayout android:id="@+id/ristretto_button" style="@style/WidgetBeverageButton" > <ImageView style="@style/WidgetButtonImage" android:src="@drawable/ic_ristretto" /> <TextView style="@style/WidgetButtonText" android:text="@string/ristretto_short" /> </LinearLayout> <TextView style="@style/WidgetButtonHorizontalSpace" />
Each button has a LinearLayout that contains an ImageView and a TextView. After the button, you added another horizontally expanding TextView to help the buttons spread.
Add the next button for Espresso:
<LinearLayout android:id="@+id/espresso_button" style="@style/WidgetBeverageButton"> <ImageView style="@style/WidgetButtonImage" android:src="@drawable/ic_espresso" /> <TextView style="@style/WidgetButtonText" android:text="@string/espresso_short" /> </LinearLayout> <TextView style="@style/WidgetButtonHorizontalSpace" />
And the final button for the Long:
<LinearLayout android:id="@+id/long_button" style="@style/WidgetBeverageButton" > <ImageView style="@style/WidgetButtonImage" android:src="@drawable/ic_long_coffee" /> <TextView style="@style/WidgetButtonText" android:text="@string/long_coffee_short" /> </LinearLayout> <TextView style="@style/WidgetButtonHorizontalSpace" />
Phew! That was long but you’re done with the layout for the widget. :]
Run your Widget
The Widget you’ve created is beautiful, but it’s not doing anything quite yet. Build and run your app to make sure there’s no error in the XML. Just to be sure everything is fine, add the widget to the screen. If you’ve never added a widget to your Home screen before, here are the steps:
Go to the Home screen
Long press on an empty space
Select “Widgets”
Long press on the Coffee Log Widget
Drop it wherever you like on the screen
Your widget looks like this:
Notice how the autogenerated code populated the first TextView with “EXAMPLE”. Later in this tutorial, you will update it with the right number of coffee grams.
Performing actions
Now it’s time to add some interactivity to the Widget. When the user selects a button, you’ll have to open MainActivity, passing information about the selected coffee in order to update the total number of grams in today’s record.
Unfortunately, launching a simple Intent is not enough, because we have to remember that our Widget is running in an application that is different from ours and runs in another Android process. The Android platform has a solution for this called PendingIntent that is basically a way to ask another application to launch an Intent for you.
Open then the CoffeeLoggerWidget.kt file and add this utility function at the end of the companion object:
private fun getPendingIntent(context: Context, value: Int): PendingIntent { //1 val intent = Intent(context, MainActivity::class.java) //2 intent.action = Constants.ADD_COFFEE_INTENT //3 intent.putExtra(Constants.GRAMS_EXTRA, value) //4 return PendingIntent.getActivity(context, value, intent, 0) }
This Kotlin function has the responsibility of creating a PendingIntent for a given coffee:
First you define the Intent to launch as usual using the destination class as argument; in your case it’s the MainActivity class.
The MainActivity can be launched in different ways, and you need something that identifies how much to vary the coffee content. To do this you use an action MainActivity can recognise.
You also need to put into the Intent the quantity to add. Remember, MainActivity doesn’t know what button was pressed on the Widget!
Create the PendingIntent and return it to the caller of the function
Since you now have the action prepared, attach them to the buttons. Go to the updateAppWidget() function in the companion object and add the following code just before its last instruction appWidgetManager.updateAppWidget(...):
views.setOnClickPendingIntent(R.id.ristretto_button, getPendingIntent(context, CoffeeTypes.RISTRETTO.grams)) views.setOnClickPendingIntent(R.id.espresso_button, getPendingIntent(context, CoffeeTypes.ESPRESSO.grams)) views.setOnClickPendingIntent(R.id.long_button, getPendingIntent(context, CoffeeTypes.LONG.grams))
It is worth noting that updateAppWidget() is a convenience method the Android Studio wizard created in order to encapsulate the update logic for a given Widget. Looking at the same Kotlin class, you see that it’s invoked in the onUpdate() method for each Widget that requires an update. This call also happens when the Widget appears in the hosting application for the first time.
override fun onUpdate(context: Context, appWidgetManager: AppWidgetManager, appWidgetIds: IntArray) { // There may be multiple widgets active, so update all of them for (appWidgetId in appWidgetIds) { updateAppWidget(context, appWidgetManager, appWidgetId) } }
The RemoteViews class
Now your code should look like this:
internal fun updateAppWidget(context: Context, appWidgetManager: AppWidgetManager, appWidgetId: Int) { //1 val widgetText = context.getString(R.string.appwidget_text) //2 val views = RemoteViews(context.packageName, R.layout.coffee_logger_widget) //3 views.setTextViewText(R.id.appwidget_text, widgetText) //4 views.setOnClickPendingIntent(R.id.ristretto_button, getPendingIntent(context, CoffeeTypes.RISTRETTO.grams)) views.setOnClickPendingIntent(R.id.espresso_button, getPendingIntent(context, CoffeeTypes.ESPRESSO.grams)) views.setOnClickPendingIntent(R.id.long_button, getPendingIntent(context, CoffeeTypes.LONG.grams)) // 5 appWidgetManager.updateAppWidget(appWidgetId, views) }
Here’s what’s going on:
You’re using the Context in order to access a string resource.
An instance of the RemoteViews class is created and given the widget’s layout id. A RemoteViews is basically a mirror image of what you’re going to display in the Widget.
You set the previous string as content of the TextView with id R.id.appwidget_text. It’s very important to note that you can’t access the TextView directly and that only some operations are allowed using the RemoteViews; in this case you’re setting a text.
Using the RemoteViews instance, you register a PendingIntent to use when the user clicks on a each Widget button.
The last instruction binds the specific instance of RemoteViews to the specific instance of the Widget.
Build and run now. You won’t see any difference in the widget, but clicking the Widget buttons will open the app with an updated value of grams. Great job!
Updating the Widget
Widgets should always display the lastest available information, and the update frequency depends on the specific type of data. A Weather Widget doesn’t need a very frequent update, unlike the score of a football match or the price of a specific stock.
You need a way to invoke the previous onUpdate() method at a specific time interval in order to create the new RemoteViews with the new data.
The following drawing gives you an idea of the process:
The problem is how to send the “I need a refresh!” message to the Widget.
Widget configuration
When the update frequency you need is longer than 30 minutes, you don’t need to write any code and you can simply rely on the configuration file coffee_logger_widget_info.xml Android Studio generated in the res\xml folder.
<?xml version="1.0" encoding="utf-8"?> <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android" android:initialKeyguardLayout="@layout/coffee_logger_widget" android:initialLayout="@layout/coffee_logger_widget" android:minHeight="110dp" android:minWidth="180dp" android:previewImage="@drawable/example_appwidget_preview" android:resizeMode="horizontal|vertical" android:updatePeriodMillis="86400000" android:widgetCategory="home_screen"> </appwidget-provider>
The Widget refresh rate is the one defined in the attribute android:updatePeriodMillis. The default value is one day in milliseconds.
Managing updates requests
If you understand how the Android platform manages updates to your Widget, you can replicate the same thing at will. The Android Studio wizard created the CoffeeLoggerWidget class that extends AppWidgetProvider, but we didn’t realize that this was a particular implementation of a BroadcastReceiver.
You can see that by looking at the updates the wizard made to the AndroidManifest.xml file:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.raywenderlich.android.coffeelogs"> - - - - <receiver android:name=".CoffeeLoggerWidget"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/coffee_logger_widget_info" /> </receiver> - - - - </manifest>
Based on the specific Intent‘s action, the AppWidgetProvider dispatches the call to a different methods. Launching an Intent with the android.appwidget.action.APPWIDGET_UPDATE action results in the invocation of the onUpdate() function.
This is exactly what the Android system does at the interval set in the coffee_logger_widget_info.xml configuration file. This means that the updateAppWidget() function is the perfect place for the code to execute on every update.
So add the following line to the beginning of the function:
val coffeeLoggerPersistence = CoffeeLoggerPersistence(context)
and change widgetText to take the value from there:
val widgetText = coffeeLoggerPersistence.loadTitlePref().toString()
Good! Build and run and you’ll see that the widget is periodically updating the “grams” value. Seems like someone had a little too much coffee:
Update the widget manually
If your app needs to update the data in the Widget more frequently, you already have the solution: you can simply periodically launch the same Intent the Android system does. In the case of the Coffee Log application this happens every time the user selects a coffee in the app.
Open MainActivity and add the following code at the end of refreshTodayLabel:
// Send a broadcast so that the Operating system updates the widget // 1 val man = AppWidgetManager.getInstance(this) // 2 val ids = man.getAppWidgetIds( ComponentName(this, CoffeeLoggerWidget::class.java)) // 3 val updateIntent = Intent(AppWidgetManager.ACTION_APPWIDGET_UPDATE) // 4 updateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids) // 5 sendBroadcast(updateIntent)
Since this code has some new elements, let me walk you through it:
Get the AppWidgetManager instance, which is responsible for all the installed Widgets.
Ask for the identifiers of all the instances of your widget (you could add more than one to your homescreen).
Create an Intent with the android.appwidget.action.APPWIDGET_UPDATE action asking for an update.
Add the ids of the widgets you are sending the Intent to as extras of the Intent for the AppWidgetManager.EXTRA_APPWIDGET_IDS key.
Finally, send the broadcast message.
Build and run tha app to check that everytime you add some coffee, the widget also updates.
Communicating via Service
Not all the updates needed for Widgets are a consequence of an action from the user. Typical cases are data from a server through periodic polling and push notification events. In cases like these, the request has to come from a different component, which you usually implement as an Android Service.
Choose File\New\Service\Service and change the name to CoffeeQuotesService.
When you click Finish, Android studio generates a Kotlin file for you for the Service.
In CoffeeQuotesService, replace the current implementation of onBind() with:
return null
Change the return type of onBind to be the nullable IBinder?.
Then add this function, which is the one the Android system invokes at every launch of the service Service:
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { val appWidgetManager = AppWidgetManager.getInstance(this) val allWidgetIds = intent?.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS) //1 if (allWidgetIds != null) { //2 for (appWidgetId in allWidgetIds) { //3 CoffeeLoggerWidget.updateAppWidget(this, appWidgetManager, appWidgetId) } } return super.onStartCommand(intent, flags, startId) }
You’ve seen the first two lines before. The others do the following:
Check that the array of allWidgetIds was in the Intent.
Loop through the allWidgetIds list.
Update each widget.
Now, you need to call this service instead of directly updating the widget. Open CoffeeLoggerWidget and replace the content of onUpdate() with the following in order to start the Service:
val intent = Intent(context.applicationContext, CoffeeQuotesService::class.java) intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds) context.startService(intent)
This creates an Intent, puts the Widget ids in the intent, and starts the Service.
In the companion object, add the following function:
private fun getRandomQuote(context: Context): String { //1 val quotes = context.resources.getStringArray(R.array.coffee_texts) //2 val rand = Math.random() * quotes.size //3 return quotes[rand.toInt()].toString() }
This function generates a random coffee quote:
It takes a quote array from the strings file
It picks a random number
Finally, it returns the string at the random position
After you have the string, update the widget. In updateAppWidget() add this before the last call:
views.setTextViewText(R.id.coffee_quote, getRandomQuote(context))
That’s it. Every time the widget updates, you get a new quote!
Making it personal
People like to personalize the look and functionality of their Home screens, and Widgets are no exception. You have to take into account that a general purpose Widget won’t bring much value to a user. To make it personal you need to let the users set up preferences and configurations.
Earlier, when covering the configuration of a Widget, you learned that it can have a Configuration screen. This is an Activity that is automatically launched when the user adds a Widget on the home screen. Note that the preferences are set up per Widget because users can add more than one instance of a Widget. It’s better to think about saving this preferences with the id of the Widget.
In this project, the configuration screen could contain a coffee amount limit. If the user logs more coffee than the limit, the Widget will turn into a soft but alarming pink.
Creating a preferences screen
The preference screen for a Widget is an Activity. Choose New\Activity\Empty activity from the File menu and edit the fields to be
Activity name: CoffeeLoggerWidgetConfigureActivity
Layout Name: activity_coffee_logger_widget_configure
Make sure the Launcher Activity checkbox is unchecked and the Source Language is Kotlin.
When you click Finish, Android Studio will generate the code for the new Activity and a template for the layout file, along with adding the registration of the Activity in the AndroidManifest.xml file.
Now create the layout for the configuration screen. Open activity_coffee_logger_widget_configure.xml and add the following:
<?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:orientation="vertical" android:padding="16dp"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="8dp" android:labelFor="@+id/appwidget_text" android:text="@string/coffee_amount_limit" /> <EditText android:id="@id/appwidget_text" android:layout_width="match_parent" android:layout_height="wrap_content" android:inputType="number" /> <Button android:id="@+id/add_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="8dp" android:text="@string/save_configuration" /> </LinearLayout>
The layout is nothing complicated: a TextView that represents a label to the EditText, and a Button for the user to save the preferences.
Know your limits
Open CoffeeLoggerWidgetConfigureActivity and add these fields above onCreate() (developers usually put fields at the beginning of the class):
private lateinit var appWidgetText: EditText private var appWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID private val coffeeLoggerPersistence = CoffeeLoggerPersistence(this)
You will need to use these fields later to save the limit value for each widget.
In onCreate(), add the following code at the end:
//1 appWidgetText = findViewById(R.id.appwidget_text) //2 val extras = intent.extras //3 appWidgetId = extras.getInt( AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID) //4 setResult(Activity.RESULT_CANCELED)
Here’s what the code does:
Find the EditText in the layout.
Get the extras from the Intent that launched the Activity.
Extract the appWidgetId of the widget.
Make sure that if the user doesn’t press the “Save Configuration” button, the widget is not added.
Finally, you need to save the configuration when the user presses the “Save Configuration” button. Below onCreate(), declare the following OnClickListener implementation:
private var onClickListener: View.OnClickListener = View.OnClickListener { // 1 val widgetText = appWidgetText.text.toString() // 2 coffeeLoggerPersistence.saveLimitPref(widgetText.toInt(), appWidgetId) // 3 val resultValue = Intent() resultValue.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId) // 4 setResult(RESULT_OK, resultValue) // 5 finish() }
Here you:
Get the text input – the coffee limit.
Save the limit to local storage (using the Widget id).
Create a new Intent to return to the caller of the Activity and add the id of the Widget you’re configuring.
Tell the operating system that the configuration is OK. Do this by passing an Intent that contains the widget id.
Close the configuration screen
Attach this listener to the button by adding the following line below setContentView() in onCreate():
findViewById<View>(R.id.add_button).setOnClickListener(onClickListener)
This is a chained instruction that finds the Button object and sets its listener.
Linking preferences to the widget
It is a good idea to refresh the widget after the user saves the preferences. That’s because the limit might already be exceeded at the moment of adding a new widget. For this reason, write another method at the end of CoffeeLoggerWidgetConfigureActivity to trigger the refresh:
private fun updateWidget() { val appWidgetManager = AppWidgetManager.getInstance(this) CoffeeLoggerWidget.updateAppWidget(this, appWidgetManager, appWidgetId) }
The function retrieves the AppWidgetManager and triggers an update to the corresponding widget. Call this function in the OnClickListener after saving the coffee limit to coffeeLoggerPersistence. It should be before creating the Intent:
updateWidget()
To launch the configuration screen whenever the user adds a widget, you need to add it to the widget configuration file. With this in mind, open coffee_logger_widget_info.xml and add the following attribute to appwidget-provider:
android:configure="com.raywenderlich.android.coffeelogs.CoffeeLoggerWidgetConfigureActivity"
Build and run, then go to the home screen. Long press the widget and drag it to the “Remove” area. Add another widget as before and check that the configuration screen appears. It should look like this:
Enter a value in the field like 10 and press “Save configuration” to add the widget.
To make the widget react to the limit, add this in CoffeeLoggerWidget inside updateAppWidget*(, before the last line:
// 1 val limit = coffeeLoggerPersistence.getLimitPref(appWidgetId) // 2 val background = if (limit <= widgetText.toInt()) R.drawable.background_overlimit else R.drawable.background // 3 views.setInt(R.id.widget_layout, "setBackgroundResource", background)
Step by step:
First, get the limit saved by the user for that widget.
Decide if the user exceeds the limit of coffee and establish one of the two possible backgrounds: pink or blue.
Set the background to the widget's root element.
Finally, build and run. After the app opens log more coffees than the limit you set. Let's say your limit was 10: log three Espresso and go back to the home screen. As a result, your widget is now pink:
Best practices
Some final advice before you start adventuring into the world of Widgets:
Design the smallest Widget size you can. Don't take up screen real-estate if you don't need it. Be aware that the user might resize it into a bigger area.
Don't refresh the Widget too often because it will drain the battery. On the other hand, don't refresh it too rarely because it won't be useful on the screen.
Make sure you read the official guidelines for Widget design and follow the recommendations. Revisit them from time to time because things change and things get added.
Think of Widgets as a shortcut window into your app. Provide the most important information and actions in it.
Where to go from here
Congratulations, you've finished your App Widget! Download the final project using the button at the top or bottom of the tutorial.
You learned how to develop an App widget to track your coffee intake. In summary, some of your new skills are:
Create a widget layout
Link a configuration screen
Communicate via a Service
... and tie them all together. This is impressive!
You can learn more about App Widgets by checking out the official docs.
For a better understanding of Intents, have a look at the Android Intents Tutorial.
You can create a better user interface for your apps and widgets with more Material Design. Get a little knowledge boost from Android: An Introduction to Material Design.
If you have any questions or comments about Android App Widgets, please join the forum discussion below!
The post Android App Widgets Tutorial appeared first on Ray Wenderlich.
Android App Widgets Tutorial published first on https://medium.com/@koresol
0 notes
buzzmycode-blog · 9 years ago
Text
How to create Custom Grid View in Android
How to create Custom Grid View in Android
Yesterday I have written a post on Simple Grid View with single text view only. Now I am writing for the Custom Grid View having Image and Text View in each of its grid.
Adapter loads the Grid View with the data from data sources. For grid view with a single text we used ArrayAdapter of String type. For a Grid View with more than one widgets you need to create a Custom Adapter that is a user…
View On WordPress
0 notes
mobilenamic · 6 years ago
Text
Release 2.18.3: QML JSON ListModel and Todo List App
V-Play 2.18.3 adds the JsonListModel as a performant and feature-rich QML ListModel enhancement for Qt. It helps you transform your JSON data to a model and enables you to detect changes to individual items in your model. You can then only update the changed items in your UI instead of updating the full list. This update also adds several improvements and fixes.
Improved Data Manipulation and ListView Performance
You can now use JsonListModel to transform your JSON data into a QML ListModel for usage with e.g. an AppListView.
The JsonListModel type implements the full QML ListModel API and fires individual events for all changes in the data. The list view can thus only update relevant entries or apply transition animations. This is super useful, as you can e.g. fetch new data and simply replace the old JSON. The JsonListModel will detect all changes, and the ListView updates its items accordingly – without a full redraw.
You thus get much better performance and scrolling stays smooth when the list is updated:
The JsonListModel is backed by a performant QSyncable model in Qt C++ and exposed to QML for easy usage. With the JsonListModel you can:
Fetch JSON data from REST APIs with QML and JavaScript.
Pass the data to your C++ list model, which synchronizes the JSON data and prepares it for usage in your view.
Show the model data with a list view in QML, which only renders list items that have changed.
With the JsonListModel you do not require to implement a custom model in C++ anymore. The JsonListModel itself is your C++ model, which is fully usable from QML and can work with JSON list items of any format.
Apart from list views, the model also supports the GridView and Repeater types to display model data.
The following example shows how to use JsonListModel together with AppListView. When adding a new item to the JSON, the JsonListModel detects the change. The AppListView can thus use a transition animation when adding the entry. It is not required to fully redraw the list and existing items in the view are not affected.
import VPlayApps 1.0 import QtQuick 2.0 App { NavigationStack { Page { id: page title: "JSONListModel" // property with json data property var jsonData: [ { "id": 1, "title": "Entry 1" }, { "id": 2, "title": "Entry 2" }, { "id": 3, "title": "Entry 3" } ] // list model for json data JsonListModel { id: jsonModel source: page.jsonData keyField: "id" } // list view AppListView { anchors.fill: parent model: jsonModel delegate: SimpleRow { text: model.title } // transition animation for adding items add: Transition { NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 1000 easing.type: Easing.OutQuad; } } } // Button to add a new entry AppButton { anchors.horizontalCenter: parent.horizontalCenter anchors.bottom: parent.bottom text: "Add Entry" onClicked: { var newItem = { "id": jsonModel.count + 1, "title": "Entry "+(jsonModel.count + 1) } page.jsonData.push(newItem) // manually emit signal that jsonData property changed // JsonListModel thus synchronizes the list with the new jsonData page.jsonDataChanged() } } } // Page } }
  Please see the documentation of JsonListModel for more information and examples. The JsonListModel is now also used for all JSON models of the V-Play SDK app demos.
New App Example with Core App Components
You can find a new app demo which incorporates all core elements that you need in a basic app. It is based on the principles of the Separation of Model, View and Logic Code guide. The demo includes login, app navigation, controls, REST API access, offline caching and also uses the JsonListModel.
You can find the Basic Demo App along with other app demos in the V-Play SDK and as a project wizard in Qt Creator. The basic app is the best starting point for new applications and combines many features that used to be part of individual wizards before. It is also available for you on GitHub.
Todo List App with Sort and Filter Options
To further demonstrate the power of JsonListModel, we also prepared an advanced Todo List Demo App.
It uses list transition animations and shows how to integrate PullToRefreshHandler, VisibilityRefreshHandler or SortFilterProxyModel. The demo supports fetching of todos, creation and storing of drafts, offline caching, paging, sorting and filtering.
Use Custom Page Transitions
You can now configure the used NavigationStack page transition with NavigationStack::transitionDelegate property. By default, the NavigationStack uses NavigationStack::transitionDelegateiOS on iOS and NavigationStack::transitionDelegateAndroid on Android.
You can also specify a custom transition using StackViewDelegate.
More Features, Improvements and Fixes
Here is a compressed list of further improvements with this update:
The NavigationStack transition for Android now better matches the default Android platform transition.
VisibilityRefreshHandler now also refreshes if it gets visible after the content height of the list changes (for example when filtering).
Fix animation of AppActivityIndicator and ActivityIndicatorBarItem to loop infinitely.
The AppTextEdit::cursorInView feature does no longer require the AppTextEdit to use id: textEdit.
For a list of additional fixes, please check out the changelog.
How to Update V-Play
Test out these new features by following these steps:
Open the V-Play SDK Maintenance Tool in your V-Play SDK directory.
Choose “Update components” and finish the update process to get this release as described in the V-Play Update Guide.
If you haven’t installed V-Play yet, you can do so now with the latest installer from here. Now you can explore all of the new features included in this release!
For a full list of improvements and fixes to V-Play in this update, please check out the change log!
      More Posts Like This
youtube
  Machine Learning: Add Image Classification for iOS and Android with Qt and TensorFlow
Qt AR: Why and How to Add Augmented Reality to Your Mobile App
Release 2.18.2: Guide for MVC, MVVM, Flux with QML
Release 2.18.1: Use JavaScript Promises with Qt, Material Cards and an Improved API to Connect to REST Services
Release 2.18.0: Update to Qt 5.11.1 with QML Compiler and Massive Performance Improvements
How to Make Cross-Platform Mobile Apps with Qt – V-Play Apps
The post Release 2.18.3: QML JSON ListModel and Todo List App appeared first on V-Play Engine.
Release 2.18.3: QML JSON ListModel and Todo List App published first on https://medium.com/@TheTruthSpy
0 notes
iyarpage · 7 years ago
Text
New Course: Beginning RecyclerView
It’s day 5 of the Android Avalanche: an event where we’ll be releasing new Android and Kotlin books, courses, and screencasts every day!
Today, we are releasing a brand new course: Beginning RecyclerView.
In this 37-video course by Joe Howard, you’ll learn how to use Android’s RecyclerView to efficiently display a list of items. Through a series of hands-on exercises and challenges, you’ll set up a basic RecyclerView, learn to use different layout managers, add animation, and more. Take a look at what’s inside:
Part 1: RecyclerView Basics
In part one, learn to bind model data to RecyclerViews.
Introduction: Find out what’s covered in our RecyclerView video tutorial series, from basic setup to animations and common interactions.
The Starter App: Download the starter app and build it in Android Studio, and take a peek at the included starter layout files.
A Basic RecyclerView: See how to setup a basic RecyclerView, along with the corresponding LayoutManager, Adapter, and ViewHolder.
Binding the Views: Learn how to connect the model data displayed in the RecyclerView to the corresponding objects in the view layer.
Challenge: RecyclerView: Practice what you’ve learned so far to add more data into the rows of the RecyclerView, and then see a solution.
Responding to Clicks: See how to respond to clicks on the rows of the RecyclerView, and take the user to a detail screen for the corresponding row item.
Challenge: Favorites: Take all the basics of RecyclerView that you’ve learned so far to build a Favorites screen for the sample app.
Conclusion: Let’s review what you’ve covered in this first part on RecyclerView basics, and discuss what’s next.
Part 2: Layout Managers
In part two, learn to use the various RecyclerView layout managers: LinearLayoutManager, GridLayoutManager, and StaggeredGridLayoutManager.
Introduction: Let’s take a quick look at the layout managers that you’ll learn about in this part, and describe the capabilities of each.
LinearLayoutManager: Learn more detail about LinearLayoutManager by creating a horizontal RecyclerView on the detail screen.
Nested RecyclerViews: Create a nested RecyclerView, learn about LinearSnapHelper, and improve performance with a RecycledViewPool.
GridLayoutManager: See how to create a grid of items with RecyclerView using GridLayoutManager, replacing the need for GridView.
Custom Span Size: See how to use varying span sizes within a RecyclerView managed by GridLayoutManager using a span size lookup.
Challenge: Span Size: Practice setting custom span sizes on a RecyclerView managed by GridLayoutManager, then see a solution.
StaggeredGridLayoutManager: Learn how to handle the case of grid items having different natural sizes using StaggeredGridLayoutManager.
Switching Between Span Sizes: Add a menu to allow switching between span sizes for a RecyclerView managed by a StaggeredGridLayoutManager.
Challenge: Layout Managers: Practice what you’ve learned about layout manager to create a grid of items on the detail screen, then see a solution.
Conclusion: Let’s review what you learned about the various RecyclerView layout managers, and discuss what’s next.
Part 3: Decorating and Animating
In part three, learn how to use item decorations for spacing and separators and add animation.
Introduction: Learn about the objectives of this part, which are to become familiar with the capabilities of ItemDecoration and to see how to animate items in a RecyclerView.
ItemDecoration: Offsets: See how to use ItemDecoration with a RecyclerView to control the spacing around the items utilizing offsets.
ItemDecoration: Drawing: See how to use ItemDecoration with a RecyclerView to create separators between the elements in a list.
Challenge: ItemDecoration: Practice using ItemDecoration with a RecyclerView to create separators between the items in a grid, then see a solution.
Item Animations: Discover how to use animations to add dynamic effects to the presentation of the items in a RecyclerView.
Challenge: Item Animations: Practice using animations to add dynamic effects to the presentation of the items in a RecyclerView.
Conclusion: Let’s review what you learned about using ItemDecoration and animations with a RecyclerView, and discuss what’s next.
Part 4: Section Headers and View Types
In part four, learn about the different view types in a RecyclerView .
Introduction: Learn about the objectives of this part, which are to become familiar with using different view types in a RecyclerView.
Custom Section Headers: See how to sort the items displayed in a RecyclerView into groups and then add section headers to the groups.
Multiple View Types: Use view types to customize the display of items displayed in a RecyclerView, based on the type of the item.
Challenge: View Types: Practice using view types to customize the display of certain items in a RecyclerView, then see a solution.
Conclusion: Let’s review what you learned about using view types for items displayed in a RecyclerView, and discuss what’s next.
Part 5: Common Interactions
In the final part, learn how to handle different interactions with a RecyclerView.
Introduction: Learn about the objectives of this part, which are to become familiar with common interactions with a RecyclerView, such as drag and drop and swipe-to-delete.
ItemTouchHelper: Discover the capabilities and use cases for combining the ItemTouchHelper class with a RecyclerView.
Rearranging Rows: See how to use ItemTouchHelper to create a basic capability to rearrange the items in a RecyclerView.
Handles and Selection: See how to setup drag handles and item selection highlighting using ItemTouchHelper with a RecyclerView.
Challenge: ItemTouchHelper: Practice using ItemTouchHelper to allow for drag and drop rearrangement of the items displayed in a grid via a RecyclerView
Swipe to Delete: See how to use ItemTouchHelper to add a basic swipe-to-delete capability for the items in a RecyclerView.
Conclusion: In this final episode, we’ll summarize the course, and then see an overview of RecyclerView topics that were not covered.
The Android Avalanche Bundle
If you like this course, from now until March 30th you can get it along with the rest of our new Android and Kotlin books, courses, and screencasts — at a big discount!
Our new Android Avalanche Bundle includes:
Android Apprentice ($54.99 value): Gives you access to our new Android Apprentice book, which teaches you how to build four complete Android apps from scratch. PDF/ePub format.
Kotlin Apprentice ($54.99 value): Gives you access to our new Kotlin Apprentice book, which gives you a deep dive into the Kotlin programming language itself. PDF/ePub format.
A raywenderlich.com subscription ($19.99 value): Gives you access to all 8 of our new Android video courses, our 2 new Android screencasts, and access to any new courses and screencasts we release in the future.
The bundle price of $99.99 includes the first month of your subscription, which will continue at $19.99/month thereafter. You can cancel at any time and keep the books. This bundle gives you more than 20% off everything in the Android Avalanche!
The Android Avalanche bundle is only available for the next two weeks, so be sure to order your copy while you can.
Already a subscriber? As a subscriber, you already have access to this new course as part of your subscription. You can also enjoy a $20 discount on the bundle that will get you both books added to your collection. It’s our way of thanking you for supporting what we do here at raywenderlich.com.
Where To Go From Here?
If you want to learn Android and Kotlin development — or level up your existing skills – there’s no better way to learn than these new books, courses, and screencasts.
And this is only the beginning! We’re committed to creating more new books, courses, and screencasts on Android development, with the goal of covering Android and Kotlin in the same way that we’ve covered iOS and Swift over the years.
We truly appreciate your support in making this possible. We’re excited about this new chapter at raywenderlich.com. So order your copy of the Android Avalanche Bundle today before the deal is over!
The post New Course: Beginning RecyclerView appeared first on Ray Wenderlich.
New Course: Beginning RecyclerView published first on https://medium.com/@koresol
0 notes
iyarpage · 8 years ago
Text
Android RecyclerView Tutorial with Kotlin
Update note: This tutorial has been updated to Kotlin, Android 26 (Oreo) and Android Studio 3.0 by Rod Biresch. The original tutorial was written by Darryl Bayliss.
Recycling is one of those things that is good for the planet, and it’s a common sense way to make sure we don’t find ourselves buried in our own rubbish or without sufficient resources in the future.
A few Android engineers thought about the benefits of recycling and realized that an OS can also run more efficiently if it recycles. The result of this inspiration was millions of eco-Warriors and recycling enthusiasts rejoicing when the RecyclerView widget was introduced into Android Lollipop — or something like that. :]
There was even more celebration when Google announced a support library to make this clean, green, recycling machine backwards compatible all the way to Android Eclair (2.2), which was released back in 2010!
In this tutorial, you’re going to experience the power of RecyclerView in action and learn:
The purpose of a RecyclerView
The components that make up a RecyclerView
How to change the layout of a RecyclerView
How to add some nice animations to your RecyclerView
You’re also going to blast off into outer space with the sample app Galacticon. You’ll use it to build out a feed of daily astronomy photos from a public NASA API.
Prerequisites: You should have a working knowledge of developing for Android with Kotlin before working through this tutorial. If you need a refresher, take a look at some of our introductory tutorials! Also, you will need Android Studio 3.0 or greater.
Heading to Cape Canaveral: Getting Started
Download the starter project and open it up in Android Studio. There isn’t much to it yet, nor is the almighty RecyclerView anywhere to be seen.
Click the Run app button at the top and you’ll see something that resembles outer space in all the wrong ways:
It’s empty, but that’s ok. You wouldn’t learn much if all the work was done for you! Before you can add that amazing astrophotography from NASA, you’ll need to do some set up work.
Obtaining The (API) Keys to the Shuttle
You’ll use the Astronomy Picture of the Day API, one of the most popular web services provided by NASA. To ensure it doesn’t fall victim to unsolicited traffic, the service requires you to have an API key to use it in an application.
Fortunately, getting a key is as simple as putting your name and email address into api.nasa.gov and copying the API key that appears on the screen or the email sent to you.
Once you’ve acquired your API key, copy it and open the strings.xml file in your project. Paste your API key into the api_key string resource, replacing INSERT API KEY HERE:
Space Oddity: Learning About RecyclerView
You’re about to blast off into outer space to explore the vastness of RecyclerViews, but no competent commander heads into the unknown without preparation. You have questions, and you need answers before you go any further. Consider this section as your mission brief.
A RecyclerView can be thought of as a combination of a ListView and a GridView. However, there are extra features that separate your code into maintainable components even as they enforce memory-efficient design patterns.
But how could it be better than the tried and tested ListView and GridView you’re used to? Could it be some kind of alien technology? The answers, as always, are in the details.
Why You Need RecyclerView
Imagine you’re creating a ListView where the custom items you want to show are quite complicated. You take time to lovingly create a row layout for these items, and then use that layout inside your adapter.
Inside your getView() method, you inflate your new item layout. You then reference every view within by using the unique ids you provided in your XML to customize and add some view logic. Once finished, you pass that view to the ListView, ready to be drawn on the screen. All is well…or is it?
The truth is that ListViews and GridViews only do half the job of achieving true memory efficiency. They recycle the item layout, but don’t keep references to the layout children, forcing you to call findViewById() for every child of your item layout every time you call getView().
All this calling around can become very processor-intensive, especially for complicated layouts. Furthermore, the situation can cause your ListView scrolling to become jerky or non-responsive as it frantically tries to grab references to the views you need.
Android engineers initially provided a solution to this problem on the Android Developers site with smooth scrolling, via the power of the View Holder pattern.
When you use this pattern, you create a class that becomes an in-memory reference to all the views needed to fill your layout. The benefit is you set the references once and reuse them, effectively working around the performance hit that comes with repeatedly calling findViewById().
The problem is that it’s an optional pattern for a ListView or GridView. If you’re unaware of this detail, then you may wonder why your precious ListViews and GridViews are so slow.
First Contact: RecyclerView and Layouts
The arrival of the RecyclerView changed everything. It still uses an Adapter to act as a data source; however, you have to create ViewHolders to keep references in memory.
When you need a new view, it either creates a new ViewHolder object to inflate the layout and hold those references, or it recycles one from the existing stack.
Now you know why it’s called a RecyclerView!
Another perk of using RecyclerViews is that they come with default animations that you don’t have to create or add yourself — they just work.
Thanks to the requirement for a ViewHolder, the RecyclerView knows exactly which animation to apply to which item. Best of all, it just does it as required. You can even create your own animations and apply them as needed.
The last and most interesting component of a RecyclerView is its LayoutManager. This object positions the RecyclerView’s items and tells it when to recycle items that have transitioned off-screen.
Layout Managers come in three default flavors:
LinearLayoutManager positions your items to look like a standard ListView
GridLayoutManager positions your items in a grid format similar to a GridView
StaggeredGridLayoutManager positions your items in a staggered grid format.
You can also create your own LayoutManagers to use with a RecyclerView if you want an extra bit of customization.
Hopefully that answers all your questions, commander. Now, onto the mission!
Preparing for Launch: Creating the RecyclerView
To create the RecyclerView, you’ll break the work into four parts:
Declare the RecyclerView in an activity layout and reference it in your activity Kotlin file.
Create a custom item XML layout for your RecyclerView to use for its items.
Create the view holder for your view items, hook up the data source of the RecyclerView and handle the view logic by creating a RecyclerView Adapter.
Attach the adapter to the RecyclerView.
Step one should be familiar. Open up the activity_main.xml layout file, and add the following as a child of the LinearLayout:
<android.support.v7.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" android:scrollbars="vertical"/>
Here you’re setting up the layout and telling the RecyclerView to match its parent.
Note: You’re using the v7 support library for backwards compatibility with older devices. The starter project already adds the RecyclerView Support Library as a dependency in your app’s build.gradle file. If you want more information on how to do it yourself, check out the Android developer website.
Open MainActivity.kt and declare the following property at the top of the class:
private lateinit var linearLayoutManager: LinearLayoutManager
In onCreate(), add the following lines after setContentView:
linearLayoutManager = LinearLayoutManager(this) recyclerView.layoutManager = linearLayoutManager
Android Studio should prompt you to import kotlinx.android.synthetic.main.activity_main.* for recyclerView. You may wonder how do we have a reference to recyclerView without first finding the view, i.e. findViewById()? The project has been configured to use Kotlin Android Extensions plugin. This plugin enables the ability to import views in a layout as “synthetic” properties.
import kotlinx.android.synthetic.main.activity_main.*
The recyclerView is now an extension property for Activity, and it has the same type as declared in activity_main.xml. The plugin removes a lot of boilerplate code and reduces the risk of potential bugs.
Phase one of ignition is complete! You’ve declared and allocated memory for two parts of the puzzle that RecyclerViews need to work: The RecyclerView and its Layout Manager.
Ignition Phase 2: Laying out the RecyclerView Items
Phase two of ignition involves creating a custom layout for the item you want your RecyclerView to use. It works exactly the same as it does when you create a custom layout for a ListView or Gridview.
Head over to your layout folder and create a new layout with the name recyclerview_item_row and set the root element as a LinearLayout. In your new layout, add the following XML elements as children of your LinearLayout:
<ImageView android:id="@+id/itemImage" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="8dp" android:layout_weight="3" android:adjustViewBounds="true" /> <TextView android:id="@+id/itemDate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="top|start" android:layout_marginTop="8dp" android:layout_weight="1" tools:text="Some date" /> <TextView android:id="@+id/itemDescription" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center|start" android:layout_weight="1" android:ellipsize="end" android:maxLines="5" />
No rocket science here: You declared a few views as children of your layout, and can now use them in your adapter.
Adapters: Rocket Fuel for Your RecyclerView
Right-click on the com.raywenderlich.galacticon folder, select New \ Kotlin File/Class, and name it RecyclerAdapter and select Class for Kind. At the top of the file below the package declaration, import the support library’s version of RecyclerView:
import android.support.v7.widget.RecyclerView
Make the class extend RecyclerView.Adapter so it looks like the following:
class RecyclerAdapter : RecyclerView.Adapter<RecyclerAdapter.PhotoHolder>() { }
Android Studio will detect that you’re extending a class that has required methods and will underline your class declaration with a red squiggle.
To resolve this, click on the line of code to insert your cursor, then press Option + Return (or Alt + Enter on a PC) to bring up a context menu. Select Implement Methods:
Confirm you want to implement the suggested methods by clicking OK:
These methods are the driving force behind your RecyclerView adapter. Note how there is still a compiler error for the moment– this is because your adapter and the required methods are actually defined using your ViewHolder class, PhotoHolder, which doesn’t exist just yet. You’ll get to define your ViewHolder and see what each required method does shortly, so just hang tight, Commander!
As with every adapter, you need to provide the corresponding view a means of populating items and deciding how many items there should be.
Item clicks were previously managed by a ListView’s or GridView’s onItemClickListener. A RecyclerView doesn’t provide methods like this because it has one focus: ensuring the items inside are positioned properly and managed efficiently.
The job of listening for actions is now the responsibility of the RecyclerView item and its children. This may seem like more overhead, but in return, you get fine-grained control over how your item’s children can act.
At the top of your RecyclerAdapter class, add a variable photos to hold your photos in the primary constructor:
class RecyclerAdapter(private val photos: ArrayList<Photo>) RecyclerView.Adapter<RecyclerAdapter.PhotoHolder>() {
Nice job, Commander! Your adapter now knows where to look for data. Soon you’ll have an ArrayList of photos filled with the finest astrophotography!
Next, you’ll populate the stubbed methods that were added by Android Studio.
The first method, getItemCount(), is pretty simple and should be familiar from your work with ListViews or GridViews.
The adapter will work out how many items to display. In this case, you want the adapter to show every photo you’ve downloaded from NASA’s API. To do that, add update getItemCount() to the following:
override fun getItemCount() = photos.size
Next, you’re going to exploit the ViewHolder pattern to make an object that holds all your view references.
Velcro For All: Keeping Hold Of Your Views
To create a PhotoHolder for your view references, you’ll create a nested class in your adapter. You’ll add it here rather than in a separate class because its behavior is tightly coupled with the adapter. First, import synthetic properties for the recycler view item so you can reference the view properties:
import kotlinx.android.synthetic.main.recyclerview_item_row.view.*
Add the following code at the bottom of the RecyclerAdapter class:
//1 class PhotoHolder(v: View) : RecyclerView.ViewHolder(v), View.OnClickListener { //2 private var view: View = v private var photo: Photo? = null //3 init { v.setOnClickListener(this) } //4 override fun onClick(v: View) { Log.d("RecyclerView", "CLICK!") } companion object { //5 private val PHOTO_KEY = "PHOTO" } }
So what did you do here?
Made the class extend RecyclerView.ViewHolder, allowing it to be used as a ViewHolder for the adapter.
Added a reference to the lifecycle of the object to allow the ViewHolder to hang on to your View, so it can access the ImageView and TextView as an extension property. Kotlin Android Extensions plugin adds in hidden caching functions and fields so that views are not constantly queried.
Initialized the View.OnClickListener.
Implemented the required method for View.OnClickListener since ViewHolders are responsible for their own event handling.
Added a key for easier reference to the particular item being used to launch your RecyclerView.
You should still have a compiler errors with onBindViewHolder and onCreateViewHolder methods. Change the holder: ? argument on onBindViewHolder to have a type RecyclerAdapter.PhotoHolder.
override fun onBindViewHolder(holder: RecyclerAdapter.PhotoHolder, position: Int) { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. }
Then add a RecyclerAdapter.PhotoHolder return type to the onCreateViewHolder method and remove the safe call operator (i.e. ?) of the parent argument type.
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerAdapter.PhotoHolder { TODO("not implemented") //To change body of created functions use File | Settings | File Templates. }
You should now be able to build and run the app again, but it’ll look about the same because you haven’t told the RecyclerView how to associate the PhotoHolder with a view.
Assembling The Pieces
Sometimes there are no ViewHolders available. In this scenario, RecylerView will ask onCreateViewHolder() from RecyclerAdapter to make a new one. You’ll use the item layout — PhotoHolder — to create a view for the ViewHolder.
The inflate code could simply be added to onCreateViewHolder(). However, this is a nice opportunity to show a really cool Kotlin feature called Extensions.
First, add a new Kotlin file named Extensions.kt to the project and then add the following new extension function to the new file:
fun ViewGroup.inflate(@LayoutRes layoutRes: Int, attachToRoot: Boolean = false): View { return LayoutInflater.from(context).inflate(layoutRes, this, attachToRoot) }
Replace the TODO("not implemented") line between the curly braces in onCreateViewHolder() with the following:
val inflatedView = parent.inflate(R.layout.recyclerview_item_row, false) return PhotoHolder(inflatedView)
Here you inflate the view from its layout and pass it in to a PhotoHolder. The parent.inflate(R.layout.recyclerview_item_row, false) method will execute the new ViewGroup.inflate(...) extension function to inflate the layout.
And with that, you’ve made it so the object holds onto those references while it’s recycled, but there are still more pieces to put together before you can launch your rocketship.
Start a new activity by replacing the log in ViewHolder’s onClick with this code:
val context = itemView.context val showPhotoIntent = Intent(context, PhotoActivity::class.java) showPhotoIntent.putExtra(PHOTO_KEY, photo) context.startActivity(showPhotoIntent)
This grabs the current context of your item view and creates an intent to show a new activity on the screen, passing the photo object you want to show. Passing the context object into the intent allows the app to know what activity it is leaving.
Next thing to do is to add this method inside PhotoHolder:
fun bindPhoto(photo: Photo) { this.photo = photo Picasso.with(view.context).load(photo.url).into(view.itemImage) view.itemDate.text = photo.humanDate view.itemDescription.text = photo.explanation }
This binds the photo to the PhotoHolder, giving your item the data it needs to work out what it should show.
It also adds the suggested Picasso import, which is a library that makes it significantly simpler to get images from a given URL.
The last piece of the PhotoHolder assembly will tell it how to show the right photo at the right moment. It’s the RecyclerAdapter’s onBindViewHolder, and it lets you know a new item will be available on screen and the holder needs some data.
Add the following code inside the onBindViewHolder() method:
val itemPhoto = photos[position] holder.bindPhoto(itemPhoto)
Here you’re passing in a copy of your ViewHolder and the position where the item will show in your RecyclerView, and calling bindPhoto(...).
And that’s all you needed to do here on the assembly — just use the position where your ViewHolder will appear to grab the photo out of your list, and then pass it to your ViewHolder.
Step three of your ignition check protocol is complete!
Countdown And Liftoff: Hooking up the Adapter And RecyclerView
This is the moment you’ve been waiting for, the final stage before blast off! All you need to do is hook your adapter up to your RecyclerView and make sure it retrieves photos when it’s created so you can explore space — in pictures.
Open MainActivity.kt, and add this property at the top:
private lateinit var adapter: RecyclerAdapter
Next, underneath the assignment of recyclerView.layoutManager, add the following:
adapter = RecyclerAdapter(photosList) recyclerView.adapter = adapter
Here you’re creating the adapter, passing in the constructors it needs and setting it as the adapter for your RecyclerView.
Although the adapter is connected, there’s one more thing to do to make sure you don’t have an empty screen.
In onStart(), underneath the call to super, add this code:
if (photosList.size == 0) { requestPhoto() }
This adds a check to see if your list is empty, and if yes, it requests a photo.
Next, in receivedNewPhoto(), update the method so it looks like the following:
override fun receivedNewPhoto(newPhoto: Photo) { runOnUiThread { photosList.add(newPhoto) adapter.notifyItemInserted(photosList.size) } }
Here you are informing the recycler adapter that an item was added after the list of photos was updated.
Now you’re ready to commence the ignition sequence, er…I mean run the app.
Run the app, load up the emulator and before long, Galacticon should look something like this:
That’s not all. Tap on the photo, and you should be greeted with a new activity that brings that item into focus:
But that’s still not all! Try rotating your device or emulator (function + control + F11/F12) and you’ll see the image in full screen glory!
Depending on the size of the image and your device screen it may look a little distorted, but don’t worry about that.
Congratulations! You have a working RecyclerView and can take your journey amongst the stars.
Taking A Spacewalk: Adding Scrolling support
If you head back to MainActivity on your device and try to scroll down, you’ll notice something is amiss — your RecyclerView isn’t retrieving any new photos.
Your RecyclerView is doing exactly as it’s told by showing the contents of photosList. The problem is that the app will only retrieve one photo when you load the app. It has no idea when or how to grab more photos.
So next, you’ll retrieve the number of the photos and the last visible photo index while scrolling. Then you’ll check to see if the last photo is visible and if there are no photos already on request. If these are both true, then your app goes and downloads more pretty photos!
This patch will require a spacewalk, so break out your spacesuit and get ready for a zero gravity experience.
In MainActivity.kt, add this property with custom accessor below to MainActivity:
private val lastVisibleItemPosition: Int get() = linearLayoutManager.findLastVisibleItemPosition()
This uses your RecyclerView’s LinearLayoutManager to get the index of the last visible item on the screen.
Next, you add a method that inserts an onScrollListener to your RecyclerView, so it can get a callback when the user scrolls:
private fun setRecyclerViewScrollListener() { recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() { override fun onScrollStateChanged(recyclerView: RecyclerView?, newState: Int) { super.onScrollStateChanged(recyclerView, newState) val totalItemCount = recyclerView!!.layoutManager.itemCount if (!imageRequester.isLoadingData && totalItemCount == lastVisibleItemPosition + 1) { requestPhoto() } } }) }
This function gives the RecyclerView a scroll listener that is triggered by scrolling. During scrolling, the listener retrieves the count of the items in its LayoutManager and calculates the last visible photo index. Once done, it compares these numbers (incrementing the index by 1 because the index begins at 0 while the count begins at 1). If they match and there are no photos already on request, then you request a new photo.
Finally, hook everything to the RecyclerView by calling this method from onCreate, just beneath where you set your RecyclerView Adapter:
setRecyclerViewScrollListener()
Hop back in the ship (build and run the app again). Scroll down and you should see quite an improvement!
Excellent work, your RecyclerView now updates to show the latest photo requested by your app. The great thing is that receivedNewPhoto() handles most of the work because you told it to notify your adapter about new items.
That earns an intergalactic thumbs up for upcycling code!
Layout Changes
Now that your RecyclerView is up and running, it’s time to trick out your spaceship.
Wouldn’t it be cool if your RecyclerView could change its layout? Good news: RecyclerView’s item positioning is separated into a layout manager.
Add a property for a GridLayoutManager to the top of MainActivity.kt:
private lateinit var gridLayoutManager: GridLayoutManager
Note that GridLayoutManager is a built-in layout manager, but it could just as easily be custom.
In onCreate(), initialize the LayoutManager below the existing Linear Layout Manager:
gridLayoutManager = GridLayoutManager(this, 2)
Just like you did with the previous LayoutManager, you pass in the context the manager will appear in, but unlike the former, it takes an integer parameter. In this case, you’re setting the number of columns the grid will have.
Add this method to MainActivity:
private fun changeLayoutManager() { if (recyclerView.layoutManager == linearLayoutManager) { //1 recyclerView.layoutManager = gridLayoutManager //2 if (photosList.size == 1) { requestPhoto() } } else { //3 recyclerView.layoutManager = linearLayoutManager } }
This code checks to see what LayoutManager your RecyclerView is using, and then:
If it’s using the LinearLayoutManager, it swaps in the GridLayoutManager
It requests a new photo if your grid layout only has one photo to show
If it’s using the GridLayoutManager, it swaps in the LinearLayoutManager
Next, you need to make some changes to lastVisibleItemPosition to help it handle the new LayoutManager. Make it look like the following:
private val lastVisibleItemPosition: Int get() = if (recyclerView.layoutManager == linearLayoutManager) { linearLayoutManager.findLastVisibleItemPosition() } else { gridLayoutManager.findLastVisibleItemPosition() }
Here you ask the RecyclerView to tell you what its LayoutManager is, then you ask that LayoutManager to tell you the position of the last visible item.
To use the grid layout, make use of the Options menu button that is already available in the app. Add the following code underneath onStart():
override fun onOptionsItemSelected(item: MenuItem): Boolean { if (item.itemId == R.id.action_change_recycler_manager) { changeLayoutManager() return true } return super.onOptionsItemSelected(item) }
This checks the ID of the item tapped in the menu, then works out what to do about it. In this case, there should only be one ID that will match up, effectively telling the app to go away and rearrange the RecyclerView’s LayoutManager.
And just like that, you’re ready to go! Load up the app and tap the button at the top right of the screen, and you’ll begin to see the stars shift:
Star Killer
Sometimes you’ll see things you just don’t like the look of, perhaps a galaxy far, far away that has fallen to the dark side or a planet that is prime for destruction. How could you go about killing it with a swipe?
Luckily, Android engineers have provided a useful class named ItemTouchHelper that gives you easy swipe behavior. Creating and attaching this to a RecyclerView requires just a few lines of code.
In MainActivity.kt, underneath setRecyclerViewScrollListener() add the following method:
private fun setRecyclerViewItemTouchListener() { //1 val itemTouchCallback = object : ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT or ItemTouchHelper.RIGHT) { override fun onMove(recyclerView: RecyclerView, viewHolder: RecyclerView.ViewHolder, viewHolder1: RecyclerView.ViewHolder): Boolean { //2 return false } override fun onSwiped(viewHolder: RecyclerView.ViewHolder, swipeDir: Int) { //3 val position = viewHolder.adapterPosition photosList.removeAt(position) recyclerView.adapter.notifyItemRemoved(position) } } //4 val itemTouchHelper = ItemTouchHelper(itemTouchCallback) itemTouchHelper.attachToRecyclerView(recyclerView) }
Let’s go through this step by step:
You create the callback and tell it what events to listen for. It takes two parameters, one for drag directions and one for swipe directions, but you’re only interested in swipe, so you pass 0 to inform the callback not to respond to drag events.
You return false in onMove because you don’t want to perform any special behavior here.
onSwiped is called when you swipe an item in the direction specified in the ItemTouchHelper. Here, you request the viewHolder parameter passed for the position of the item view, then you remove that item from your list of photos. Finally, you inform the RecyclerView adapter that an item has been removed at a specific position.
You initialize the ItemTouchHelper with the callback behavior you defined, and then attach it to the RecyclerView.
Add the method to the activity’s onCreate(), underneath setRecyclerViewScrollListener():
setRecyclerViewItemTouchListener()
This will attach the ItemTouchListener to the RecyclerView using the code you just wrote.
Run the app once more and swipe across one of your items, you should see it begin to move. If you swipe the item far enough, you should see it animate and vanish. If other items are visible, then they will reorganize themselves to cover the hole. How cool is that?
Where To Go From Here?
Nice job! You’ve been on quite an adventure, but now it’s time to head back to Earth and think about what you’ve learned.
You’ve created a RecyclerView and all the components it needs, such as a LayoutManager, an Adapter and a ViewHolder.
You’ve updated and removed items from an Adapter.
You’ve added some cool features like changing layouts and adding swipe functionality.
Above all, you’ve experienced how separation of components — a key attribute of RecyclerViews — provides so much functionality with such ease. If you want your collections to be flexible and provide some excitement, then look no further than the all-powerful RecyclerView.
The final project for this tutorial is available here.
If you want to learn more about RecyclerViews then check out the Android documentation to see what it can do. Take a look at the support library for RecyclerViews to learn how to use it on older devices. If you want to make them fit with the material design spec then check out the list component design specification.
Join us in the forums to discuss this tutorial and your findings as you work with RecylerViews!
Until next time, space traveler!
The post Android RecyclerView Tutorial with Kotlin appeared first on Ray Wenderlich.
Android RecyclerView Tutorial with Kotlin published first on http://ift.tt/2fA8nUr
0 notes