I'm newbie in Kotlin and i'm trying to know how can i implementing java interface on kotlin, i'm using that on android,
public interface OnClickedItemListener {
void onClick(boolean state);
}
OnClickedItemListener is my custom interface which i want to implementing that, in kotlin i have this class:
class MyProgressView : RelativeLayout {
constructor(context: Context?) : super(context) {
init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
init()
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
private fun init() {
LayoutInflater.from(context).inflate(R.layout.download_progress_layout, this)
cusotmView.setOnClickListener {
}
}
}
in that whats equivalent this cods for example:
class MyProgressView : RelativeLayout {
constructor(context: Context?) : super(context) {
init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
init()
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
private fun init() {
LayoutInflater.from(context).inflate(R.layout.download_progress_layout, this)
cusotmView.setOnClickListener {
/*
if(onitemClickListener!=null) onitemClickListener.onClick()
*/
}
}
/*
public interface OnitemClickListener{
void onClick();
}
public static void setOnitemClickListener(OnitemClickListener listener){
onitemClickListener = l;
}
*/
}
use setOnClickItemListener in your Activity.
class MyProgressView : RelativeLayout, OnClickedItemListener {
var onClickItemListener: OnClickedItemListener? = null
constructor(context: Context?) : super(context) {
init()
}
constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
init()
}
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init()
}
private fun init() {
LayoutInflater.from(context).inflate(R.layout.download_progress_layout, this)
}
override fun onClick(state: Boolean) {
//do something on onclick
}
fun setOnClickedItemListener(onclickItemListener: OnClickedItemListener) {
this.onClickItemListener = onclickItemListener
}
}
I hope this may help you.
Related
Is there a way to custom checkbox to Read aloud with format : checkbox + [text] + [state of checkbox] that the screen reader, in android case the TalkBack, has to read the accessible elements ?
CODE:
class CustomRadioButton : AppCompatRadioButton {
var talkBackString: CharSequence? = null
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(
context,
attrs,
defStyle
) {
setupView()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
setupView()
}
constructor(context: Context) : super(context) {
setupView()
}
private fun setupView() {
accessibilityDelegate = MyAccessibilityDelegate()
}
inner class MyAccessibilityDelegate : AccessibilityDelegate() {
/**
* Override function onInitializeAccessibilityNodeInfo of AccessibilityDelegate
* #param host is [View]
* #param info is [AccessibilityNodeInfo]
*/
override fun onInitializeAccessibilityNodeInfo(host: View, info: AccessibilityNodeInfo) {
super.onInitializeAccessibilityNodeInfo(host, info)
if (talkBackString.isNullOrEmpty() && host.contentDescription.isNullOrEmpty().not()) {
talkBackString = host.contentDescription
}
info.apply {
contentDescription = ""
hintText = talkBackString.toString()
error = ""
text = ""
}
}
}
}
I'm making my custom view. Before I add constructor contain defStyleRes, the original constructor is primary constructor. so I can use attrs at init. How can I use it now?
class StoreTotalPanel : RelativeLayout {
#JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0)
: super(context, attrs, defStyleAttr)
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int)
: super(context, attrs, defStyleAttr, defStyleRes)
init {
LayoutInflater.from(context)
.inflate(layout.panel_store_total, this, true)
attrs?.let { // <- Here is error
val typedArray = context.obtainStyledAttributes(it, R.styleable.custom_card_view)
val myString = typedArray.getString(R.styleable.custom_card_view_command)
}
}
...
}
It is because init relies on the primary constructor. Since there is none, it fails to find attrs. The solution is to replace init with your own function, which is called by both secondary connstructors:
class StoreTotalPanel : RelativeLayout {
#JvmOverloads
constructor(
context: Context,
attrs: AttributeSet? = null,
defStyleAttr: Int = 0
) : super(context, attrs, defStyleAttr) {
init(context, attrs)
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) {
init(context, attrs)
}
private fun init(context: Context, attrs: AttributeSet?) {
LayoutInflater.from(context).inflate(layout.panel_store_total, this, true)
attrs?.let {
val typedArray = context.obtainStyledAttributes(it, R.styleable.custom_card_view)
val myString = typedArray.getString(R.styleable.custom_card_view_command)
}
}
}
Be aware that inflate() returns a view which you do not use yet; the layout will be empty with this code snippet.
Have you tried to create a val on constructor itself?
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
constructor(
context: Context,
attrs: AttributeSet?,
defStyleAttr: Int,
private val defStyleRes: Int)
: super(context, attrs, defStyleAttr, defStyleRes)
I am trying to make a class extends from Vertical linerLayout and holds two views for ex ImageView and EditText how I can add and control the two views in the parent class
class GoogleSearchBar : LinearLayout {
constructor(context: Context) : super(context) {
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr:
Int) : super(context, attrs, defStyleAttr) {
}
}
class GoogleSearchBar : LinearLayout {
constructor(context: Context) : super(context) {
setupView()
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
setupView()
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr:
Int) : super(context, attrs, defStyleAttr) {
setupView()
}
private void setupView(){
View view = inflater.inflate(R.layout.my_view, null, false);
addlayout.addView(view);
}
}
create xml layout with name my_view.
I want to use library which is in Java and it has alot of errors so I'm trying to change it to Kotlin. And AndroidStudio is not converting Java to Kotlin properly so I have to do it function by function and check it manually. But these 3 constructors gives error:
Error: None of these following functions can be called with the arguments supplied
Java:
public class CountryCodePicker extends RelativeLayout
...
public CountryCodePicker(Context context) {
super(context);
if (!isInEditMode()) init(null);
}
public CountryCodePicker(Context context, AttributeSet attrs) {
super(context, attrs);
if (!isInEditMode()) init(attrs);
}
public CountryCodePicker(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
if (!isInEditMode()) init(attrs);
}
Kotlin:
class CountryCodePicker: RelativeLayout
...
constructor(context: Context): this{
super(context)
if (!isInEditMode) init(null)
}
constructor(context: Context, attrs: AttributeSet): this{
super(context, attrs)
if (!isInEditMode) init(attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): this{
super(context, attrs, defStyleAttr)
if (!isInEditMode) init(attrs)
}
class CountryCodePicker: RelativeLayout {
constructor(context: Context) : super(context) {
if (!isInEditMode) init(null)
}
constructor(context: Context, attrs: AttributeSet): super(context, attrs){
if (!isInEditMode) init(attrs)
}
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int): super(context, attrs, defStyleAttr) {
if (!isInEditMode) init(attrs)
}
}
You should use JvmOverloads for this:
class CountryCodePicker #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : RelativeLayout(context, attrs, defStyleAttr) {
init {
if (!isInEditMode()) {
init(attrs) // or better inline the function body
}
}
}
The JvmOverloads will create the 3 constructors with the default values as defined. That is the behavior you would expect and makes the code cleaner.
I try to subclass EditText for convenience reasons (NumberEdit) using kotlin but the rendered View loses most of the EditText properties. The look is that of a TextView and it is not focusable with the mouse (in the emulator). When I click into the activity I can then edit the first of the NumberEdit widgets and can cycle to the next one with the tab key.
I added two emulator screenshots to illustrate the difference.
An EditText looks like this
The new NumberEdit looks like this
The extended class looks like this:
import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.widget.EditText
class EditNumber(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int, defStyleRes: Int)
: EditText(context, attributeSet, defStyleAttr, defStyleRes) {
constructor(context: Context) : this(context, null, 0, 0)
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0, 0)
constructor(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int)
: this(context, attributeSet, defStyleAttr, 0)
init {
inputType = InputType.TYPE_CLASS_NUMBER + InputType.TYPE_NUMBER_FLAG_DECIMAL
}
}
Does anyone have a clue what I am doing wrong? Do I have to reference some attributes explicitly?
I'm not a kotlin expert but if you look at the java source code for edittext you have following:
public class EditText extends TextView {
public EditText(Context context) {
this(context, null);
}
public EditText(Context context, AttributeSet attrs) {
this(context, attrs, com.android.internal.R.attr.editTextStyle);
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr) {
this(context, attrs, defStyleAttr, 0);
}
public EditText(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
It doesn't look like you pass the right parameters to the constructor... You pass a lot of 0s and nulls...
In Kotlin you can write this much more concise:
class EditNumber #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = R.attr.editTextStyle,
defStyleRes: Int = 0
) : EditText(context, attrs, defStyle, defStyleRes)
Notice the defStyle parameter.