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

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.

Related

Button is visiable but TextView / ImageView is not visiable in custom compound view

I am trying to create compound CardView using two CardView and extended Framelayout. If I place a button inside custom CardView as a child the button is visible but if i place TextView or ImageView as a child the widget (TextView or ImageView) is not visible.
Screenshot of Custom widget with TextView as child
Screenshot of Custom Widget with Button as child
kotlin code
import android.content.Context
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
import android.widget.TextView
import androidx.cardview.widget.CardView
class CompoundCardView : FrameLayout{
private var childView:CardView? = null
private var heading:String? = null
set(value) {
field = value
invalidate()
requestLayout()
}
get() {
return field
}
constructor(context: Context) : super(context) {
init(context, null)
}
constructor(context: Context, attrs: AttributeSet) : super(context, attrs) {
init(context, attrs)
}
constructor(context: Context,
attrs: AttributeSet,
defStyle: Int) : super(context, attrs, defStyle) {
init(context, attrs)
}
private fun init(context: Context, attrs: AttributeSet?) {
context.theme.obtainStyledAttributes(attrs,R.styleable.CompoundCardView,0,0).apply {
try {
heading = getString(R.styleable.CompoundCardView_heading)
}finally {
recycle()
}
}
val inflater = context.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater
inflater.inflate(R.layout.compaund_card_view,this,true)
childView = findViewById(R.id.holder)
val header:TextView = findViewById(R.id.header)
header.text = heading
}
override fun addView(child: View?) {
invalidate()
childView?.addView(child,0, child?.layoutParams)
requestLayout()
}
}
xml layout
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.card.MaterialCardView
android:id="#+id/holder"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="20dp"
android:background="#00FFFFFF"
app:cardCornerRadius="8dp"
app:strokeColor="#2196F3"
app:strokeWidth="1dp" />
<com.google.android.material.card.MaterialCardView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:backgroundTint="#FFC107"
app:cardCornerRadius="8dp"
app:contentPaddingBottom="4dp"
app:contentPaddingLeft="8dp"
app:contentPaddingRight="8dp"
app:contentPaddingTop="4dp"
app:strokeColor="#2196F3"
app:strokeWidth="1dp">
<TextView
android:id="#+id/header"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="#string/heading"
android:textSize="20sp" />
</com.google.android.material.card.MaterialCardView>
</merge>

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)

WebRTC VideoView incorrect view for local peer

I am writing a WebRTC solution and having an issue in Local View while using back camera (Wrong Rotation / Incorrect View)
<com.src.webrtc.android.VideoView
android:id="#+id/main_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
Local View (Incorrect view)
Remote View (Correct View : while viewing as a Remote user)
I was facing the same issue while working on the webRTC. I fixed it by setting the method setMirror(false).
here's some code:
call_activity.xml
<org.webrtc.SurfaceViewRenderer
android:id="#+id/fullscreen_video_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<org.webrtc.SurfaceViewRenderer
android:id="#+id/pip_video_view"
android:layout_height="144dp"
android:layout_width="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"/>
in CallActivity.java
SurfaceViewRenderer fullscreenRenderer =
findViewById(R.id.fullscreen_video_view);
fullscreenRenderer.init(eglBase.getEglBaseContext(), null);
fullscreenRenderer.setScalingType(ScalingType.SCALE_ASPECT_FILL);
fullscreenRenderer.setEnableHardwareScaler(false /* enabled */);
//this code is used for rotation
fullscreenRenderer.setMirror(false);
I am using implementation 'org.webrtc:google-webrtc:1.0.28513'
Update:
what you can do in VideoView.kt is:
class VideoView : SurfaceViewRenderer{
constructor(context: Context) : super(context)
constructor(context: Context, attrs: android.util.AttributeSet?) : super(context, attrs)
fun init(rendererEvents: RendererCommon.RendererEvents?) {
super.init(EglBaseProvider.getEglBase(this).eglBaseContext, rendererEvents)
setMirror(false)
}
override fun release() {
super.release()
EglBaseProvider.release(this)
}
override fun setMirror(mirror: Boolean) {
super.setMirror(mirror)
}
}
or
class VideoView : SurfaceViewRenderer{
constructor(context: Context) : super(context)
constructor(context: Context, attrs: android.util.AttributeSet?) : super(context, attrs)
fun init(rendererEvents: RendererCommon.RendererEvents?) {
super.init(EglBaseProvider.getEglBase(this).eglBaseContext, rendererEvents)
super.setMirror(false)
}
override fun release() {
super.release()
EglBaseProvider.release(this)
}
}

Android Custom View: How to set click listener on individual widgets

This is my layout file for the custom view
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="?actionBarSize">
<ImageView
android:id="#+id/ivMenu"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="#drawable/ripple"
android:clickable="true"
android:padding="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_menu_gray" />
<ImageView
android:id="#+id/ivDrawer"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:background="#drawable/ripple"
android:clickable="true"
android:padding="12dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/ic_drawer_gray" />
</android.support.constraint.ConstraintLayout>
</LinearLayout>
There are two ImageViews that I need to set click listeners on. I have created a class extending LinearLayout, since it is the root element in my layout.
I don't know how to set click listeners on individual items in the layout.
here is my class file for the layout
class WolfBottomAppBar : LinearLayout {
constructor(context: Context) : super(context) {
init(context)
}
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {
init(context)
}
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
init(context)
}
private fun init(context: Context) {
((context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) as LayoutInflater).inflate(R.layout.wolf_bottom_app_bar, this)
}
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
if (event.action == MotionEvent.ACTION_UP) {
/*
* I can set click listener for the whole view here, but not on individual items
*/
}
return super.dispatchTouchEvent(event)
}
override fun dispatchKeyEvent(event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_UP && (event.keyCode == KeyEvent.KEYCODE_DPAD_CENTER || event.keyCode == KeyEvent.KEYCODE_ENTER)) {
}
return super.dispatchKeyEvent(event)
}
}
put
fun setMenuListener(listener : View.OnClickListener) {
findViewById<ImageView>(R.id.ivMenu).setOnClickListener(listener)
}
fun setDrawerListener(listener : View.OnClickListener) {
findViewById<ImageView>(R.id.ivDrawer).setOnClickListener(listener)
}
into you custom view class.
You can just access the ImageViews with their ids. You need to add the inflated view to your root (=WolfBottomAppBar); e.g. in the init method:
private fun init(context: Context) {
((context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)) as LayoutInflater).inflate(R.layout.wolf_bottom_app_bar, this, true)
ivMenu.setOnClickListener { Log.d(TAG, "Image ivMenu clicked!") }
}
Don't forget to import the synthetic Kotlin package for the layout file and to add android:focusable="true" to the two ImageViews xml

Categories

Resources