I tried following a tutorial (https://guides.codepath.com/android/using-the-app-toolbar#custom-title-view) on creating a custom TextView inside a Toolbar. What I want to do is have the ability to dynamically change the text inside the TextView using Java. However, the problem is that I can't and no error messages are being displayed.
Toolbar code in XML:
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:elevation="4dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/toolbarTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="Test1"
android:textSize="16sp"
android:textColor="#color/textColor" />
</androidx.appcompat.widget.Toolbar>
Toolbar Java code in the Activity Class:
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayShowTitleEnabled(false);
TextView toolbarTitle = toolbar.findViewById(R.id.toolbarTitle);
toolbarTitle.setText("Test");
Styles.xml:
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorSecondary</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
A simple toolbarTitle.setText() should do the job but for some unknown reasons it doesn't. Even if I remove the android:text from the XML code and use setText() right after the Java code it still doesn't work.
Does this mean that TextViews inside Toolbars are immutable?
Thanks!
Edit 1:
So I managed to find the problem but haven't particularly found a solution. The problem is caused by the Data Binding in the activity_main.xml file. Once the all code related to Data Binding is removed, I'm able to use setText() the way I want. Why is this causing a problem?
activity_main.xml:
<?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"
tools:context=".activity.MainActivity">
<data>
<variable
name="VM"
type="com.tahmidu.app.view_model.IMainActivityNavViewModel" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/colorPrimary">
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorPrimary"
android:minHeight="?attr/actionBarSize"
android:theme="?attr/actionBarTheme"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<TextView
android:id="#+id/toolbarTitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/textColor" />
</androidx.appcompat.widget.Toolbar>
<FrameLayout
android:id="#+id/audioMainFragment"
android:name="com.tahmidu.app.fragment.AudioFragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/toolbar" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/colorSecondary"
app:itemIconTint="#color/bottom_navigation_color"
app:labelVisibilityMode="unlabeled"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_navigation_main" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
TextViews inside toolbars are definitely not immutable. Maybe the problem is where you are calling the textview.setText() method. It should be after after the view is created, so on onCreate() or onViewCreated()
Solution (Suggested by Nabil): Bind the text. Ensure you set the LifecycleOwner() method otherwise the UI would not update. setText() stops working if you use Data Binding from the looks of it.
Related
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/bottomnav">
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomnav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
Whenever i try to add bottom navigation bar the whole activity goes blank
If you would like to display buttons in the Bottom Navigation Bar, you need to add app:menu to BottomNavigationView:
<?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:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center">
<FrameLayout
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toTopOf="#+id/bottomnav">
</FrameLayout>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottomnav"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_nav_menu"/>
</androidx.constraintlayout.widget.ConstraintLayout>
Under res/menu, create a bottom_nav_menu.xml:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/main" android:title="Main" />
<item android:id="#+id/secondary" android:title="Secondary" />
</menu>
Then you should see 2 buttons in your Bottom Navigation Bar.
The above should work fine on a Physical Android Device. If you are not able to preview the Bottom Navigation Bar in Design view of Android Studio, please check if your build.gradle has the following dependency:
implementation 'com.google.android.material:material:1.5.0'
You can either downgrade it to:
implementation 'com.google.android.material:material:1.3.0'
or upgrade it to:
implementation 'com.google.android.material:material:1.6.0'
This is My Floating Action Button
How to set fabmargin using custom fab. I was creating an android app based on an UI design But this bottom appbar with custom fab is difficult.
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#color/white"
app:borderWidth="0dp"
app:layout_anchor="#id/bottom_app_bar" />
<com.google.android.material.bottomappbar.BottomAppBar
android:id="#+id/bottom_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:fabAlignmentMode="end"
app:fabCradleMargin="1dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:menu="#menu/bottom_menu" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Themes.xml
#style/FabShapeStyle1
<style name="FabShapeStyle1" parent="ShapeAppearance.MaterialComponents.SmallComponent">
<item name="cornerSize">20%</item>
</style>
enter code here
enter code here
if you are using latest material design dependency which supports material 3 then apply this property in fab button
currently this is latest dependency of material
implementation 'com.google.android.material:material:1.7.0'
app:shapeAppearanceOverlay="#style/Widget.Material3.FloatingActionButton.Primary"
now your Fab button code look like this
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:backgroundTint="#color/white"
app:shapeAppearanceOverlay="#style/Widget.Material3.FloatingActionButton.Primary"
app:borderWidth="0dp"
app:layout_anchor="#id/bottom_app_bar" />
My recyclerview is:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout android:layout_width="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:background="#drawable/recyclerview_highlight"
android:layout_margin="6dp">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="6dp">
<TextView
android:id="#+id/articleCategTextView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
android:text="#null"
app:layout_constraintBottom_toTopOf="#id/articleNameTextView"
app:layout_constraintRight_toLeftOf="#id/articleQteTextView"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/articleQteTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintLeft_toRightOf="#id/articleCategTextView"
app:layout_constraintBottom_toTopOf="#id/articleNameTextView"
android:text="#null" />
<TextView
android:id="#+id/articleNameTextView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="end"
android:maxLines="1"
app:layout_constraintBottom_toBottomOf="parent"
android:text="#null" />
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
#drawable/recyclerview_highlight:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:state_selected="true" android:drawable="#color/selected_color"/>
</selector>
In "onBindViewHolder", I highlight it, when selected with:
holder.itemView.setSelected(article.isSelected());
All is ok BUT, for a little more visual elegance, I wanted to transform the LinearLayout into Cardview.
And when I try it, setSelected has not effect anymore. I even try to "setActivated" with state_activated but not better.
What should I modify to obtain the same type of operation? Is it at the level of the layout, the selector or the java code, and what to use instead of "selected"?
I finaly had to add a LinearLayout, inside the cardView; which is the one I setSelected() and the result is what I needed.
How do I remove this gap in a ConstraintLayout? The top is an ImageView with a top constraint to the top of the parent (ConstraintLayout).
Gap at the top between the toolbar and banner
This is how my styles.xml looks like:
<resources>
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
<!-- Customize your theme here. -->
<item name="colorPrimary">#color/colorPrimary</item>
<item name="colorPrimaryDark">#color/colorPrimaryDark</item>
<item name="colorAccent">#color/colorAccent</item>
</style>
My activity_main.xml looks like this:
<?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">
<ImageView
android:id="#+id/headerImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/header" />
<Button
android:id="#+id/addlog_btn"
style="#android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="108dp"
android:background="#drawable/newlogbtn"
android:fontFamily="#font/roboto_regular"
android:onClick="createNewLog"
android:paddingTop="72sp"
app:layout_constraintStart_toStartOf="#+id/headerImg"
app:layout_constraintTop_toTopOf="#+id/headerImg" />
<Button
android:id="#+id/addlog_btn2"
style="#android:style/Widget.DeviceDefault.Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:background="#drawable/settingsbtn"
android:fontFamily="#font/roboto_regular"
android:paddingTop="72sp"
app:layout_constraintEnd_toEndOf="#+id/headerImg"
app:layout_constraintTop_toTopOf="#+id/addlog_btn" />
</androidx.constraintlayout.widget.ConstraintLayout>
My end goal is this:
I would like to achieve this with just editing the XML if it is possible, I tried to change the margins and padding's of both parent and I didn't do it right or it just doesn't seem to work.
You can remove this gap by adding android:scaleType="centerCrop" to the banner ImageView so that it will fill the entire assigned room to it.
So the layout will be after this change:
<?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">
<ImageView
android:id="#+id/headerImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:scaleType="centerCrop"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="#drawable/header" />
<Button
android:id="#+id/addlog_btn"
style="#android:style/Widget.DeviceDefault.Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="32dp"
android:layout_marginLeft="32dp"
android:layout_marginTop="108dp"
android:background="#drawable/newlogbtn"
android:fontFamily="#font/roboto_regular"
android:onClick="createNewLog"
android:paddingTop="72sp"
app:layout_constraintStart_toStartOf="#+id/headerImg"
app:layout_constraintTop_toTopOf="#+id/headerImg" />
<Button
android:id="#+id/addlog_btn2"
style="#android:style/Widget.DeviceDefault.Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginEnd="32dp"
android:layout_marginRight="32dp"
android:background="#drawable/settingsbtn"
android:fontFamily="#font/roboto_regular"
android:paddingTop="72sp"
app:layout_constraintEnd_toEndOf="#+id/headerImg"
app:layout_constraintTop_toTopOf="#+id/addlog_btn" />
</androidx.constraintlayout.widget.ConstraintLayout>
To remove any doubts or thoughts about duplicate: on Material Design is defined what is "extended".
But most of the people confuses "extended" with "Type of Transition: Speed Dial", what make hard to find solutions. Like here
Question
So what I'm looking forward is how setup the FAB with text and a extended size.
Today my code is like this:
<android.support.design.widget.FloatingActionButton
android:id="#+id/maps_main_distance_btn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:text="#string/str_distance_btn"
app:elevation="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
But my button look like this:
No text and no right format. I'm using it in a Constraint Layout.
Add the dependencies in your Gradle file:
implementation 'com.google.android.material:material:1.1.0-alpha04'
in your xml file:
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_margin="#dimen/fab_margin"
android:text="Create"
app:icon="#drawable/outline_home_24" />
You can create a utility class that animates a MaterialButton to an Extended FloatingActionButton using a ConstraintLayout. You'll first need to declare the two states of the MaterialButton in xml, and then use the TransitionManager to animate between them.
You can read a medium post about it here, in the meantime, I'll add bits of relevant code here.
Collapsed FAB state:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout android:id="#+id/extend_fab_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/bg_fab"
android:elevation="8dp">
<android.support.design.button.MaterialButton
android:id="#+id/fab"
style="#style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="56dp"
android:layout_height="56dp"
app:cornerRadius="56dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Extended FAB State:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout android:id="#+id/extend_fab_container"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:elevation="8dp"
android:background="#drawable/bg_fab">
<android.support.design.button.MaterialButton
android:id="#+id/fab"
style="#style/Widget.MaterialComponents.Button.UnelevatedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cornerRadius="56dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Background Drawable:
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="#color/colorAccent" />
<corners android:radius="56dp" />
</shape>
And relevant Java Expansion code:
private void setExtended(boolean extended, boolean force) {
if (isAnimating || (extended && isExtended() && !force)) return;
ConstraintSet set = new ConstraintSet();
set.clone(container.getContext(), extended ? R.layout.fab_extended : R.layout.fab_collapsed);
TransitionManager.beginDelayedTransition(container, new AutoTransition()
.addListener(listener).setDuration(150));
if (extended) button.setText(currentText);
else button.setText("");
set.applyTo(container);
}
You can use this library to do that. (I used another way)
But I used a FancyButton to create a round and awesome button in coordinator layout as below:
<mehdi.sakout.fancybuttons.FancyButton
android:id="#+id/actMain_btnCompare"
app:layout_behavior="#string/fab_transformation_sheet_behavior"
android:layout_width="125dp"
android:layout_height="38dp"
android:layout_gravity="bottom|center"
android:layout_margin="20dp"
android:elevation="3dp"
android:padding="2dp"
fancy:fb_borderColor="#color/white"
fancy:fb_borderWidth="3dp"
fancy:fb_defaultColor="#color/colorPrimaryDark"
fancy:fb_radius="20dp"
fancy:fb_text="مقایسه محصول"
fancy:fb_textColor="#color/white"
fancy:fb_textGravity="center"
fancy:fb_textSize="13sp" />
and result is:
That can have icon in it (see FancyButton).
with app:layout_behavior="#string/fab_transformation_sheet_behavior" it acts like fab as below:
Good luck.
The short answer: set the background to a rect with rounded corners, rather than an oval. Then set the dimension of the radius to half that of the height of the button.
How I actually did it:
<android.support.design.widget.FloatingActionButton
android:id="#+id/maps_main_distance_btn"
android:layout_width="#dimen/floating_button_width"
android:layout_height="#dimen/floating_button_height"
android:layout_marginBottom="8dp"
android:background="#drawable/btn_background_expanded"
android:text="#string/str_distance_btn"
app:elevation="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
drawable/btn_background_expanded.xml:
<?xml version="1.0" encoding="utf-8"?>
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:colorControlHighlight">
<item>
<shape android:shape="rectangle">
<solid android:color="?android:colorAccent" />
<corners
android:radius="#dimen/floating_button_radius"
/>
</shape>
</item>
</ripple>