Meaning of this in Java (currently in Kotlin) - java

I am looking at a class which goes like this:
class temp(context: Context, attrs: AttributeSet) :
LinearLayout(context, attrs), tempInterface {
..................................
}
I just wanted to ask, how can I translate this to Java? I have been able to do this as of now:
public class temp extends LinearLayout implements tempInterface
....................
public temp(Context context, AttributeSet attrs) {
super(context, attrs);
}
....................
}
In the Kotlin version, I see that LinearLayout is also accepting two attributes (context and attrs) whereas in Java version I see I have only defined the constructor for the primary class, i.e. temp. Is that okay?

What you wrote is exactly equivalent to the Kotlin code. There are several ways to valide this.
Use Kotlin decompiler
You can copy the Kotlin code into a project that has Kotlin set up (you can find working samples), then open it in IntelliJ IDEA or Android Studio.
There's a menu item: Tools > Kotlin > Show Kotlin bytecode, and then there's a Decompile button on it.
Executing this flow gives the following output:
public final class temp extends LinearLayout implements tempInterface {
public temp(#NotNull Context context, #NotNull AttributeSet attrs) {
Intrinsics.checkNotNullParameter(context, "context");
Intrinsics.checkNotNullParameter(attrs, "attrs");
super(context, attrs);
}
}
This is the exact code that Kotlin compiles to.
Ask ChatGPT to translate it
This is perfect for ChatGPT's capabilities, rather than asking here on SO. I tried it myself with prompt: "here's some Kotlin code, translate to Java: <code>" and it gave an almost perfect translation of the Kotlin code back to Java. It just missed public on class.
Look at documentation
This being said, you probably want to create a custom view/layout in Android using the Java language. You can see the example code and other documentation here: https://developer.android.com/develop/ui/views/layout/custom-views/create-view#subclassview
If you swap between Java and Kotlin just above the code block you can find a very similar example to yours.
Generate code from template in Android Studio
Note that usually you need 3 constructors, this is shown by looking at the code generated in Android Studio:
public class MyView extends View {
public MyView(Context context) {
super(context);
init(null, 0);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
init(attrs, 0);
}
public MyView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(attrs, defStyle);
}
private void init(AttributeSet attrs, int defStyle) {
...
}
}
You can use Android Studio's File > New > UiComponent > Custom View. Note that this action is context sensitive, make sure you're inside a Java or Kotlin file in an Android module, or right clicks src/main/java or src/main/kotlin to be sure.

Related

What is resource:0 doing?

I didn't understand what is the use of 0 here.
What exactly it is doing?
public WordAdapter(Activity nmbersActivity, ArrayList<Word> word) {
super(nmbersActivity,0,word);
}
And i have check the documentation and can't find exactly what it is.
In the implementaion this is the code.
public ArrayAdapter(#NonNull Context context, #LayoutRes int resource,
#NonNull List<T> objects) {
this(context, resource, 0, objects);
}
From the docs:
The id of the TextView within the layout resource to be populated
ArrayAdapters are commonly used in lists so a text resource id is included to display the item title. Passing 0 signifies the default state of no TextView resource.

How to remove toolbar buttons in dankito/RichTextEditor for Android

I integrated the following library in my Android app project successfully. That works well, Thanks to the author dankito !
RichTextEditor
However, I would like to remove some buttons from the toolbar. (Heading 1 - 6, Body Text, Preformatted, Block quot, Insert Checkbox ..)
But I do not understand how to do it. It's written in Kotlin.
Is it possible to do it simply? I am stuck ...
I would also like to change the strings of characters to translate them into French. Is it possible ?
Here is the code of the library that I obviously can not modify.
package net.dankito.richtexteditor.android.toolbar
import android.content.Context
import android.util.AttributeSet
import net.dankito.richtexteditor.android.command.*
class AllCommandsEditorToolbar : EditorToolbar {
constructor(context: Context) : super(context) { initToolbar() }
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) { initToolbar() }
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initToolbar() }
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { initToolbar() }
private fun initToolbar() {
addCommand(BoldCommand())
addCommand(ItalicCommand())
addCommand(UnderlineCommand())
addCommand(StrikeThroughCommand())
addCommand(SuperscriptCommand())
addCommand(SubscriptCommand())
addCommand(RemoveFormatCommand())
addCommand(UndoCommand())
addCommand(RedoCommand())
addCommand(BlockQuoteCommand())
addCommand(SetTextFormatCommand())
addCommand(SetFontNameCommand())
addCommand(SetFontSizeCommand())
addCommand(SwitchTextColorOnOffCommand())
addCommand(SetTextColorCommand())
addCommand(SwitchTextBackgroundColorOnOffCommand())
addCommand(SetTextBackgroundColorCommand())
addCommand(DecreaseIndentCommand())
addCommand(IncreaseIndentCommand())
addCommand(AlignLeftCommand())
addCommand(AlignCenterCommand())
addCommand(AlignRightCommand())
addCommand(AlignJustifyCommand())
addCommand(InsertBulletListCommand())
addCommand(InsertNumberedListCommand())
addCommand(InsertLinkCommand())
addCommand(InsertImageCommand())
addCommand(InsertCheckboxCommand())
addSearchView()
}
}
Thanks for your help
In order to modify the library, you'll need to remove the dependency of the current library from the Build.gradle and then, adding the library as a module in Android Studio.
This answer already explained how to do that.
About your modification on the library, in initToolbar method (or maybe other methods, depends on the library implementation), you'll need to remove the Button (or anything you want) plus related codes inside the library.
i.e: Remove : addCommand(UndoCommand()) to remove UndoCommand from the library then look for related codes in the library and remove them too.

Intercept every view element being inflated?

I am trying to intercept every view widget that is being inflated in my activity and override the setText functionality of that view if it exists.
So if a TextView has a android:text="bla" in the XML layout i want to be able to intercept that and maybe add a ** at the end of all texts being set from the xml.
One way that seems to be close to what i need is to use a Custom Layout inflator.
LayoutInflaterCompat.setFactory(layoutInflator, InflatorOnSteriods(this))
and the in my InflatorOnSteriods to override onCreateView and then intercept all views there.. this approach doesn't seem to work at all. onCreateView is never called.
I tried also to use cloneInContext
LayoutInflaterCompat.setFactory(layoutInflater.cloneInContext(this), InflatorOnSteriods(this))
But no luck as well, maybe my approach is totally wrong i am also open to a different way where i can intercept all views being presented and to be specific set a certain attribute on that view. It is really important to make sure that i will be the last one changing that view and make sure the system respects my changes and wont override them later.
Update:
Although i don't think its relevant; Code of InflatorOnSteroids.kt
class InflatorOnSteriods(val appCompatActivity: AppCompatActivity) : LayoutInflaterFactory {
override fun onCreateView(parent: View, name: String, context: Context, attrs: AttributeSet): View {
var result: View
if (TextUtils.equals(name, "DebugDrawerLayout")) {
result = ImageView(context, attrs)
}
result = appCompatActivity.onCreateView(name, context, attrs)
if (result == null) {
// Get themed views from app compat
result = appCompatActivity.delegate.createView(parent, name, context, attrs)
}
return result
}
}
After some time troubleshooting my solution i finally managed to achieve what i wanted with the inflator factory solution.
First i create an abstract activity that has a custom inflator set to it.
abstract class SteroidsActivity : AppCompatActivity() {
var mInflater: LayoutInflater? = null
abstract fun getActivityLayout(): Int
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mInflater = layoutInflater?.cloneInContext(this)
LayoutInflaterCompat.setFactory(mInflater, InflaterOnSteroids(this))
setContentView(getActivityLayout())
}
override fun getLayoutInflater(): LayoutInflater? {
return mInflater
}
override fun getSystemService(name: String): Any? {
if (name == LAYOUT_INFLATER_SERVICE) {
if (mInflater == null) {
mInflater = super.getSystemService(name) as LayoutInflater
}
return mInflater
}
return super.getSystemService(name)
}
}
Second thing that you need to do is create your custom inflator factory
class InflaterOnSteroids(appCompatActivity1: AppCompatActivity) : LayoutInflaterFactory {
override fun onCreateView(parent: View?, name: String, context: Context, attrs: AttributeSet): View? {
//Do stuff here and return a view
return null
}
}
The problem with my code was that it was always crashing with a weird error that i couldn't troubleshoot until i realised that i need to add a ? after View since i'm using kotlin and parent view can be null :)
Happy programming
Good reference can be found here

android 2 way data binding example don't work as described

I read this article about 2 way android data binding
I noticed that code is a bit vague and decide to implement workable example and put it on github, so other guys will be much easier to dive in it. But going according instructions provided in this article I wasn't able make it work.
In my example I just have main activity with switcher, and custom control, also with switcher. So, when I checking main switcher it refresh all the stuff properly and work as expected, but however when I check/uncheck internal switcher, it dosen't affect main viewmodel and anything in activity - so 2 way binding not working.
Please, help me find the reason why this happen and fix the problem.
Code fixed and now worked as expected in Android Studio 2.2 beta 1 at least.
Link to the code sample on github
You almost hooked up everything properly. In CustomSwitcher, there was no notification when the inner switcher's value changed. You must listen for that change and call the onValChanged callback.
Here is your code:
public CustomSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);
this.binding = CustomSwitcherBinding.inflate(LayoutInflater.from(context), this, true);
}
public void setVm(boolean vmVal){
this.vm = vmVal;
this.binding.setItem(vm);
}
The inflated binding doesn't directly notify the custom switcher, so you must listen for the event. Then you'll have to call the listener. You must also avoid the infinite loop of notifying the same value over-and-over again by assuring that you're not setting the same value as already exists.
public CustomSwitcher(Context context, AttributeSet attrs) {
super(context, attrs);
this.binding = CustomSwitcherBinding.inflate(LayoutInflater.from(context), this, true);
this.binding.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
#Override
public void onPropertyChanged(Observable sender, int propertyId) {
if (propertyId == BR.item) {
setVm(binding.getItem());
}
}
});
}
public void setVm(boolean vmVal){
if (vmVal != this.vm) {
this.vm = vmVal;
this.binding.setItem(vm);
if (this.onValChanged != null) {
this.onValChanged.onValChanged(this, vmVal);
}
}
}

Kotlin initializing an object

I have a base class that I am extending, but want to inflate a view where the normal Java constructor would be.
class TextView(context: Context?) : ViewAbstractClass(context)
I am not sure how to do this in Kotlin. What are the constructs are there Kotlin that allow you to do complex initialisation of objects?
https://kotlinlang.org/docs/reference/classes.html#constructors
class Customer(name: String) {
init {
logger.info("Customer initialized with value ${name}")
}
}
There are a couple ways this can be done, however this is what I've been doing in my app.
class TextView : ViewAbstractClass {
constructor(context: Context) : super(context)
constructor(context: Context, attributeSet: AttributeSet) : super(context, attributeSet)
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int) : super(context, attributeSet, defStyleAttr) {
// custom init code for this constructor.
}
constructor(context: Context, attributeSet: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attributeSet, defStyleAttr, defStyleRes)
init {
// Common init code
}
}
Notice that you don't actually use () in the class signature, but instead provide all the constructors explicitly.
You can learn more about secondary constructors here:
https://kotlinlang.org/docs/reference/classes.html

Categories