Custom TextInputLayout - android

I want to have my CustomTextInputLayout to have Widget.MaterialComponents.TextInputLayout.OutlinedBox as default style without defining it anywhere in the XML.
I tried this
class CustomTextInputLayout #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextInputLayout(ContextThemeWrapper(context, R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox), attrs, defStyleAttr) {
}
and this
class CustomTextInputLayout #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : TextInputLayout(context, attrs, R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox)
but it's not working. I've tried the default XML way
<com.custom.CustomTextInputLayout
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
...>
<com.google.android.material.textfield.TextInputEditText
...
android:hint="Sample Hint" />
</com.custom.CustomTextInputLayout>
and it's working.
What am I missing here?
How can I set a default style for custom TextInputLayout without using XML?

It is not exactly what you are looking for.
You can define:
public class CustomTextInputLayout #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.attr.textInputStyle
) : TextInputLayout(ContextThemeWrapper(context, R.style.Outlined_Theme), attrs, defStyleAttr) { ... }
with:
<style name="Outlined.Theme" parent="">
<item name="textInputStyle">#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox</item>
</style>
Then in your layout juse use:
<com.example.quicksample.CustomTextInputLayout
....
android:hint="Sample">
<com.google.android.material.textfield.TextInputEditText../>
</com.example.quicksample.CustomTextInputLayout>
Your code doesn't work because ContextThemeWrapper(context, R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox) the 2nd parameter has to be an attribute theme and not a style (it is the same for TextInputLayout(context, attrs, R.style.Widget_MaterialComponents_TextInputLayout_OutlinedBox))

Related

Android Studio Eel xml preview not showing, custom component missing classes

I have recently updated Android Studio to Android Studio Electric Eel | 2022.1.1.
For xml layout if we are using simple view like TextView/Button , it is displayed on preview.
But if we are using CustomView, then it is not showing in preview.(Preview is blank)
Also it is showing error: Missing classes
My Simple Test App , main activity xml file is as
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.example.webviewdeeplink.CustomTextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is Test Text"
android:textSize="24sp"
app:font="RobotoCondensed-LightItalic.ttf"
app:layout_constraintBottom_toTopOf="#id/button"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Custom Component class -
class CustomTextView : androidx.appcompat.widget.AppCompatTextView {
constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(
context!!,
attrs,
defStyle
) {
init(attrs)
}
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs) {
init(attrs)
}
constructor(context: Context?) : super(context!!) {
init(null)
}
private fun init(attrs: AttributeSet?) {
if (attrs != null) {
val a = context.obtainStyledAttributes(attrs, R.styleable.CustomTextView)
val fontName = a.getString(R.styleable.CustomTextView_font)
try {
if (fontName != null) {
val myTypeface = Typeface.createFromAsset(
context.assets,
"fonts/$fontName"
)
setTypeface(myTypeface)
}
} catch (e: Exception) {
e.printStackTrace()
}
a.recycle()
}
}
}
If any one faced this issue , could you please confirm issue.
OR this is known Android Studio Issue?
try this code...
constructor(context: Context?, attrs: AttributeSet?, defStyle: Int) : super(
context!!,
attrs,
0
) {
init(attrs)
}
Replace defStyle with 0
Change the build variant to debug
Clean and Rebuild the project
This will fix the issue.

How to use CustomView in Android

In my application I create one custom view for show TextView and FontAwesome!
I write below codes, but not set values and just show default values!
TextWithIcon class :
class TextWithIcon #JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0,
defStyleRes: Int = 0
) : LinearLayout(context, attrs, defStyle, defStyleRes) {
init {
LayoutInflater.from(context).inflate(R.layout.layout_text_with_awesome, this, true)
orientation = VERTICAL
attrs?.let {
val typedArray = context.obtainStyledAttributes(R.styleable.TextWithIcon)
val title = resources.getText(
typedArray.getResourceId(
R.styleable.TextWithIcon_customText,
R.string.app_name
)
)
val icon = resources.getText(
typedArray.getResourceId(
R.styleable.TextWithIcon_customIcon,
R.string.app_name
)
)
val titleTxt = getChildAt(0) as TextView
titleTxt.text = title
Log.e("titleTxt",title.toString())
//binding.iconTxt.text = "&#x$icon"
typedArray.recycle()
}
}
}
CustomViewLayout file :
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="#+id/titleTxt"
android:layout_width="wrap_content"
android:layout_height="#dimen/_20mdp"
android:gravity="right"
android:textColor="#color/darkJungleGreen"
android:textSize="#dimen/_10font_mdp" />
<com.myapp.utils.views.FontAwesome
android:id="#+id/iconTxt"
android:layout_width="#dimen/_20mdp"
android:layout_height="#dimen/_20mdp"
android:layout_gravity="right"
android:gravity="center"
android:textColor="#color/beauBlue"
android:textSize="#dimen/_10font_mdp"
app:fontPath="fonts/fontawesome_re.ttf" />
</merge>
And I used this class with code in XML :
<com.myapp.TextWithIcon
android:id="#+id/item1Title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginRight="#dimen/_10mdp"
android:drawablePadding="#dimen/_5mdp"
android:gravity="center"
android:textColor="#color/ochre"
android:textSize="#dimen/_10font_mdp"
app:customIcon="f007"
app:customText="wegwergewrg"
app:fontPath="fonts/iransans_bold.ttf"
app:layout_constraintEnd_toStartOf="#id/item1Line"
app:layout_constraintTop_toTopOf="#id/item1Line" />
I set value with this code : app:customText="wegwergewrg", but not show this and just show default value from
resources.getText(
typedArray.getResourceId(
R.styleable.TextWithIcon_customText,
R.string.app_name
)
)
How can I fix it?
You are going to want your styleable to look something like this:
<resources>
<declare-styleable name="TextWithIcon">
<attr name="customText" format="reference|string" />
</declare-styleable>
</resources>
This definition will permit you to use text as well as a string resource id for "app:customText".
You can get the value from the attribute as follows:
class TestCustomView #JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null
) : androidx.appcompat.widget.AppCompatTextView(context, attrs) {
init {
val a = context.obtainStyledAttributes(attrs, R.styleable.TextWithIcon)
for (attr in 0 until a.indexCount) {
when (a.getIndex(attr)) {
R.styleable.TextWithIcon_customText -> {
text = a.getText(attr) ?: "Unknown text."
}
}
}
a.recycle()
}
}

Custom TextView not invoked

As the title says, I have implemented this simple custom textView. The idea would be to apply a style that I choose by passing it through xml.
The class I created, however, is never called, in fact in debug it never stops at the breakpoints I entered.
In particular, the class I am using is the following
class MyTextView : AppCompatTextView {
constructor(context: Context, attrs: AttributeSet?, defStyle: Int) : super(
context, attrs, defStyle
) {
init(attrs)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init(attrs)
}
constructor(context: Context) : super(context) {
init(null)
}
private fun init(attrs: AttributeSet?) {
if (attrs != null) {
val a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView)
val fontName = a.getString(R.styleable.MyTextView_fontName)
if (fontName != null) {
val myTypeface = Typeface.createFromAsset(context.assets, "fonts/$fontName")
typeface = myTypeface
}
a.recycle()
}
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
this.text = "new text"
}
}
Here my xml:
<com.example.utils.widget.MyTextView
android:id="#+id/myText"
android:layout_width="wrap_content"
android:layout_height="200dp"
android:elevation="20dp"
android:text="MyText"
app:fontName="ultrabold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
and here the attrs.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTextView">
<attr name="fontName" format="string"/>
</declare-styleable>
</resources>
All compile correctly but I can't see my textview and not invoked by breakpoints. Anyone know why?

IndexOutOfBoundException in EditText

I'm using custom editText for showing number value, It working in most of the time but some time it throw IndexOutOfBoundsException.
CustomEditText,
class FixedCursorEditText : EditText {
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet, defStyle: Int) : super(context, attrs, defStyle)
override fun onSelectionChanged(selStart: Int, selEnd: Int) {
this.text?.length?.let { this.setSelection(it) }
}
}
XML file,
<sample.example.views.FixedCursorEditText
android:id="#+id/enterAmountEditText"
android:layout_width="0dp"
android:layout_height="64dp"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16dp"
android:backgroundTint="#color/colorPrimaryText"
android:digits="0123456789"
android:inputType="number"
android:text="#={ viewModel.amount }"
android:textColor="#color/colorPrimaryText"
android:textSize="32sp"
app:backgroundTint="#color/colorPrimaryText"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
>
<requestFocus />
<sample.example.views.FixedCursorEditText>
In fragment,
var currentValue = viewModel.parse(viewModel.amount.value) ?: 0
currentValue += amount
viewModel.amount.value = currentValue.toString()
enterAmountEditText.text?.length?.let { enterAmountEditText.setSelection(it) }
Can you help me for solving this issue.
Error log,
IndexOutOfBoundsException: offset(3) should be less than line limit(0)
at sample.example.views.FixedCursorEditText.onSelectionChanged(FixedCursorEditText.kt:15)
at sample.example.databinding.FragmentAmountBindingImpl.executeBindings(FragmentAmountBindingImpl.java:291)

How to create View class object in Kotlin? What is AttributeSet? How to create it for a view?

In Android, I have two class files, MainActivity and CanV.
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
}
CanV.kt, This is a View class.
class CanV(context: Context, attributeSet: AttributeSet): View(context){ ... }
CanV view in activity_main.xml
<com.app.app_name.CanV
android:id="#+id/cans"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="60dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="1.0">
</com.app.app_name.CanV>
Now I want to create CanV class object in MainActivity.
I came to try:
val c: CanV = CanV(this, ?)
But, I don't know the AttributeSet parameter value. How do I create and pass the AttributeSet of CanV view?
If you want to be able to create instances of CanV from both XML and Java/Kotlin, you should provide two constructors:
class CanV : View {
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
...
}
The first can be used from Kotlin (val v: CanV = CanV(this)), and the second is used automatically when inflating from XML.

Categories

Resources