My Android (Java) App uses Fragments to display products in a GridLayout.
Each product is a cardview with two TextViews as well as an ImageView.
I have all my products stored on a webserver in mariaDB. Fragment's OnCreate method gets my productList from server.
Now I want to dynamically create CardViews for all products returned from the server. For now, I have hardcoded the layout, but as the number of products can change, it's neccesary to create CardViews for the products dynamically.
How can I achieve this in Java?
This is how the Fragment looks:
Here's how I implemented the layout:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 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.DrinksFragment">
<androidx.gridlayout.widget.GridLayout
android:id="#+id/mainGrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="14dp"
app:alignmentMode="alignMargins"
app:columnCount="3"
app:columnOrderPreserved="false"
app:rowCount="3">
<androidx.cardview.widget.CardView
android:id="#+id/cV_water"
style="#style/ProductCardStyle">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center_horizontal|center_vertical"
android:layout_margin="16dp"
android:orientation="vertical">
<ImageView
android:id="#+id/iV_water"
style="#style/ImageStyle"
android:contentDescription="#string/ic_water"
app:layout_constraintBottom_toTopOf="#+id/tV_counterWater"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/tV_descWater"
app:srcCompat="#drawable/ic_water_bottle" />
<TextView
android:id="#+id/tV_descWater"
style="#style/TextStyle"
android:text="#string/product_water"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/tV_counterWater"
style="#style/TextStyle"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.cardview.widget.CardView>
</androidx.gridlayout.widget.GridLayout>
</FrameLayout>
Also, here's the ProductCardStyle:
<style name = "ProductCardStyle">
<item name = "cardBackgroundColor">#color/colorPrimary</item>
<item name = "android:layout_width">0dp</item>
<item name = "android:layout_height">0dp</item>
<item name = "android:layout_marginLeft">2dp</item>
<item name = "android:layout_marginRight">2dp</item>
<item name = "android:layout_marginBottom">2dp</item>
<item name = "android:layout_marginTop">2dp</item>
<item name = "cardCornerRadius">4dp</item>
<item name = "cardElevation">8dp</item>
<item name = "layout_columnWeight">1</item>
<item name = "layout_rowWeight">1</item>
</style>
Would appreciate any help!
You need to use RecyclerView with GridLayoutManager.
You can begin with simple RecyclerView like in this article
https://proandroiddev.com/how-to-implement-a-recyclerview-33fd4ff9988e
And apply GridLayoutManager after RecyclerView implemented.
For more info:
https://developer.android.com/guide/topics/ui/layout/recyclerview
Related
I am trying to add a bottom navigation menu for the application i am trying to make, I followed every step of the video and the bottom nav menu still not showing up. Can someone help me?
Dashboard 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="Dashboard.Dashboard">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentContainerView"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/bottom_nav" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="#+id/bottom_nav_view"
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>
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/feedFragment"
android:title="#string/home"
android:icon="#drawable/home_icon"/>
<item
android:id="#+id/searchFragment"
android:title="#string/search"
android:icon="#drawable/search_icon"/>
<item
android:id="#+id/postFragment"
android:title="#string/add"
android:icon="#drawable/add_post"/>
<item
android:id="#+id/notificationFragment"
android:title="#string/notification"
android:icon="#drawable/notification_icon"/>
<item
android:id="#+id/profileFragment"
android:title="#string/profile"
android:icon="#drawable/person_icon"/>
</menu>
never mind, I got it work somehow. Everything was working perfectly. I just needed to add a library before I use the bottom navigation bar.
This library in your build.grandle
implementation 'androidx.navigation:navigation-fragment:2.4.1'
implementation 'androidx.navigation:navigation-ui:2.4.1'
I have a problem in my activity: it has FragmentContainerView that initially show the home fragment and, when the activity's method onCreate start, it show a BottomSheetDialog. When I show the BottomSheetDialog the Home Fragment disappear.
From what I know the problem is the replace method, so I think that I should insert the Dialog in a child fragment, but I don't know how.
This is my project:
MainActivity onCreate
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setSubtitle("Workout");
toolbar.setNavigationOnClickListener(v -> {
getSupportFragmentManager().beginTransaction().replace(R.id.fragmentContainerView, new HomeFragment()).commit();
toolbar.setSubtitle("Workout");
});
bottomSheetDialog = new BottomSheetDialog(this, R.style.BottomSheetTheme);
bottomSheetDialog.setContentView(LayoutInflater.from(getApplicationContext()).
inflate(R.layout.bottom_sheet_layout, findViewById(R.id.bottom_sheet)));
bottomSheetDialog.show();
}
activitymain.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">
<androidx.fragment.app.FragmentContainerView
android:id="#+id/fragmentContainerView"
android:name="com.example.myproject.Fragments.HomeFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginTop="?actionBarSize"
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"
tools:layout="#layout/fragment_home" />
<androidx.appcompat.widget.Toolbar
android:id="#+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?actionBarSize"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="#menu/items"
app:navigationIcon="#drawable/app_logo"
app:titleTextColor="#color/white"
app:subtitleTextColor="#color/white" />
</androidx.constraintlayout.widget.ConstraintLayout>
bottom_sheet_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:id="#+id/bottom_sheet"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/bottom_sheet_background">
<TextView
android:id="#+id/titleView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:text="title"
android:textColor="#color/red_700"
android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="#+id/TextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="16dp"
android:layout_marginTop="16dp"
android:text="text"
android:textColor="#E53935"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/titleView" />
</androidx.constraintlayout.widget.ConstraintLayout>
bottom_sheet_backgound.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<solid android:color="#color/white"/>
<corners android:topLeftRadius="20dp" android:topRightRadius="20dp"/>
</shape>
themes.xml
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.MyApp" parent="Theme.MaterialComponents.DayNight.NoActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">#color/red_700</item>
<item name="colorPrimaryVariant">#color/red_900</item>
<item name="android:background">#color/black</item>
<item name="android:textColor">#color/white</item>
<!-- Status bar color. -->
<item name="android:statusBarColor" tools:targetApi="l">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
<item name="android:listDivider">#drawable/divider</item>
</style>
<style name="BottomSheetTheme" parent="Theme.Design.BottomSheetDialog">
<item name="bottomSheetStyle">#style/BottomSheetStyle</item>
</style>
<style name="BottomSheetStyle" parent="Widget.Design.BottomSheet.Modal">
<item name="background">#android:color/transparent</item>
</style>
</resources>
If you need to see other files, tell me
Ok problem resolved.
For first I was wrong in style and I changed from:
<item name="background">#android:color/transparent</item>
to:
<item name="android:background">#android:color/transparent</item>
The real problem was that BottomSheetDialog's theme has setted the app's theme background like default background, so the background was black.
Resolved by adding:
<item name="android:background">#android:color/transparent</item>
in BottomSheetTheme
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.
I added a style for a checkbox like below
<style name="SurveyCheckBox" >
<item name="colorControlNormal">#color/colorPrimaryLight</item>
<item name="colorControlActivated">#color/colorSecondary</item>
<item name="colorControlHighlight">#color/colorSecondaryDark</item>
</style>
It works perfectly but I also added this style for checkboxes created dynamically in a recycler view. In this case, style does not affect checkboxes. To solve this problem, I added "android:" before the item name.
<style name="SurveyCheckBox" >
<item name="android:colorControlNormal">#color/colorPrimaryLight</item>
<item name="android:colorControlActivated">#color/colorSecondary</item>
<item name="android:colorControlHighlight">#color/colorSecondaryDark</item>
</style>
This property works in API >=21 but does not work <21. Is there any solution for this problem?
recycler_view_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#color/white"
android:orientation="horizontal"
android:padding="10dp">
<TextView
android:id="#+id/survey_check_text"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="left|center"
android:layout_weight="8"
android:textColor="#color/colorOnBackground"
android:textSize="16sp" />
<CheckBox
android:id="#+id/survey_check_box"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:theme="#style/SurveyCheckBox" /> </LinearLayout>
Have you tried with android.support.v7.widget.AppCompatCheckBox instead of CheckBox ?
I am making Spinner like below image. It's work fine as I want. But I want to change background color to #FFFFFF and textColor to #000000. But I got revise output...
java code:
Spinner staticSpinner = (Spinner)findViewById(R.id.static_spinner);
ArrayAdapter<CharSequence> staticAdapter = ArrayAdapter.createFromResource(this,R.array.request_role,android.R.layout.simple_spinner_item);
staticAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
// Apply the adapter to the spinner
staticSpinner.setAdapter(staticAdapter);
xml code :
<Spinner
android:id="#+id/static_spinner"
android:layout_width="150dp"
android:layout_height="45dp"
android:layout_marginLeft="30dp"
style="#android:style/Widget.Holo.Light.DropDownItem" ></Spinner>
simple_spinner_dropdown_item.xml
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/dropdownListPreferredItemHeight"
android:ellipsize="marquee"
android:textColor="#000000"
/>
simple_spinner_item.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:ellipsize="marquee"
android:textColor="#000000"
android:textAlignment="inherit"/>
styles.xml
<resources xmlns:android="http://schemas.android.com/apk/res/android">
<!-- Base application theme. -->
<style name="AppTheme" parent="Theme.AppCompat">
<item name="colorPrimary">#0072BA</item>
<item name="colorPrimaryDark">#004F80</item>
<item name="colorAccent">#0072BA</item>
<item name="android:textColorPrimary">#FFFFFF</item>
<item name="colorControlHighlight">#FFFFFF</item>
<item name="android:actionBarSize">48dp</item>
<item name="actionBarSize">48dp</item>
<item name="android:windowActionBar">false</item>
</style>
</resources>
By using below code I can solve my problem.
<Spinner
android:id="#+id/static_spinner2"
android:layout_width="fill_parent"
android:layout_height="32dp"
android:layout_marginLeft="30dp"
android:background="#drawable/apptheme_spinner_background_holo_light"
android:popupBackground="#ffffff" />
Spinner_item.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="14sp"
android:background="#FFFFFF"
android:textColor="#000000" />
spinner_dropdown_item.xml
<?xml version="1.0" encoding="utf-8"?>
<CheckedTextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#android:id/text1"
style="?android:attr/spinnerDropDownItemStyle"
android:singleLine="true"
android:layout_width="match_parent"
android:layout_height="?android:attr/listPreferredItemHeight"
android:ellipsize="marquee"
android:textColor="#000000"/>
java code :
Spinner staticSpinner = (Spinner)findViewById(R.id.static_spinner);
ArrayAdapter<CharSequence> staticAdapter =
ArrayAdapter.createFromResource(this,R.array.request_role,R.layout.spinner_item);
staticAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
// Apply the adapter to the spinner
staticSpinner.setAdapter(staticAdapter);
Use this spinner in your code
<Spinner
style="#style/edit_style"
android:id="#+id/spr_city"
android:background="#drawable/selector_spinner"
android:layout_width="0dp"
android:textColor="#android:color/white"
android:minHeight="#dimen/min_height"
android:textCursorDrawable="#null"
android:textColorHint="#android:color/white"
android:layout_height="fill_parent"
android:layout_weight="9"
/>
and make this style in style .xml
<style name="edit_style" >
<item name="android:textSize">14sp</item>
<item name="android:textColor">#ffffff</item>
</style>
and use this code in activity
ArrayAdapter<String> adp1=new ArrayAdapter<String> (activity,R.layout.spinner_item_selected,city_list);
adp1.setDropDownViewResource(R.layout.spinner_item);
s_city.setAdapter(adp1);
and create xml spinner_item_selected
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="#+id/textViewSpinnerItem"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="#dimen/common_margin"
style="#style/edit_style"
android:textColor="#android:color/white"
xmlns:android="http://schemas.android.com/apk/res/android" />
and one more xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="#+id/textViewSpinnerItem"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="#dimen/common_margin"
style="#style/edit_style"
android:textColor="#color/spinner_item_selector"
xmlns:android="http://schemas.android.com/apk/res/android" />
You can set the spinners background color in xml like this:
android:background="YOUR_HEX_COLOR_CODE"
and if you use the drop down menu with you spinner you can set its background color like this:
android:popupBackground="YOUR_HEX_COLOR_CODE"
change android.R to yourprojcet.R
android.R.layout.simple_spinner_dropdown_item
to
letmobility.com.itforte.R.layout.simple_spinner_dropdown_item;
it is taking android layout instead of your app specific layout.
Your call should be like this :
ArrayAdapter<CharSequence> staticAdapter =
ArrayAdapter.createFromResource(this,R.array.request_role,android.R.layout.simple_spinner_item);
staticAdapter.setDropDownViewResource(R.layout.simple_spinner_dropdown_item);
instead of :
ArrayAdapter<CharSequence> staticAdapter = ArrayAdapter.createFromResource(this,R.array.request_role,android.R.layout.simple_spinner_item);
staticAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);