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)
}
}
Related
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.
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>
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)
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.
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