Kotlin doOnLayout not setting visibility.GONE - android

I have a custom ConstraintLayout Myword. when I set the visibility of myword1 to GONE inside kotlin fun doOnLayout, it becomes invisible but myword2 doesn't move down.
But if I set its visibility to GONE in XML or outside doOnLayout, it works as intended.
<learnprogramming.academy.relaf.Myword
android:id="#+id/myword1"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<learnprogramming.academy.relaf.Myword
android:id="#+id/myword2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="#id/myword1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
Source code:
lateinit var bannerword : MutableList<Myword>
lateinit var swippon : ConstraintLayout
fun updatewords{
swippon.doOnLayout {
if (swippon.height>1000) bannerword[0].visibility = View.GONE}
class PhrasesFragment: Fragment() {
companion object {
fun newInstance(): PhrasesFragment {
return PhrasesFragment()
}
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?): View? {
return inflater.inflate(R.layout.inglesa_screen, container, false) }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bannerword=mutableListOf(myword1,myword2)
swippon=parent
updatewords()
}
}
doOnLayout function when layout is laid out calculates parent Layout height and eventually removes myword1. I actually solved changing doOnLayout with Handler(Looper.getMainLooper()).post{} but is wrong with doOnLayout? How should i have used it in the correct way?

Related

cant get any component in fragment class (kotlin)

i manually created a fragment. but cant declare a component like web view or button. when i paste and edit "val webview: WebView ..." there is error "Fragment(R.layout.fragment_htmlviewer)" too. i dont know how to do, when i create from android studio, it looks like very complicated. so i watched a video and this is more easy but cant declare components. im very beginner so help me please... my code:
fragment_htmlviewer.xml
<WebView
android:id="#+id/htmlViewer"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/floating_action_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:contentDescription="#string/fabdescription"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:srcCompat="#drawable/ic_left_arrow_icon" />
HtmlViewerFragment.kt
class HtmlViewerFragment : Fragment(R.layout.fragment_htmlviewer) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return super.onCreateView(inflater, container, savedInstanceState)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
val webview: WebView = getView()!!.findViewById<View>(R.id.htmlViewer) as WebView
}
}
I recommend you to use the binding structure, it is a more preferred structure today.
build.gradle(module)
buildFeatures {
viewBinding true
dataBinding true
}
HtmlViewerFragment
private var _binding: FragmentHtmlViewerBinding? = null
private val binding
get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentHtmlViewerBinding.inflate(inflater, container, false)
//.. this is write code
binding.apply{
//eg:
htmlViewer.setOnClickListener{
}
}
return binding.root
}
override fun onStart() {
super.onStart()
htmlViewer = requireView().findViewById(R.id.htmlViewer) as WebView
htmlViewer!!.loadUrl("https://www.google.com")
}
this is solution.
htmlViewer = requireView().findViewById(R.id.htmlViewer) as WebView
fixed

creating bottom sheet dialog with ConstraintLayout

I am trying to create modal bottom sheet dialog to show a list of items which will be scrollable.
dialog_bottom_example.xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/white"
xmlns:app="http://schemas.android.com/apk/res-auto">
<LinearLayout
android:id="#+id/container"
android:layout_width="0dp"
android:layout_height="0dp"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
Items in LinearLayout is getting added dynamically based on list size as below:
ExampleDialogBottom:
class ExampleDialogBottom: BottomSheetDialogFragment() {
private lateinit var binding: DialogExampleBinding
private var skusItems = mutableListOf<SkuItem>();
companion object {
internal const val TAG = "ExampleDialogBottom"
#JvmStatic
fun newInstance(nonEligibleErxItem: NonEligibleErxItem) = NonEligibleBottomDialog
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = DialogExampleBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
configureSkuItems()
}
private fun configureSkuItems() {
if (!skuItems.isNullOrEmpty()) {
val inflater = LayoutInflater.from(context)
for (sku in skuItems) {
val skuItemView = SingleSkuItemViewBinding.inflate(inflater, null, false)
skuItemView.skuImage.setImageWithVisibility(sku.imageUrl)
skuItemView.skuTitle.setTextWithVisibility(sku.name)
binding.container.addView(skuItemView.root)
}
binding.container.visibility = View.VISIBLE
} else {
binding.container.visibility = View.GONE
}
}
ExmpaleActivity:
button.setOnClickListener {
ExampleDialogBottom.newInstance().show(getSupportFragmentManager(),
ExampleDialogBottom.TAG);
}
However, when I click on button, a transparent dialog shows up, no content is showing.
When I removed match-contraint and changed it match-parent or wrap-content, it's working as expected.
It would be great if someone could help? Thanks in advance.

Android Buttons in Fragments to not get triggered

Why do buttons in Fragments to not get triggered? I've already spent about 5 hours on this, but no onClick / onFocusListener will trigger
Edit: Code
So this Fragment(s) is on a ViewPager2 on my MainActivity and
it just wont trigger any Callback Methods. I have also tried to but those onClick initializations everywhere
Fragment:
class SearchFragment : Fragment() {
private lateinit var searchBinding: FragmentSearchBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
searchBinding = FragmentSearchBinding.inflate(layoutInflater)
interface OnSearch {
fun onArticleSelected(position: Int)
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
// Inflate the layout for this fragment
return inflater.inflate(R.layout.fragment_search, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
var test = activity?.findViewById<TabLayout>(R.id.tab_layout)
searchBinding.searchBar.setOnFocusChangeListener{view, hasFocus ->
if (hasFocus){
if (test != null) {
test.isVisible = false
}
Log.d("SearchFragment", "onFocus")
}else{
if (test != null) {
test.isVisible = true
}
}
}
}
}
XML:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.main.search.SearchFragment"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.button.MaterialButton
android:id="#+id/testButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
<EditText
android:id="#+id/search_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:hint="Search"
android:focusedByDefault="true"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/searchRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</FrameLayout>
Try something like this
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?) {
super.onCreateView(view, savedInstanceState)
val binding = FragmentSearchBinding.inflate(inflater, container, false);
val view = binding.root
// Set binding
return view;
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
view.findViewById(R.id.searchBar).setOnFocusChangeListener { view, hasFocus ->
}
}

ViewPager is not working correctly after device rotation

After rotation, one old page is displayed, followed by new pages.
Before rotation 1.
After rotation 2.
Layout with ViewPager:
<RelativeLayout ...
<androidx.viewpager.widget.ViewPager
android:id="#+id/pager"
android:overScrollMode="never"
android:layout_marginStart="16dp"
android:layout_marginTop="20dp"
android:layout_marginEnd="16dp"
android:layout_marginBottom="10dp"
android:layout_height="match_parent"
android:layout_width="match_parent">
</RelativeLayout>
Fragment with this layout:
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
val view = inflater.inflate(layoutId(), container, false)
view.findViewById<ViewPager>(R.id.pager).adapter = TextPagerAdapter(activity!!.supportFragmentManager, listOf())
return view
}
TextPagerAdapter:
override fun getItem(position: Int): Fragment = PageFragment.newInstance("sssssss ssss $position")
override fun getCount() = 5//pageText.size
}
PageFragment:
override fun onCreateView(inflater: LayoutInflater,container: ViewGroup?,savedInstanceState: Bundle?): View? {
val view = inflater.inflate(layoutId(), container, false)
view.findViewById<TextView>(R.id.page_content_textView).text = arguments!!.getCharSequence(PAGE_TEXT)
return view
}
I forgot to check if the content fragment is already created.
The solution is to check if the savedInstanceState == null. And create new fragment if that condition is true.
In MyActivity:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if(savedInstanceState == null) this.supportFragmentManager.beginTransaction()
.add(containerViewId, CollectionDemoFragment()).commit()
}

Fragment does not respond to onClick event on custom views

I have MainFragment, and inside my fragment I added my CustomButton custom view. And, onViewCreated, I setOnClickListener to the view. But, the fragmenet does not respond to the click.
ButtonWithImage
class ButtonWithImage(context: Context, attrs: AttributeSet) : LinearLayout(context, attrs) {
init {
val view = View.inflate(context, R.layout.item_custom_btn, this)
val attributes = context.obtainStyledAttributes(attrs, R.styleable.BadgeIcon)
view.btn_image.setImageDrawable(attributes.getDrawable(R.styleable.BadgeIcon_image))
view.btn_text.setText(attributes.getResourceId(R.styleable.BadgeIcon_text, 0))
attributes.recycle()
}
}
fragment_main.xml
...
<LinearLayout
android:layout_width="match_parent"
android:layout_height="50dp"
android:orientation="horizontal">
<corn.transaction.custom_view.ButtonWithImage
android:id="#+id/my_cards"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
app:image="#drawable/ic_my_cards"
app:text="#string/btn_text_my_cards"/>
<corn.transaction.custom_view.ButtonWithImage
android:id="#+id/transactions"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
app:image="#drawable/ic_transactions"
app:text="#string/btn_text_transactions"/>
</LinearLayout>
...
MainFragment.kt
class MainFragment : Fragment() {
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_main, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
my_cards.setOnClickListener { logMessage("loooooog") }
}
I think you can fix it by:
Adding focusable=false and clickable=false to your btn_image and btn_text
Adding focusable=true and clickable=true to your root view of this custom layout (also give it id -> lets say custom_button_container)
call my_cards.findViewById<LinearLayout>(R.id.custom_button_container).setOnClickListener { logMessage("loooooog") }
The optimal solution is making all views in XML clickable and focusable false.
You can use the following code:
my_cards.setOnClickListener { logMessage("loooooog") }
As all views are not clickable and focusable, they do ignore clicks, but not the custom view itself.

Categories

Resources