Kotlin synthetic in Adapter or ViewHolder - kotlin

I am new in kotlin. I have found and tried to use synthetic method instead of annoying method findViewById in my Activity class, but I have found "If we want to call the synthetic properties on View (useful in adapter classes), we should also import kotlinx.android.synthetic.main.view.*." But I can't figure out how it exactly works? Is there any examples?

Simple example from https://github.com/antoniolg/Kotlin-for-Android-Developers
import kotlinx.android.synthetic.item_forecast.view.*
class ForecastListAdapter() : RecyclerView.Adapter<ForecastListAdapter.ViewHolder>() {
class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
fun bindForecast(forecast: Forecast) {
itemView.date.text = forecast.date.toDateString()
}
}
}
No need to write
val view = itemView.findViewById(R.id.date) as TextView
view.text = forecast.date.toDateString()
Just
itemView.date.text = forecast.date.toDateString()
Simple and effective!

Kotling 1.1.4 out
Further information : https://antonioleiva.com/kotlin-android-extensions/
You need to enable Kotlin Android Extentions by adding this to your build.gradle:
apply plugin: 'org.jetbrains.kotlin.android.extensions'
androidExtensions {
experimental = true
}
Since this new version of Kotlin, the Android Extensions have incorporated some new interesting features: caches in any class (which interestingly includes ViewHolder)
Using it on a ViewHolder (or any custom class). Note that this class should implement LayoutContainer interface:
class ViewHolder(override val containerView: View) : RecyclerView.ViewHolder(containerView),
LayoutContainer {
fun bind(title: String) {
itemTitle.text = "Hello Kotlin!"
}
}

You need
import kotlinx.android.synthetic.row_wall.view.*
And later something along the lines of:
convertView.titleText.text = item.title
The point is that the view.* introduces extensions to the View class.

Try
class CustomViewModel(val baseView: View) {
val firstName = baseView.firstName
val lastName = baseView.lastName
}
View object exposes the views
ref:https://discuss.kotlinlang.org/t/unable-to-use-kotlin-android-extension-in-adapter-class/2890

If you are using the latest version l;.you don't have to add experimental = true to it.
in Project level Gradle
classpath 'org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.21'
And in app level Gradle
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions' //These should be on the top of file.
and in dependencies..
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.21'
and import below as
import kotlinx.android.synthetic.main.your_layout_file_name.view.*
and example
import kotlinx.android.synthetic.main.item_animal.view.*
class AnimalVH(parent: ViewGroup, layoutID: Int) : BaseViewHolder<Animal>(parent, layoutID) {
override fun bindData(animal: Animal) {
itemView.tv_animal.text = animal.title
}
}
where BaseViewHolder is
abstract class BaseViewHolder<T>(parent: ViewGroup, layoutID: Int) : RecyclerView.ViewHolder(
LayoutInflater.from(parent.context).inflate(layoutID, parent, false)
) {
abstract fun bindData(model: T)
}

It means you have to place this line at the beginning of your source file:
import kotlinx.android.synthetic.main.view.*
So now instead of, for example, findView(R.id.textView) as TextView you would write just textView. The latter is a synthetic extension property located in the package kotlinx.android.synthetic.main.view, that's why you have to import everything from it.
There's a tutorial on the official site, take a look.

FYI: Data binding is recommended over synthetic for view lookups.
Comment from a DA for Android from Google on Reddit
Hey! Developer Advocate for Android at Google here!
I wanted to add a bit of background here. Kotlin Extensions with
synthetic views was never intentionally “recommended” though that
shouldn’t be taken as a recommendation to not use them. If they're
working for you please feel free to continue using them in your app!
We’ve been shifting away from them (e.g. we don’t teach them in the
Udacity course) because they expose a global namespace of ids that’s
unrelated to the layout that’s actually inflated with no checks
against invalid lookups, are Kotlin only, and don't expose nullability
when views are only present in some configuration. All together, these
issues cause the API to increase number of crashes for Android apps.
On the other hand, they do offer a lightweight API that can help
simplify view lookups. In this space it's also worth taking a look at
Data Binding which also does automatic view lookups - as well as
integrates with LiveData to automatically update your views as data
changes.
Today, there's a few options in this space that work:
Data Binding is the recommendation for view lookup as well as binding,
but it does add a bit of overhead when compared to Android Kotlin
Extensions. It's worth taking a look to see if this is a good fit for
your app. Data Binding also allows you to observe LiveData to bind
views automatically when data changes. Compared to Kotlin Extensions,
it adds compile time checking of view lookups and type safety. Android
Kotlin Extensions is not officially recommended (which is not the same
as recommendation against). It does come with the issues mentioned
above, so for our code we're not using them. Butter Knife is another
solution that is extremely popular and works for both Kotlin and the
Java Programming Language. Reading through the comments here there's a
lot of developers that are having great luck with Kotlin Extensions.
That's great - and something we'll keep in mind as we look at ways to
continue improving our APIs. If you haven't taken a look at Data
Binding, definitely give it a shot.
As an aside, our internal code style guide is not intended to be
directly applied outside of our codebase. For example, we use
mPrefixVariables, but there's no reason that every app should follow
that style.

Related

How to move a function from one Kotlin class to another using IntelliJ?

I'm using IntelliJ IDEA to refactor some Kotlin code. I have two classes in the same file and I want to move a function from one class to another using Refactor -> Move (F6), but that doesn't work, and I get tooltip message that says: "Cannot perform refactoring. Move declaration is only supported for top-level declarations and nested classes".
Am I doing something wrong? Or that refactoring is simply not supported?
[edit1] I tried to do the same operation with Java classes and everything works perfectly; so why this is not allowed for Kotlin?
[edit2] I thought that the problem is only when to two classes are in the same file, but it turns out that is not possible to move a function between classes in separate files!
It's a well-known Kotlin-only problem.
in IDEA (both free and paid editions);
in Android Studio.
Official ticket
There is an easy, but slightly janky, work around.
You just need to wrap the function you want to move in a class:
class TopLevelClass {
fun functionToMove() {
//...
}
}
wrap it in a new class
class TopLevelClass {
class TemporaryMoveClass{ /** you can now move this entire new class */
fun functionToMove() {
//...
}
}
}
and after you do the refactor, delete the temporary wrapper class you created.
The janky part is that you need to replace all instances of functionToMove() with NewTopLevelClass.functionToMove() yourself.
One of the major benefits of doing it this way, rather than just cut and pasting it yourself, is that as soon as you wrap it in the TemporaryMoveClass it will tell you any parameters you need to introduce(Refactor>Extract>Parameter). And then you can do that inside the original TopLevelClass before you move it. (this preserves the types of any TopLevelClass properties you were using, and automatically introduces the new parameter(s) into the existing function calls)

JavaFX vertical slider

I'm exploring JavaFX and I must say I'm little disappointed with the lack of learning material. I'm rookie to JavaFX but I have some experience with Swing.
How can I place the slider vertically?
And one more question,I want the Thumb to be draggable only to the Tick marks,not in the intermediate space,how can I achieve that?
How can I place the slider vertically?
Use setOrientation
slider.setOrientation(Orientation.VERTICAL);
I want the Thumb to be draggable only to the Tick marks,not in the intermediate space,how can I achieve that?
Use setSnapToTicks after setting an appropriate tick unit, count and block increment.
slider.setMajorTickUnit(0.25f);
slider.setMinorTickCount(1);
slider.setBlockIncrement(0.125f);
slider.setSnapToTicks(true);
Sample app:
import static javafx.application.Application.launch;
import javafx.application.*;
import javafx.event.*;
import javafx.geometry.Orientation;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.scene.layout.*;
import javafx.stage.Stage;
public class VerticalSliderSample extends Application {
#Override public void start(Stage stage) {
Slider slider = new Slider(0, 1, 0.5);
slider.setShowTickMarks(true);
slider.setShowTickLabels(true);
slider.setMajorTickUnit(0.25f);
slider.setMinorTickCount(1);
slider.setBlockIncrement(0.125f);
slider.setSnapToTicks(true);
slider.setOrientation(Orientation.VERTICAL);
VBox layout = new VBox(10);
layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 10;");
layout.getChildren().setAll(slider);
stage.setScene(new Scene(layout));
stage.show();
}
public static void main(String[] args) { launch(args); }
}
I'm exploring JavaFX and I must say I'm little disappointed with the luck of learning material.
Email (constructive) feedback on Oracle developed JavaFX documentation to:
jfx-docs-feedback_ww#oracle.com
With Java 8 and with it JavaFX 8 and its corresponding SceneBuilder coming (at this time of post its still Java 7 GA with SceneBuilder 2.2), people should get more familiar using it. It is a powerful tool for people who don't know each special attribute from its hat off and want to practice the Inversion of Control principle the new JavaFX and its FXMLs offer us.
Here is an example out of one of my projects to show the most popular
properties on each Node
Though I can sometimes understand you, for being frustrated especially if some new features come out, that some higher class examples what this Node can do and maybe find it easier, but as a programmer you need to learn to work with the corresponding API. It would be nice to have a part of each API documentation like in the PHP community where you can maintain it as a wiki.

Qt5. Embed QWidget object in QML

I am using Qt5 beta and trying to embed a QWidget-based object into QML. The goal is to use QML as much as possible, and only use QWidget objects where QML does not do what I need. I found a link explaining how to do this for Qt4.7, but I have not found any information explaining how to do this in Qt5.
http://doc.qt.digia.com/4.7/declarative-cppextensions-qwidgets.html
The same example is also available in the Qt5 examples folder under:
examples\qtquick1\declarative\cppextensions\qwidgets
Unfortunately, this example uses QtQuick 1, rather than QtQuick 2, and I would like to use the new features of Qt5. I actually want to embed a qwt widget, but as a first step I would be happy to embed any simple QWidget-based object.
Can anybody help me get the example working under Qt5 / QtQuick 2 ?
Qt Quick 2 uses a scene graph for efficient rendering on the GPU. Unfortunately this makes it impossible to embed classic widgets into the scene. The old approach to embed such widgets with the help of QGraphicsProxyWidget works only with Qt Quick 1, because internally it uses a QGraphicsView for all the heavy lifting and QGraphicsProxyWidget is meant to be used with it.
As of now there are no plans to enable embedding classic QWidgets into the scene graph I know of. I think this is rather unlikely to change, because the concepts of QPainter, the painting framework used for the classic widgets, and the new scene graph doesn't play well with each other.
There some efforts to develop new widgets sets specifically tailored for the needs of QML, but none of them are as powerful and mature as the classic widgets. The most prominent ones are the QML Quick Controls, bundled with Qt since version 5.1.
If you really depend on QWT my advice would be to stick with Qt Quick 1.1 for now. It's still bundled with Qt 5, probably for cases like yours. That way you won't take advantage of the new scene graph, though.
You can embed QWidget to QML by using QQuickPaintedItem class:
http://doc.qt.io/qt-5/qquickpainteditem.html
Qt5 has an example:
http://doc.qt.io/qt-5/qtquick-customitems-painteditem-example.html
You should implement an inherent of QQuickPaintedItem with private widget attribute, that you want to embed. Provide paint method, that just render the QtWidget and provide mouse and other event transmitting from inherit of QQuickPaintedItem to embed QtWidget.
There's also QSG (Qt scene graph API), but my experience with that thing wasn't smooth. I believe the clue in multithreading (performing rendering in the different thread (not the Qt GUI thread one, however on Windows that's not true and all is done in main GUI thread).
I've implemented embedding of QCustomPlot, here's link: github.com/mosolovsa/qmlplot
What could be done is to render the widget to an image and upload as texture.For interaction someone needs to forward events like mouseClick or keyPressed from the sceneGraph, translate to widget coordinates, pass on, render and upload texture again. Just an idea :)
The recommended approach is to stay with a QWidget based application and embed the QML parts using QWidget::createWindowContainer.
Further to Julien's answer - a simple way to achieve this is to use QQuickWidget to display the QML scene, and then add a regular QWidget as a child of the QQuickWidget. You can also add a simple intermediate QObject to anchor the QWidget to an item in the scene.
E.g.:
In main.qml:
Item {
... // layouts, extra items, what have you
Item
{
objectName: "layoutItem"
anchors.fill: parent
}
... // more layouts, extra items, etc.
}
widgetanchor.h:
class WidgetAnchor: public QObject
{
ptr<QWidget> _pWidget;
QPointer<QQuickItem> _pQuickItem;
public:
WidgetAnchor(QWidget* pWidget, QQuickItem* pItem)
: QObject(pWidget), _pWidget(pWidget), _pQuickItem(pItem)
{
connect(_pQuickItem, &QQuickItem::xChanged, this, &WidgetAnchor::updateGeometry);
connect(_pQuickItem, &QQuickItem::yChanged, this, &WidgetAnchor::updateGeometry);
connect(_pQuickItem, &QQuickItem::widthChanged, this, &WidgetAnchor::updateGeometry);
connect(_pQuickItem, &QQuickItem::heightChanged, this, &WidgetAnchor::updateGeometry);
updateGeometry();
}
private:
void updateGeometry()
{
if (_pQuickItem)
{
QRectF r = _pQuickItem->mapRectToItem(0, QRectF(_pQuickItem->x(), _pQuickItem->y(), _pQuickItem->width(), _pQuickItem->height()));
_pWidget->setGeometry(r.toRect());
}
}
};
In main.cpp:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
auto pqw = new QQuickWidget;
pqw->setSource(QUrl::fromLocalFile("main.qml"));
pqw->setResizeMode(QQuickWidget::SizeRootObjectToView);
pqw->setAttribute(Qt::WA_DeleteOnClose);
auto pOwt = new MyWidget(pqw);
if (auto pOverlayItem = pqw->rootObject()->findChild<QQuickItem*>("overlayItem"))
new WidgetAnchor(pOwt, pOverlayItem);
pqw->show();
return app.exec();
}
The documentation states that using QQuickWidget has advantages over QQuickView and QWidget::createWindowContainer, such as no restrictions on stacking order, but has a 'minor performance hit'.
Hope that helps.

Is there any data binding mechanism available for iOS?

In .NET I just do something like DataForm.Source = Object and then magic happens. Platform routes data changes from ui fileds to object properties, does validation and so on. Can I do something similar with Cocoa Touch and CoreData objects?
The closest thing in Cocoa is 'Key-Value Observing'. In the desktop Cocoa framework you can use bindings to hook user interface elements up to underlying objects so that changes in the objects or UI elements are reflected in the other.
Whilst Cocoa on iOS doesn't have this sort of UI bindings, you can still use 'Key-Value Observing' to synchronise changes in the data model with UI elements as described here:
http://developer.apple.com/library/iOS/#documentation/General/Conceptual/Devpedia-CocoaApp/KVO.html
I wrote a little open-source library that provides some simple data-binding functionality. It's basically just a wrapper around key-value observing (KVO).
http://github.com/kristopherjohnson/KJSimpleBinding
There are a few other similar libraries on GitHub:
http://github.com/dewind/KeyPathBindings
http://github.com/jonsterling/Observe
http://github.com/mruegenberg/objc-simple-bindings
http://github.com/zeasy/EasyBinding
Probably should also mention Github's Reactive Cocoa, a framework for composing and transforming sequences of values, an objective-C version of .NET's Reactive Extensions (Rx).
Binding mechanics can be done really simple (from the sample):
// RACObserve(self, username) creates a new RACSignal that sends a new value
// whenever the username changes. -subscribeNext: will execute the block
// whenever the signal sends a value.
[RACObserve(self, username) subscribeNext:^(NSString *newName) {
NSLog(#"%#", newName);
}];
Don't forget NSFetchedResultsController.
Not a full blown data bound controller, but makes table views a lot easier to use with Core Data.
If you're using Swift, check out Bond framework: https://github.com/ReactiveKit/Bond
Binding is as simple as:
textField.reactive.text.bind(to: label.reactive.text)
It plays well with functional:
textField.reactive.text
.map { "Hi " + $0 }
.bind(to: label.reactive.text)
And provides simple observations:
textField.reactive.text
.observeNext { text in
print(text)
}
STV (http://sensiblecocoa.com) is a framework that can do that within tableviews
I use CoreDataTableViewController from the Stanford University for my TableViewControllers. It hides a lot of details that you would normally implement in your TableViewController.
Googling for CoreDataTableViewController.h and .m will help you on the road. There are versions from several courses available, the latest does ARC, the old ones don't.
For syncing labels and edit fields with an NSManagedObject, I am still looking for a good solution.
Yes, there is a data binding framework that integrates well into Interface Builder and requires only minimal code overhead (if at all).
Take a look at https://github.com/mutech/aka-ios-beacon
EDIT:
You can for example bind a table view to a fetched results controller simply by setting the data source binding property of the table view in interface builder to:
[ yourResultsController ] { defaultCellMapping: "YourCellId" }
And the only thing you have to do is to define a property yourResultsController in your view controller.
The wiki provides a rather complete documentation and a lot of example use cases.

Does Xcode support regions?

Does Xcode support anything akin to Visual Studio style #region directives for arbitrary code folding?
No, you can only fold code on various defined scoping levels in Xcode.
You can use little tricks to make navigating via the function menu easier, though.
#pragma mark
Allows you to create a grouping where the label following mark will show up in the function menu. If the label is a hyphen, a separator is inserted into the function menu.
Also, the following labels in comments will show up in the function menu:
// MARK:
// TODO:
// FIXME:
// !!!:
// ???:
Obviously since #pragma mark is not really portable, if you're building a portable application and need it to work with a compiler that doesn't just ignore #pragma directives that it doesn't understand, the comment-style mark is a decent alternative.
I am going to hell for this but here goes:
At the top of a given file, put
#define FOLD 1
Wherever you want to fold something, wrap it in an if block like so:
if(FOLD) {
// your code to hide
// more code
}
That will let you fold it away out of sight.
That won't work in the place you want it most, that is, around groups of functions or methods.
It may be useful inside a long, linear method with no internal conditionals or loops, but such methods aren't common in general Mac OS X UI code, though if you're writing some big numeric or graphics-crunching code it could help group things.
And the if(fold) is entirely superfluous. Just use the braces inside a method or function and Xcode will fold them.
Try this way :
//region title1
{
//region Subtitl1
{
}
//region Subtitl2
{
}
}
It can do like that :
Without support for .Net style regions, being able to collapse all your functions at the same time is the next best thing.
command-option-shift-left arrow
to collapse all.
command-option-shift-right arrow
to expand all.
Xcode will remember the last state of collapsed functions.
A useful option in XCode 12 (maybe before), is an option in preferences "Code Folding Ribbon"
When you check it, the source code looks like this
When you hover the mouse over this ribbon, you get foldable regions based on brackets, like this
When you click the Ribbon, it folds the bracket region, like this
Its not as the regions in Visual Studio, where you can place them wherever you want, but they're good enough to tidy up your code files.
To answer your question...No. And It drives me nuts.
If you have the opportunity/ability you can use AppCode for this. I've been using it for a few years and it usually beats Xcode in many areas.
Also I specifically use AppCode because of these features:
Ability to use regions
Searching classes, text and usages is MUCH faster.
Refactoring is also faster.
Cleaner and more customizable UI.
Tabs are handled (in my opinion) much better than in Xcode.
FOLDING. You can actually change what levels of folding you want. Why Apple thought there should be no quick-key to fold extensions is beyond me. And fold ribbons? Really Apple? Yes they're pretty and all but most professionals use hotkeys for everything.
Better GIT integration.
Support for live updates in SwiftUI
If you use other Jetbrains IDE's like PyCharm or Android Studio the UI is exactly the same.
Some downsides of AppCode:
Some things that work in Xcode aren't supported
Visual #colorLiteral(). When using them they don't show a color picker.
No Storyboard support. Annoying to have to open up Xcode. If you write your UI in code this is a moot point.
Editing .plist files isn't as nice. Doable, but not nice.
Initial indexing can take a while.
Cost. But I would argue the time savings in just navigation will compensate for this.
Kind of a lot for a simple question but I think it's nice having alternatives.
Put your desired code inside brackets { }, and it will become a folding zone.
But you have to keep in mind that brackets also define variables scope, so this code should not have variables declarations which will be used outside these brackets.
One nice solution I just found:
Put your project into one big namespace.
Close and reopen this namespace for the individual sections of your source file:
namespace myproj { // members of class MyClassA
void MyClassA::dosomething()
{
}
void MyClassA::dosomethingelse()
{
}
} // members of class MyClassA
namespace myproj { // members of MyClassB
void MyClassB::dosomething()
{
}
void MyClassB::dosomethingelse()
{
}
} // members of MyClassB