I have a basic activity with an AutoCompleteTextView. I am trying to use it as a Exposed Dropdown Menu [1] to pick from a list of options, as per the Material Design documentation. [2]
However, when I click the TextInputLayout, the dropdown does not appear - although the arrow does flip.
What have I missed?
MainActivity.kt:
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(R.layout.activity_main) // edit, the mistake is here - see my answer.
val items = listOf("Option 1", "Option 2", "Option 3", "Option 4")
val adapter = ArrayAdapter(this, R.layout.list_item, items)
binding.positionPickerField.setAdapter(adapter)
}
}
activity_main.xml:
<?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.google.android.material.textfield.TextInputLayout
android:id="#+id/menu"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox.ExposedDropdownMenu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:hint="enter your starting position"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent">
<AutoCompleteTextView
android:id="#+id/position_picker_field"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="none" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
list_item.xml:
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:padding="16dp"
android:textAppearance="?attr/textAppearanceSubtitle1" />
[1] https://material.io/components/menus#exposed-dropdown-menu
[2] https://material.io/components/menus/android#exposed-dropdown-menus
You have not added threshold value in the AutoCompleteTextView.
Just add the method -
binding.positionPickerField.setThreshold(1); // will start working from first character
I was not setting up the viewbinding correctly.
The fix was in onCreate():
binding = ActivityMainBinding.inflate(layoutInflater)
val view = binding.root
setContentView(view)
https://developer.android.com/topic/libraries/view-binding#activities
Related
I realise this question has been asked previously but the answers provided haven't helped me out. I cannot see what is going wrong here.
I have an activity, in which I display a bottom sheet, the bottom sheet has a title and a recyclerview. The recycler view is only displaying one item, regardless of how many are passed to the adapter. It is possible to scroll through the items but only one at any time is visible.
Here is my activity xml:
<?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"
tools:context=".features.order.automatedcheckout.view.AutomatedCheckoutQRCodeActivity"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/scanBarcodeInstruction"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginTop="50dp"
android:text="Scan the barcode to get started"
android:textSize="18sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.constraintlayout.widget.Guideline
android:id="#+id/loadingGuideline"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.5"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ProgressBar
android:id="#+id/progressIndicator"
app:layout_constraintBottom_toTopOf="#+id/loadingGuideline"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/scanBarcodeInstruction"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<androidx.appcompat.widget.AppCompatImageView
android:id="#+id/qrcodeImageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#+id/scanBarcodeInstruction"/>
<TextView
android:id="#+id/tenderName"
app:layout_constraintTop_toBottomOf="#+id/qrcodeImageView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="#+id/changeTenderButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="10dp"
android:visibility="gone"
android:layout_marginBottom="20dp"
android:layout_marginRight="20dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
android:text = "Change Tender"/>
</androidx.constraintlayout.widget.ConstraintLayout>
and here is my bottom sheet fragment xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.LinearLayoutCompat
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bottomSheetLayout"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tenderTitle"
android:layout_marginTop="20dp"
android:layout_marginStart="20dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SELECT"/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/tenderList"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
</androidx.appcompat.widget.LinearLayoutCompat>
my bottom sheet fragment:
class TenderBottomSheetFragment : BottomSheetDialogFragment() {
private var _binding: FragmentTenderBottomSheetBinding? = null
private val binding get() = _binding!!
private lateinit var onTenderClicks:(tenderDetails: Pair<Int?, String?>) -> Unit
lateinit var adapter: TenderAdapter
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
_binding = FragmentTenderBottomSheetBinding.inflate(inflater, container, false)
adapter = TenderAdapter (
arguments?.parcelableArrayList(ARG_TENDERS)!!,
onTenderClicks
)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
val layoutManager = LinearLayoutManager(requireContext())
binding.tenderList.layoutManager = layoutManager
binding.tenderList.addItemDecoration(DividerItemDecoration(requireContext(), layoutManager.orientation))
binding.tenderList.adapter = adapter
}
companion object {
fun newInstance(
campusTenders: List<TenderKt>,
onTenderClick: (tenderDetails: Pair<Int?, String?>) -> Unit
): TenderBottomSheetFragment {
val tenderDialogFragment = TenderBottomSheetFragment()
tenderDialogFragment.onTenderClicks = onTenderClick
tenderDialogFragment.apply {
arguments = Bundle().apply {
putParcelableArrayList(ARG_TENDERS, ArrayList(tenders))
}
}
return tenderDialogFragment
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}
I'm sure this is something really simple but unfortunately right now, I'm not seeing it. If anyone could help I would really appreciate it.
UPDATE
Here is the recycler item layout:
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
xmlns:app="http://schemas.android.com/apk/res-auto">
<TextView
android:id="#+id/campus_tender_name"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text ="Flex Account"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</androidx.constraintlayout.widget.ConstraintLayout>
I have now updated that to:
<TextView
android:id="#+id/campus_tender_name"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:padding="10dp"
tools:text = "Flex Account"
android:textSize="16sp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
and that works fine. So it was the constraint layout in the recycler view item
I want my Snackbar to start the animation from the view in red and not at the bottom of the screen as by default, I wanted to give the feeling that the snackbar is appearing behind this view, unfortunately, I don't get good results.
Note: The project I'm working on is not using coordinatorlayout, but I can use.
Activity
class MainActivity : AppCompatActivity() {
private lateinit var snackbar : Snackbar
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
with(binding) {
val view = root
setContentView(view)
snackbar = Snackbar.make(this#MainActivity, view, "Teste", Snackbar.LENGTH_SHORT)
snackbar.anchorView = textText
snackbar.animationMode = BaseTransientBottomBar.ANIMATION_MODE_SLIDE
btnSnackbar.setOnClickListener {
snackbar.show()
}
}
}
}
Layout
<?xml version="1.0" encoding="utf-8"?>
<layout 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">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="#+id/btn_snackbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:text="#string/snackbar" />
<TextView
android:id="#+id/text_text"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="#color/design_default_color_error"
android:gravity="center"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
com.google.android.material:material:1.7.0
I tried using elevation to override the snackbar and it doesn't work either.
My project has a class called Welcome.kt
class Welcome : AppCompatActivity() {
private lateinit var vb: ActivityWelcomesBinding
fun runDemo(v: View) {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vb = ActivityRegisterBinding.inflate(layoutInflater)
setContentView(vb.root)
}
}
In the layout of this class (Welcome.kt) I have the usual views and also an included layout
<?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">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background"
tools:context=".Welcome">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
...
...
<include layout="#layout/layout_buttons" />
...
...
</FrameLayout>
</ScrollView>
</FrameLayout>
And this is the included layout (layout_buttons), a series of buttons that have the onClick attribute, which should execute the "startDemo" function that is in the activity Welcome.kt
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
...
...
<Button
android:id="#+id/btn_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:onClick="runDemo"
android:text="#string/text1" />
<Button
android:id="#+id/btn_2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:onClick="runDemo"
android:text="#string/text2" />
<Button
android:id="#+id/btn_3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="10dp"
android:onClick="runDemo"
android:text="#string/text3" />
</LinearLayout>
Since the buttons are inside an included layout, I can't find a way to get them to call the "runDemo" function of the Welcome.kt activity.
I have searched for information but nothing I have found has solved my problem.
Thanks in advance
you should give your include tag an id for example
<include id="#+id/buttonsLayout"
layout="#layout/layout_buttons" />
After this you can use it like this :
class Welcome : AppCompatActivity() {
private lateinit var vb: ActivityWelcomesBinding
fun runDemo(v: View) {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
vb = ActivityRegisterBinding.inflate(layoutInflater)
setContentView(vb.root)
vb.buttonsLayout.yourBtnId
}
}
if you want still to use onClick in the xml then you should use data binding not view binding
I want to add dynamic inputs using one fragment, this fragment includes one input and everytime that I click the button the fragment will be insert in the activity layout,
actually I can do it but when I click the button for the second time it's add the fragment input but is overlaps with de old fragment input
inputFragment.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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=".fragments.InputFragment">
<com.google.android.material.textfield.TextInputLayout
android:id="#+id/contInput"
style="#style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="Usuario"
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">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/input"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</com.google.android.material.textfield.TextInputLayout>
</RelativeLayout>
activity.xml
<?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:id="#+id/cont"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".controller.Activity">
<Button
android:id="#+id/btn"
android:layout_width="324dp"
android:layout_height="81dp"
android:layout_marginTop="82dp"
android:text="Insert input"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.494"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/fragment_container"
tools:ignore="MissingConstraints" />
<FrameLayout
android:id="#+id/fragment_container"
android:layout_width="414dp"
android:layout_height="289dp"
android:layout_marginTop="36dp"
app:layout_constraintTop_toTopOf="parent"
tools:layout_editor_absoluteX="-2dp" />
</androidx.constraintlayout.widget.ConstraintLayout >
activity.kt
class Activity : AppCompatActivity(){
private var myList = ArrayList<InputFragment>()
private lateinit var binding: ActivityBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val binding = ActivityBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.btn.setOnClickListener {
val fragmentManager = supportFragmentManager
val fragmentTransaction = fragmentManager.beginTransaction()
val nuevoFragmento = InputFragment()
fragmentTransaction.add (R.id.fragment_container, nuevoFragmento)
fragmentTransaction.addToBackStack(null)
fragmentTransaction.commit()
}
}
}
This is not achievable with fragments, when a new fragment is added to the fragment container, the old will not be visible. I will suggest using something that allows list based views such as the Recyclerview. But for a simple small number of inputs, manually hiding inputs and toggling the visibility is the simplest solution
I am having significant difficulty in this and have tried everything imaginable. I am trying to make a card view draggable/swipeable vertically. All I want to accomplish is for the user to be able to swipe/drag the card view up and down. Please see attached photos-this is what I am trying to accomplish.
activity_main
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout 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"
android:background="#color/colorPrimary"
tools:context=".MainActivity">
<androidx.cardview.widget.CardView
android:id="#+id/cardviewbackground"
android:layout_width="match_parent"
android:layout_height="350dp"
android:layout_marginTop="-175dp"
app:cardBackgroundColor="#color/white"
app:cardCornerRadius="18dp"
android:layout_marginStart="40dp"
android:layout_marginEnd="40dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
</androidx.coordinatorlayout.widget.CoordinatorLayout>
MainActicity.kt
class MainActivity<T> : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
val listener = View.OnDragListener { view, event ->
when(event.action) {
DragEvent.ACTION_DRAG_STARTED -> {
event.clipDescription.hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN)
}
else -> false
}
}
}