I have a form in my app which requires the user to enter his/her height and weight. There are two radio buttons of imperial and metric units. I want to show one height edittext (meters) when the user chooses imperial in the radiogroup and two edittexts (feet + inches) for metric. How can I implement this?
Use both edittexts (in meters) and (in feet-inches) with one have android:visibility="gone"
when user selects the metric hide the another one edittext and show edittexts (feet + inches) and when user selects the imperial then hide the other and show height edittext (meters)...
Try with the following code working fine.
//activity.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingHorizontal="15dp">
<RadioGroup
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/radioGroup1">
<RadioButton
android:id="#+id/imperial"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Imperial" />
<RadioButton
android:id="#+id/metric"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Metric" />
</RadioGroup>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:orientation="vertical">
<EditText
android:id="#+id/height_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:hint="Input height" />
<EditText
android:id="#+id/feet_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginTop="20dp"
android:hint="Input Feet" />
<EditText
android:id="#+id/inches_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone"
android:layout_marginTop="10dp"
android:hint="Input Inches" />
</LinearLayout>
</LinearLayout>
//activity code
class TestActivity : AppCompatActivity() {
private lateinit var heightEdt: EditText
private lateinit var feetEdt: EditText
private lateinit var inchesEdt: EditText
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test)
heightEdt = findViewById(R.id.height_et)
feetEdt = findViewById(R.id.feet_et)
inchesEdt = findViewById(R.id.inches_et)
val rg = findViewById<View>(R.id.radioGroup1) as RadioGroup
rg.setOnCheckedChangeListener { group, checkedId ->
when (checkedId) {
R.id.imperial -> {
heightEdt.isVisible = true
feetEdt.isVisible = false
inchesEdt.isVisible = false
}
R.id.metric -> {
heightEdt.isVisible = false
feetEdt.isVisible = true
inchesEdt.isVisible = true
}
}
}
}
}
Related
I am currently working on a currency converter in Android Studio. The error that I faced was that if I were to put the current input, which is "US Dollars" in the editTextCurrency box (enter currency box) and click on the convert button, the application would crash. However, if I were to put a wrong input for example "US" in the editTextCurrency(Enter currency box), the application did not crash but print out the message on the TextView which is intended to. I am not sure how I should solve this issue, I hope someone could point out the error that I made. Thanks.
kt file
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AppCompatActivity
import edu.singaporetech.travelapp.databinding.ActivityCurrencyConverterBinding
/**
* Activity that displays UI to convert currency
*/
class CurrencyConverterActivity : AppCompatActivity() {
private lateinit var binding: ActivityCurrencyConverterBinding
val TAG: String = "CurrencyConverterActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityCurrencyConverterBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.editTextCurrency
binding.editTextRate
binding.editTextSingDollar
binding.currencyTextView
binding.rateTextView
binding.singdollarTextView
binding.convertCurrencyButton
binding.currencyOutputTextView
binding.convertCurrencyButton.setOnClickListener {
if (binding.editTextCurrency.text.toString() == "US Dollars"){
binding.currencyOutputTextView.visibility = View.VISIBLE
var currencyResult = calculateRate(binding.editTextSingDollar.toString().toFloat(), binding.editTextRate.toString().toFloat())
binding.currencyOutputTextView.text = getString(R.string.display_currency, binding.editTextSingDollar.toString().toFloat(), currencyResult)
}else{
binding.currencyOutputTextView.text = getString(R.string.invalid_currency)
binding.currencyOutputTextView.visibility = View.VISIBLE
}
}
}
}
private fun calculateRate(value: Float, exchangeRate: Float): Float {
// TODO What's the formula you need?
return value * exchangeRate
}
xml file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/currencyTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/currency"
android:textSize="24sp" />
<EditText
android:id="#+id/editTextCurrency"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/input_currency"
android:inputType="textPersonName"
android:textSize="20sp" />
<TextView
android:id="#+id/rateTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/rate"
android:textSize="24sp" />
<EditText
android:id="#+id/editTextRate"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/input_rate"
android:inputType="numberDecimal"
android:minHeight="48dp"
android:textSize="20sp" />
<TextView
android:id="#+id/singdollarTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/singapore_dollars"
android:textSize="24sp" />
<EditText
android:id="#+id/editTextSingDollar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ems="10"
android:hint="#string/input_singapore_dollars"
android:inputType="numberDecimal"
android:textSize="20sp" />
<Button
android:id="#+id/convertCurrencyButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/convert" />
<TextView
android:id="#+id/currencyOutputTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="TextView"
android:textAlignment="center"
android:visibility="invisible" />
</LinearLayout>
string.xml
<resources>
<string name="invalid_currency">Invalid Currency</string>
<string name="display_currency">%.1f SGD is %.1f Singapore Dollars</string>
</resources>
Changes
binding.convertCurrencyButton.setOnClickListener {
if (binding.editTextCurrency.text.toString() == "US Dollars"){
binding.currencyOutputTextView.visibility = View.VISIBLE
var currencyResult = calculateRate(binding.editTextSingDollar.text.toString().toFloat(), binding.editTextRate.text.toString().toFloat())
binding.currencyOutputTextView.text = getString(R.string.display_currency, binding.editTextSingDollar.text.toString().toFloat(), currencyResult)
}else{
binding.currencyOutputTextView.text = getString(R.string.invalid_currency)
binding.currencyOutputTextView.visibility = View.VISIBLE
}
}
Error message that I got from logcat
java.lang.NumberFormatException: For input string: "androidx.appcompat.widget.AppCompatEditText
This code is where I am creating Alert dialog. whenever I press ok it crashes .password_dialog has 1 editText and 2 buttons.
private fun passwordCheck(position: Int){
val view=LayoutInflater.from(requireContext()).inflate(R.layout.password_dialog,null,false)
val builder=AlertDialog.Builder(requireContext())
with(builder){
setTitle("Enter your Pin")
setPositiveButton("Ok"){dialog,which->
if(pin_text.text.toString()=="1234"){
Toast.makeText(requireContext(),"Right Pin",Toast.LENGTH_LONG).show()
}
else{
pin_text.requestFocus()
pin_text.error="Incorrect"
}
}
setCancelable(false)
setNegativeButton("Cancel"){dialog,which->
dialog.dismiss()
}
setView(view)
show()
}
}
Create a layout with the view, for example, an EditText that only accepts numbers and two buttons, accept or cancel.
Then inflate the view
val view = LayoutInflater.from(context).inflate(R.id.layout, null, false)
Then with that view you get the reference of the buttons and the EditText with
val button = view.findViewById<Button>(R.id.button)
//I'm not going to declare all views, but assuming you already did.
button.setOnClickListener {
if (editText.text.toString.toInt() == 1234 //your correct pin) {
//CORRECT PIN TODO
} else {
editText.requestFocus()
editText.error = "Incorrect pin"
}
}
Then create the dialog and add that view to it
AlertDialog.Builder(context).setView(view).create().show()
Do not add the validation methods in the accept button of the dialog.
They are what are declared as follows.
setPositiveButton("Accept"){diálog, which -> }
This is the way by which you can create your own dialog with custom layout.
Implement your PIN UI in custom_dialog.xml and your logic in Kotlin file.
Here is example how you can create custom Dialog.
custom_dialog.xml
<androidx.constraintlayout.widget.ConstraintLayout 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:background="#424242">
<TextView
android:id="#+id/popup_dialog"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16sp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16sp"
android:layout_marginBottom="10dp"
android:text="Custom Dialog Box"
android:textColor="#color/white"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<LinearLayout
android:id="#+id/linearLayoutOpt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="16sp"
android:layout_marginTop="16dp"
android:layout_marginEnd="16sp"
android:layout_marginBottom="10dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/popup_dialog">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:orientation="horizontal">
<TextView
android:id="#+id/no_opt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingTop="8dp"
android:paddingRight="8dp"
android:paddingBottom="18dp"
android:text="No"
android:textStyle="bold"
android:textAllCaps="false"
android:textColor="#color/white" />
<Space
android:layout_width="32sp"
android:layout_height="12sp" />
<TextView
android:id="#+id/yes_opt"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:gravity="center_vertical"
android:paddingLeft="8dp"
android:paddingTop="8dp"
android:paddingRight="8dp"
android:paddingBottom="18dp"
android:text="Yes"
android:textStyle="bold"
android:textAllCaps="false"
android:textColor="#color/white" />
</LinearLayout>
</LinearLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
showDialog()
}
private fun showDialog() {
val customDialog = Dialog(this)
customDialog.setContentView(R.layout.custom_dialog)
customDialog.window?.setLayout(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT
)
val yesBtn = customDialog.findViewById(R.id.yes_opt) as TextView
val noBtn = customDialog.findViewById(R.id.no_opt) as TextView
yesBtn.setOnClickListener {
//Do something here YOUR LOGIC
customDialog.dismiss()
}
noBtn.setOnClickListener {
customDialog.dismiss()
}
customDialog.show()
}
}
example app screenshot
I am pretty much a beginner in app development. I am creating a GPA calculator. I was able to create a button that would create a new EditText view for each time it was tapped. but I don't know how can get the values from those EditTexts separately so I can use them to calculate GPA. I looked up every similar question here and on the internet in general, but none of them helped me. Here is my code:
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">
<LinearLayout
android:id="#+id/layout_list"
android:layout_width="match_parent"
android:layout_height="500dp"
android:orientation="vertical"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<Button
android:id="#+id/add_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="20dp"
android:drawableRight="#drawable/ic_baseline_add_24"
android:text="Add"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/textView" />
</LinearLayout>
<Button
android:id="#+id/calculate_button"
android:layout_width="180dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:text="Calculate"
app:layout_constraintLeft_toLeftOf="#id/layout_list"
app:layout_constraintTop_toBottomOf="#id/layout_list" />
<TextView
android:id="#+id/result"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginLeft="20dp"
android:layout_marginTop="13dp"
android:hint="GPA:0.0"
android:textSize="20dp"
app:layout_constraintStart_toEndOf="#id/calculate_button"
app:layout_constraintTop_toBottomOf="#id/layout_list"
tools:text="GPA:0.0" />
</androidx.constraintlayout.widget.ConstraintLayout>
new_layout.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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<EditText
android:id="#+id/gpa_points"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="#drawable/custom_input"
android:hint=" GPA point"
android:inputType="number"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<EditText
android:id="#+id/credit_points"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_margin="20dp"
android:background="#drawable/custom_input"
android:hint=" ETCS"
android:inputType="number"
app:layout_constraintStart_toEndOf="#+id/gpa_points"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/close"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_marginLeft="20dp"
android:layout_marginTop="18dp"
android:background="#drawable/ic_baseline_close_24"
app:layout_constraintLeft_toRightOf="#id/credit_points"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity.kt
package com.example.gpacalculator
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.View
import android.widget.Button
import android.widget.LinearLayout
class MainActivity : AppCompatActivity() {
private var layout: LinearLayout? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
layout = findViewById(R.id.layout_list)
val addButton: Button = findViewById(R.id.add_button)
addButton.setOnClickListener { addView() }
val calculateButton: Button = findViewById(R.id.calculate_button)
calculateButton.setOnClickListener { calculate() }
}
private fun addView() {
val gpaView: View = layoutInflater.inflate(R.layout.new_layout, null, false)
layout?.addView(gpaView)
}
i added this function to my code
fun calculate(){
var total = 0.0
var etcs = 0.0
layout.children.forEach { newLayout ->
// Find the gpa_points EditText in the child layout
val gpaPointsEditText = newLayout.findViewById<EditText>(R.id.gpa_points) as? EditText
val creditsEditText = newLayout.findViewById<EditText>(R.id.credit_points) as? EditText
// Parse the text to be able to perform calculations
val gpaPoints = gpaPointsEditText?.text.toString().toDouble()
val credits = creditsEditText?.text.toString().toDouble()
total+=gpaPoints*credits
etcs+=credits
}
var gpa = total/etcs
val result:TextView = findViewById(R.id.result)
result.text=gpa.toString()
}
but it gives me an error like this
java.lang.NumberFormatException: For input string: "null"
atsun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at com.example.gpacalculator.MainActivity.calculate(MainActivity.kt:46)
at com.example.gpacalculator.MainActivity.onCreate$lambda1(MainActivity.kt:27)
at com.example.gpacalculator.MainActivity.$r8$lambda$1xRU0rpJNKxzUpdKrPz49s5lowk(Unknown Source:0)
at com.example.gpacalculator.MainActivity$$ExternalSyntheticLambda0.onClick(Unknown Source:2)
You can iterate on the child views of layout, and retrieve the GPA.
// Get a decimal format for the current locale
private val decimalFormat = DecimalFormat.getInstance()
// Iterate on the children of layout
layout.children.forEach { newLayout ->
// Find the gpa_points EditText in the child layout
val gpaPointsEditText = newLayout.findViewById<EditText>(R.id.gpa_points) as EditText
// Parse the text to be able to perform calculations
val gpaPointsStr = gpaPointsEditText.text.toString()
val gpaPoints = decimalFormat.parse(str)
}
To learn more about layouts :
https://developer.android.com/guide/topics/ui/declaring-layout
i'm trying to write my very first android app. the only programing i have done in the past was some html 4 many years ago (before cms was a thing)
it is essentially a check list but i want to be able to have multiple lists seperated by a list name supplied by the user. i have an input text box called "island name" but i cant figure out how to capture that text from the user and save it for future use...
<?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">
<TextView
android:id="#+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="189dp"
android:text="temp call islander page"
android:textSize="30sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="125dp"
android:layout_marginBottom="271dp"
android:onClick="loadHome"
android:text="home"
android:textSize="30sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<EditText
android:id="#+id/editText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="41dp"
android:ems="10"
android:hint="island name"
android:inputType="textPersonName"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/button" />
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="7dp"
android:layout_marginBottom="8dp"
android:text="north"
app:layout_constraintBottom_toTopOf="#+id/checkBox2"
app:layout_constraintEnd_toEndOf="#+id/checkBox2" />
<CheckBox
android:id="#+id/checkBox2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="2dp"
android:layout_marginBottom="88dp"
android:text="south"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="#+id/editText" />
println("your island name is $name")
<TextView
android:id="#+id/textView4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="5dp"
android:layout_marginTop="19dp"
android:text="you entered $name"
app:layout_constraintStart_toEndOf="#+id/checkBox2"
app:layout_constraintTop_toBottomOf="#+id/checkBox2" />
</androidx.constraintlayout.widget.ConstraintLayout>
To put it simply, in Android dev (Android Studio) you have your view, which is your .xml file and your program logic is written in your .kt or .java file then you refer to your respective view from the .kt oe ,java file.
e.g
activity_main.xml
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.textfield.TextInputEditText
android:id="#+id/textView"
android:layout_height="wrap_content"
android:layout_width="200dp"/>
<Button
android:id="#+id/saveBtn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Save" />
</LinearLayout>
MainActivity.kt :
import kotlinx.android.synthetic.main.activity_main.* //this will reference all views in activity_main -
//Android studio usually auto imports this when you simply type control name
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
saveBtn.setOnClickListener {
saveDetails()
}
}
fun saveDetails(){
var userText = textView.text.toString()
textView4.setText(userText)
//do something with text
}
}
For those who is experiencing the same issue you can use sharedPreferences. As an example:
private lateinit var sp: SharedPreferences
private lateinit var editor: SharedPreferences.Editor
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
nameEditText = findViewById(R.id.etName)
ageEditText = findViewById(R.id.etAge)
sp = getSharedPreferences("my_sf", MODE_PRIVATE)
editor = sp.edit()
}
override fun onPause() {
super.onPause()
val name = nameEditText.text.toString()
val age = ageEditText.text.toString().toInt()
editor.apply {
putString("my_name", name)
putInt("my_age", age)
commit()
}
}
override fun onResume() {
super.onResume()
val name = sp.getString("my_name", null)
val age = sp.getInt("my_age", 0)
nameEditText.setText(name)
if (age!=0) ageEditText.setText(age.toString())
}
I'm looking for a way to recreate the alert dialog in the Setting application of Android Wear:
Which is swipe to dismissable.
But instead, what I got is this:
Just a barebone Android dialog. How can I show the AlertDialog in the Settings.apk style? (Which I think must be default for Android Wear application)
I found no default way to do this, also setting a custom view to an AlertDialog did not look good. You can still try though, maybe a different Theme works.
What I did was create a new Activity and create my own layout which looks like this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.BoxInsetLayout
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">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp"
app:layout_box="all">
<TextView
android:id="#+id/tv_longtext"
android:layout_width="match_parent"
android:layout_height="0sp"
android:layout_weight="1"
android:fontFamily="sans-serif-condensed"
android:gravity="bottom"
android:padding="5sp"
android:text="Ambient screen reduces battery life."
android:textSize="16sp" />
<TextView
android:id="#+id/tv_question"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed"
android:gravity="center_horizontal|top"
android:paddingBottom="15sp"
android:paddingTop="5sp"
android:text="Turn on?"
android:textSize="18sp" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5sp">
<android.support.wearable.view.CircledImageView
android:id="#+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|bottom"
android:src="#drawable/ic_cross"
app:circle_color="#AFAFAF"
app:circle_radius="25dp"
app:circle_radius_pressed="20dp" />
<android.support.wearable.view.CircledImageView
android:id="#+id/btn_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:src="#drawable/ic_tick"
app:circle_color="#0EB695"
app:circle_radius="25dp"
app:circle_radius_pressed="20dp" />
</FrameLayout>
</LinearLayout>
</android.support.wearable.view.BoxInsetLayout>
It looks just like the confirmation screen from the settings. Maybe it still needs some tweaks, but I think this is the way to go.
I had a similar problem and indeed I didn't find a default way to do this. I tried to use AlertDialogs for WearOs and they don't look well, because even if you pass them a custom view, the AlertDialog class crops the layout in some unexpected ways.
How I ended up solving the problem is using the Dialog class (AlertDialog's parent class) and passing it a custom view. The Dialog class doesn't alter the layout and you can attach the dialog to an activity's lifespan (which is the idea of dialogs, creating a custom activity doesn't fit with this requirement).
So you could create a function like this inside your activity:
private void showDialog() {
Dialog dialog = new Dialog(this);
View myLayout = getLayoutInflater().inflate(R.layout.my_layout_id, null);
Button positiveButton = myLayout.findViewById(R.id.positive_button);
positiveButton.setOnClickListener(
v -> {
/* Your action on positive button clicked. */
}
);
Button negativeButton = myLayout.findViewById(R.id.negative_button);
negativeButton.setOnClickListener(
v -> {
/* Your action on negative button clicked. */
}
);
dialog.setContentView(myLayout);
dialog.show();
}
I created a similar fragment with custom layout like this:
Kotlin code:
/**
* Created by nmbinh87#gmail.com on 4/12/21.
*/
class ConfirmationDialog private constructor() : DialogFragment(R.layout.confirmation_dialog) {
var listener: Listener? = null
var longMessage: String = ""
var shortMessage = ""
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
tv_longtext.text = longMessage
tv_question.text = shortMessage
tv_longtext.visibility = if (longMessage.isEmpty()) View.GONE else View.VISIBLE
tv_question.visibility = if (shortMessage.isEmpty()) View.GONE else View.VISIBLE
btn_cancel.setSafeOnClickListener {
dismiss()
listener?.onCancel()
}
btn_ok.setSafeOnClickListener {
dismiss()
listener?.onConfirm()
}
}
override fun onStart() {
super.onStart()
val params = dialog?.window?.attributes
params?.width = WindowManager.LayoutParams.MATCH_PARENT
params?.height = WindowManager.LayoutParams.MATCH_PARENT
dialog?.window?.attributes = params as WindowManager.LayoutParams
dialog?.window?.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT));
}
open class Listener {
fun onCancel() {
}
open fun onConfirm() {
}
}
companion object {
fun show(
fm: FragmentManager,
longMessage: String = "",
shortMessage: String = "",
listener: Listener
) {
val fragment = ConfirmationDialog()
fragment.longMessage = longMessage
fragment.shortMessage = shortMessage
fragment.listener = listener
fragment.show(fm, fm::class.simpleName)
}
}
}
Layout:
<?xml version="1.0" encoding="utf-8"?>
<android.support.wearable.view.BoxInsetLayout 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:background="#color/colorPrimaryDark"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:orientation="vertical"
android:padding="10dp"
app:layout_box="all">
<TextView
android:id="#+id/tv_longtext"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_weight="1"
android:fontFamily="sans-serif-condensed"
android:gravity="center"
android:padding="5sp"
android:textColor="#color/white"
android:textSize="16sp"
tools:text="Ambient screen reduces battery life." />
<TextView
android:id="#+id/tv_question"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fontFamily="sans-serif-condensed"
android:layout_weight="1"
android:gravity="center"
android:paddingTop="5sp"
android:paddingBottom="15sp"
android:textColor="#color/white"
android:textSize="18sp"
tools:text="Turn on?" />
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="5sp">
<android.support.wearable.view.CircledImageView
android:id="#+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left|bottom"
android:src="#drawable/ic_cc_clear"
app:circle_color="#AFAFAF"
app:circle_radius="25dp"
app:circle_radius_pressed="20dp" />
<android.support.wearable.view.CircledImageView
android:id="#+id/btn_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right|bottom"
android:src="#drawable/ic_cc_checkmark"
app:circle_color="#0EB695"
app:circle_radius="25dp"
app:circle_radius_pressed="20dp" />
</FrameLayout>
</LinearLayout>
</android.support.wearable.view.BoxInsetLayout>
Usage:
ConfirmationDialog.show(
childFragmentManager,
"",
"Turn alarm off?",
object : ConfirmationDialog.Listener() {
override fun onConfirm() {
super.onConfirm()
turnAlarm(false)
}
})