diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 654ed18e..34219a26 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -202,6 +202,21 @@
android:exported="false"
android:label="@string/table_layout"
android:parentActivityName=".ui.screens.main.MainActivity" />
+
+
+
-
\ No newline at end of file
+
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/CounterViewModel.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/CounterViewModel.java
new file mode 100644
index 00000000..08301a2c
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/CounterViewModel.java
@@ -0,0 +1,22 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.architecture.viewmodel;
+
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.MutableLiveData;
+import androidx.lifecycle.ViewModel;
+
+public class CounterViewModel extends ViewModel {
+
+ private final MutableLiveData counter = new MutableLiveData<>(0);
+
+ public LiveData getCounter() {
+ return counter;
+ }
+
+ public void incrementCounter() {
+ Integer currentValue = counter.getValue();
+ if (currentValue == null) {
+ currentValue = 0;
+ }
+ counter.setValue(currentValue + 1);
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/ViewModelActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/ViewModelActivity.java
new file mode 100644
index 00000000..777960e9
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/ViewModelActivity.java
@@ -0,0 +1,59 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.architecture.viewmodel;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.lifecycle.ViewModelProvider;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.ActivityViewModelBinding;
+import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.architecture.viewmodel.tabs.ViewModelTabCodeFragment;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.architecture.viewmodel.tabs.ViewModelTabLayoutFragment;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.common.LessonCodeTabsActivity;
+import com.d4rk.androidtutorials.java.ui.utils.LessonUiUtils;
+import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
+
+import java.util.Arrays;
+
+import me.zhanghai.android.fastscroll.FastScrollerBuilder;
+
+public class ViewModelActivity extends SyntaxFabActivity {
+
+ private ActivityViewModelBinding binding;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ binding = ActivityViewModelBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+ EdgeToEdgeHelper.applyEdgeToEdge(getWindow(), binding.getRoot());
+ LessonUiUtils.setupDescriptionSection(binding.descriptionSection,
+ R.string.summary_view_model,
+ true);
+
+ new FastScrollerBuilder(binding.scrollView).useMd2Style().build();
+
+ CounterViewModel counterViewModel = new ViewModelProvider(this).get(CounterViewModel.class);
+ binding.incrementButton.setOnClickListener(view -> counterViewModel.incrementCounter());
+ counterViewModel.getCounter().observe(this, value ->
+ binding.counterValue.setText(getString(R.string.view_model_counter_value, value)));
+
+ setupSyntaxFab(binding.floatingButtonShowSyntax, () -> startActivity(
+ LessonCodeTabsActivity.createIntent(
+ this,
+ R.string.view_model,
+ Arrays.asList(
+ LessonCodeTabsActivity.PageSpec.of(
+ ViewModelTabCodeFragment.class,
+ getString(R.string.code_java)
+ ),
+ LessonCodeTabsActivity.PageSpec.of(
+ ViewModelTabLayoutFragment.class,
+ getString(R.string.layout_xml)
+ )
+ )
+ )));
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/tabs/ViewModelTabCodeFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/tabs/ViewModelTabCodeFragment.java
new file mode 100644
index 00000000..7ae21a30
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/tabs/ViewModelTabCodeFragment.java
@@ -0,0 +1,37 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.architecture.viewmodel.tabs;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.FragmentCodeBinding;
+import com.d4rk.androidtutorials.java.ui.components.NoCodeAdFragment;
+import com.d4rk.androidtutorials.java.utils.CodeViewUtils;
+
+public class ViewModelTabCodeFragment extends NoCodeAdFragment {
+
+ @Override
+ @NonNull
+ protected FragmentCodeBinding inflateBinding(@NonNull LayoutInflater inflater, ViewGroup container) {
+ return FragmentCodeBinding.inflate(inflater, container, false);
+ }
+
+ @Override
+ @NonNull
+ protected View getAdView(@NonNull FragmentCodeBinding binding) {
+ return binding.adView;
+ }
+
+ @Override
+ protected void onBindingCreated(@NonNull FragmentCodeBinding binding, Bundle savedInstanceState) {
+ CodeViewUtils.populateFromRawResource(
+ binding.codeView,
+ R.raw.text_view_model_java,
+ CodeViewUtils.HighlightMode.JAVA,
+ "ViewModelTabCode");
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/tabs/ViewModelTabLayoutFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/tabs/ViewModelTabLayoutFragment.java
new file mode 100644
index 00000000..6396bf9a
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/architecture/viewmodel/tabs/ViewModelTabLayoutFragment.java
@@ -0,0 +1,37 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.architecture.viewmodel.tabs;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.FragmentCodeBinding;
+import com.d4rk.androidtutorials.java.ui.components.NoCodeAdFragment;
+import com.d4rk.androidtutorials.java.utils.CodeViewUtils;
+
+public class ViewModelTabLayoutFragment extends NoCodeAdFragment {
+
+ @Override
+ @NonNull
+ protected FragmentCodeBinding inflateBinding(@NonNull LayoutInflater inflater, ViewGroup container) {
+ return FragmentCodeBinding.inflate(inflater, container, false);
+ }
+
+ @Override
+ @NonNull
+ protected View getAdView(@NonNull FragmentCodeBinding binding) {
+ return binding.adView;
+ }
+
+ @Override
+ protected void onBindingCreated(@NonNull FragmentCodeBinding binding, Bundle savedInstanceState) {
+ CodeViewUtils.populateFromRawResource(
+ binding.codeView,
+ R.raw.text_view_model_xml,
+ CodeViewUtils.HighlightMode.XML,
+ "ViewModelTabLayout");
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/ConstraintLayoutActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/ConstraintLayoutActivity.java
new file mode 100644
index 00000000..4117c10a
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/ConstraintLayoutActivity.java
@@ -0,0 +1,53 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.layouts.constraint;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.ActivityConstraintLayoutBinding;
+import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.common.LessonCodeTabsActivity;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.layouts.constraint.tabs.ConstraintLayoutTabCodeFragment;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.layouts.constraint.tabs.ConstraintLayoutTabLayoutFragment;
+import com.d4rk.androidtutorials.java.ui.utils.LessonUiUtils;
+import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
+
+import java.util.Arrays;
+
+import me.zhanghai.android.fastscroll.FastScrollerBuilder;
+
+public class ConstraintLayoutActivity extends SyntaxFabActivity {
+
+ private ActivityConstraintLayoutBinding binding;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ binding = ActivityConstraintLayoutBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+ EdgeToEdgeHelper.applyEdgeToEdge(getWindow(), binding.getRoot());
+ LessonUiUtils.setupDescriptionSection(binding.descriptionSection,
+ R.string.summary_constraint_layout,
+ true);
+
+ new FastScrollerBuilder(binding.scrollView).useMd2Style().build();
+
+ setupSyntaxFab(binding.floatingButtonShowSyntax, () -> startActivity(
+ LessonCodeTabsActivity.createIntent(
+ this,
+ R.string.constraint_layout,
+ Arrays.asList(
+ LessonCodeTabsActivity.PageSpec.of(
+ ConstraintLayoutTabCodeFragment.class,
+ getString(R.string.code_java)
+ ),
+ LessonCodeTabsActivity.PageSpec.of(
+ ConstraintLayoutTabLayoutFragment.class,
+ getString(R.string.layout_xml)
+ )
+ )
+ )));
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/tabs/ConstraintLayoutTabCodeFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/tabs/ConstraintLayoutTabCodeFragment.java
new file mode 100644
index 00000000..8f2d267a
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/tabs/ConstraintLayoutTabCodeFragment.java
@@ -0,0 +1,37 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.layouts.constraint.tabs;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.FragmentCodeBinding;
+import com.d4rk.androidtutorials.java.ui.components.NoCodeAdFragment;
+import com.d4rk.androidtutorials.java.utils.CodeViewUtils;
+
+public class ConstraintLayoutTabCodeFragment extends NoCodeAdFragment {
+
+ @Override
+ @NonNull
+ protected FragmentCodeBinding inflateBinding(@NonNull LayoutInflater inflater, ViewGroup container) {
+ return FragmentCodeBinding.inflate(inflater, container, false);
+ }
+
+ @Override
+ @NonNull
+ protected View getAdView(@NonNull FragmentCodeBinding binding) {
+ return binding.adView;
+ }
+
+ @Override
+ protected void onBindingCreated(@NonNull FragmentCodeBinding binding, Bundle savedInstanceState) {
+ CodeViewUtils.populateFromRawResource(
+ binding.codeView,
+ R.raw.text_constraint_layout_java,
+ CodeViewUtils.HighlightMode.JAVA,
+ "ConstraintLayoutTabCode");
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/tabs/ConstraintLayoutTabLayoutFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/tabs/ConstraintLayoutTabLayoutFragment.java
new file mode 100644
index 00000000..aac54d0a
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/layouts/constraint/tabs/ConstraintLayoutTabLayoutFragment.java
@@ -0,0 +1,37 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.layouts.constraint.tabs;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.FragmentCodeBinding;
+import com.d4rk.androidtutorials.java.ui.components.NoCodeAdFragment;
+import com.d4rk.androidtutorials.java.utils.CodeViewUtils;
+
+public class ConstraintLayoutTabLayoutFragment extends NoCodeAdFragment {
+
+ @Override
+ @NonNull
+ protected FragmentCodeBinding inflateBinding(@NonNull LayoutInflater inflater, ViewGroup container) {
+ return FragmentCodeBinding.inflate(inflater, container, false);
+ }
+
+ @Override
+ @NonNull
+ protected View getAdView(@NonNull FragmentCodeBinding binding) {
+ return binding.adView;
+ }
+
+ @Override
+ protected void onBindingCreated(@NonNull FragmentCodeBinding binding, Bundle savedInstanceState) {
+ CodeViewUtils.populateFromRawResource(
+ binding.codeView,
+ R.raw.text_constraint_layout_xml,
+ CodeViewUtils.HighlightMode.XML,
+ "ConstraintLayoutTabLayout");
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/RecyclerViewActivity.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/RecyclerViewActivity.java
new file mode 100644
index 00000000..5412ee76
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/RecyclerViewActivity.java
@@ -0,0 +1,67 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.lists.recyclerview;
+
+import android.os.Bundle;
+
+import androidx.annotation.Nullable;
+import androidx.recyclerview.widget.LinearLayoutManager;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.ActivityRecyclerViewBinding;
+import com.d4rk.androidtutorials.java.ui.components.navigation.SyntaxFabActivity;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.common.LessonCodeTabsActivity;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.lists.recyclerview.tabs.RecyclerViewTabCodeFragment;
+import com.d4rk.androidtutorials.java.ui.screens.android.lessons.lists.recyclerview.tabs.RecyclerViewTabLayoutFragment;
+import com.d4rk.androidtutorials.java.ui.utils.LessonUiUtils;
+import com.d4rk.androidtutorials.java.utils.EdgeToEdgeHelper;
+
+import java.util.Arrays;
+import java.util.List;
+
+import me.zhanghai.android.fastscroll.FastScrollerBuilder;
+
+public class RecyclerViewActivity extends SyntaxFabActivity {
+
+ private ActivityRecyclerViewBinding binding;
+
+ @Override
+ protected void onCreate(@Nullable Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ binding = ActivityRecyclerViewBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+ EdgeToEdgeHelper.applyEdgeToEdge(getWindow(), binding.getRoot());
+ LessonUiUtils.setupDescriptionSection(binding.descriptionSection,
+ R.string.summary_recycler_view,
+ true);
+
+ new FastScrollerBuilder(binding.scrollView).useMd2Style().build();
+
+ binding.recyclerViewPreview.setLayoutManager(new LinearLayoutManager(this));
+ binding.recyclerViewPreview.setAdapter(new RecyclerViewPreviewAdapter(getLessonTitles()));
+
+ setupSyntaxFab(binding.floatingButtonShowSyntax, () -> startActivity(
+ LessonCodeTabsActivity.createIntent(
+ this,
+ R.string.recycler_view,
+ Arrays.asList(
+ LessonCodeTabsActivity.PageSpec.of(
+ RecyclerViewTabCodeFragment.class,
+ getString(R.string.code_java)
+ ),
+ LessonCodeTabsActivity.PageSpec.of(
+ RecyclerViewTabLayoutFragment.class,
+ getString(R.string.layout_xml)
+ )
+ )
+ )));
+ }
+
+ private List getLessonTitles() {
+ return Arrays.asList(
+ getString(R.string.linear_layout),
+ getString(R.string.constraint_layout),
+ getString(R.string.recycler_view),
+ getString(R.string.view_model)
+ );
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/RecyclerViewPreviewAdapter.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/RecyclerViewPreviewAdapter.java
new file mode 100644
index 00000000..15403804
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/RecyclerViewPreviewAdapter.java
@@ -0,0 +1,54 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.lists.recyclerview;
+
+import android.view.LayoutInflater;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.d4rk.androidtutorials.java.databinding.ItemRecyclerViewLessonBinding;
+
+import java.util.List;
+
+public class RecyclerViewPreviewAdapter extends RecyclerView.Adapter {
+
+ private final List lessons;
+
+ public RecyclerViewPreviewAdapter(@NonNull List lessons) {
+ this.lessons = lessons;
+ }
+
+ @NonNull
+ @Override
+ public LessonViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ ItemRecyclerViewLessonBinding binding = ItemRecyclerViewLessonBinding.inflate(
+ LayoutInflater.from(parent.getContext()),
+ parent,
+ false
+ );
+ return new LessonViewHolder(binding);
+ }
+
+ @Override
+ public void onBindViewHolder(@NonNull LessonViewHolder holder, int position) {
+ holder.bind(lessons.get(position));
+ }
+
+ @Override
+ public int getItemCount() {
+ return lessons.size();
+ }
+
+ static class LessonViewHolder extends RecyclerView.ViewHolder {
+ private final ItemRecyclerViewLessonBinding binding;
+
+ LessonViewHolder(ItemRecyclerViewLessonBinding binding) {
+ super(binding.getRoot());
+ this.binding = binding;
+ }
+
+ void bind(@NonNull String lessonName) {
+ binding.lessonTitle.setText(lessonName);
+ }
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/tabs/RecyclerViewTabCodeFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/tabs/RecyclerViewTabCodeFragment.java
new file mode 100644
index 00000000..7a3b98d7
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/tabs/RecyclerViewTabCodeFragment.java
@@ -0,0 +1,37 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.lists.recyclerview.tabs;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.FragmentCodeBinding;
+import com.d4rk.androidtutorials.java.ui.components.NoCodeAdFragment;
+import com.d4rk.androidtutorials.java.utils.CodeViewUtils;
+
+public class RecyclerViewTabCodeFragment extends NoCodeAdFragment {
+
+ @Override
+ @NonNull
+ protected FragmentCodeBinding inflateBinding(@NonNull LayoutInflater inflater, ViewGroup container) {
+ return FragmentCodeBinding.inflate(inflater, container, false);
+ }
+
+ @Override
+ @NonNull
+ protected View getAdView(@NonNull FragmentCodeBinding binding) {
+ return binding.adView;
+ }
+
+ @Override
+ protected void onBindingCreated(@NonNull FragmentCodeBinding binding, Bundle savedInstanceState) {
+ CodeViewUtils.populateFromRawResource(
+ binding.codeView,
+ R.raw.text_recycler_view_java,
+ CodeViewUtils.HighlightMode.JAVA,
+ "RecyclerViewTabCode");
+ }
+}
diff --git a/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/tabs/RecyclerViewTabLayoutFragment.java b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/tabs/RecyclerViewTabLayoutFragment.java
new file mode 100644
index 00000000..cc10a7cc
--- /dev/null
+++ b/app/src/main/java/com/d4rk/androidtutorials/java/ui/screens/android/lessons/lists/recyclerview/tabs/RecyclerViewTabLayoutFragment.java
@@ -0,0 +1,37 @@
+package com.d4rk.androidtutorials.java.ui.screens.android.lessons.lists.recyclerview.tabs;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+
+import com.d4rk.androidtutorials.java.R;
+import com.d4rk.androidtutorials.java.databinding.FragmentCodeBinding;
+import com.d4rk.androidtutorials.java.ui.components.NoCodeAdFragment;
+import com.d4rk.androidtutorials.java.utils.CodeViewUtils;
+
+public class RecyclerViewTabLayoutFragment extends NoCodeAdFragment {
+
+ @Override
+ @NonNull
+ protected FragmentCodeBinding inflateBinding(@NonNull LayoutInflater inflater, ViewGroup container) {
+ return FragmentCodeBinding.inflate(inflater, container, false);
+ }
+
+ @Override
+ @NonNull
+ protected View getAdView(@NonNull FragmentCodeBinding binding) {
+ return binding.adView;
+ }
+
+ @Override
+ protected void onBindingCreated(@NonNull FragmentCodeBinding binding, Bundle savedInstanceState) {
+ CodeViewUtils.populateFromRawResource(
+ binding.codeView,
+ R.raw.text_recycler_view_xml,
+ CodeViewUtils.HighlightMode.XML,
+ "RecyclerViewTabLayout");
+ }
+}
diff --git a/app/src/main/res/layout/activity_constraint_layout.xml b/app/src/main/res/layout/activity_constraint_layout.xml
new file mode 100644
index 00000000..905cb210
--- /dev/null
+++ b/app/src/main/res/layout/activity_constraint_layout.xml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_recycler_view.xml b/app/src/main/res/layout/activity_recycler_view.xml
new file mode 100644
index 00000000..99794554
--- /dev/null
+++ b/app/src/main/res/layout/activity_recycler_view.xml
@@ -0,0 +1,57 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/activity_view_model.xml b/app/src/main/res/layout/activity_view_model.xml
new file mode 100644
index 00000000..7f5ea6f8
--- /dev/null
+++ b/app/src/main/res/layout/activity_view_model.xml
@@ -0,0 +1,77 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/item_recycler_view_lesson.xml b/app/src/main/res/layout/item_recycler_view_lesson.xml
new file mode 100644
index 00000000..40885c8b
--- /dev/null
+++ b/app/src/main/res/layout/item_recycler_view_lesson.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
diff --git a/app/src/main/res/raw/text_constraint_layout_java.txt b/app/src/main/res/raw/text_constraint_layout_java.txt
new file mode 100644
index 00000000..4ea79db8
--- /dev/null
+++ b/app/src/main/res/raw/text_constraint_layout_java.txt
@@ -0,0 +1,8 @@
+ConstraintLayoutActivity binding = ActivityConstraintLayoutBinding.inflate(getLayoutInflater());
+setContentView(binding.getRoot());
+
+binding.buttonStart.setOnClickListener(view ->
+ Toast.makeText(this, "Start constrained", Toast.LENGTH_SHORT).show());
+
+binding.buttonEnd.setOnClickListener(view ->
+ Toast.makeText(this, "End constrained", Toast.LENGTH_SHORT).show());
diff --git a/app/src/main/res/raw/text_constraint_layout_xml.txt b/app/src/main/res/raw/text_constraint_layout_xml.txt
new file mode 100644
index 00000000..4f801691
--- /dev/null
+++ b/app/src/main/res/raw/text_constraint_layout_xml.txt
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/raw/text_recycler_view_java.txt b/app/src/main/res/raw/text_recycler_view_java.txt
new file mode 100644
index 00000000..e5c28d81
--- /dev/null
+++ b/app/src/main/res/raw/text_recycler_view_java.txt
@@ -0,0 +1,10 @@
+binding.recyclerViewPreview.setLayoutManager(new LinearLayoutManager(this));
+
+List lessons = Arrays.asList(
+ "Linear Layout",
+ "Constraint Layout",
+ "RecyclerView",
+ "ViewModel"
+);
+
+binding.recyclerViewPreview.setAdapter(new RecyclerViewPreviewAdapter(lessons));
diff --git a/app/src/main/res/raw/text_recycler_view_xml.txt b/app/src/main/res/raw/text_recycler_view_xml.txt
new file mode 100644
index 00000000..f44f425a
--- /dev/null
+++ b/app/src/main/res/raw/text_recycler_view_xml.txt
@@ -0,0 +1,6 @@
+
diff --git a/app/src/main/res/raw/text_view_model_java.txt b/app/src/main/res/raw/text_view_model_java.txt
new file mode 100644
index 00000000..22eb6cc9
--- /dev/null
+++ b/app/src/main/res/raw/text_view_model_java.txt
@@ -0,0 +1,6 @@
+CounterViewModel counterViewModel = new ViewModelProvider(this).get(CounterViewModel.class);
+
+binding.incrementButton.setOnClickListener(view -> counterViewModel.incrementCounter());
+
+counterViewModel.getCounter().observe(this, value ->
+ binding.counterValue.setText(getString(R.string.view_model_counter_value, value)));
diff --git a/app/src/main/res/raw/text_view_model_xml.txt b/app/src/main/res/raw/text_view_model_xml.txt
new file mode 100644
index 00000000..e8dfb76e
--- /dev/null
+++ b/app/src/main/res/raw/text_view_model_xml.txt
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 0d03c618..a9ea1704 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -162,6 +162,15 @@
Table layout
+ Constraint layout
+
+ RecyclerView
+
+ ViewModel
+ Increment counter
+ Counter: 0
+ Counter: %1$d
+
Grid view
Image view
@@ -404,6 +413,9 @@
A linear layout is a view group that arranges its children in a single, linear direction, either horizontally or vertically. The orientation of the layout can be specified using the android:orientation attribute. A linear layout can be used to create a variety of user interfaces, such as lists, buttons, and text fields.
A relative layout is a layout manager in Android that positions its child views relative to each other or to the parent layout. This makes it a very versatile layout manager, as it can be used to create a wide variety of layouts.
Table layout is the process of arranging the cells, rows, and columns of a table in a visually appealing and functional way.
+ Build flexible UI arrangements by constraining views relative to each other and to the parent container.
+ Display large or dynamic lists efficiently using RecyclerView with a ViewHolder-based adapter.
+ Store and expose screen state across configuration changes with Jetpack ViewModel and LiveData.
A grid view is a view group that displays items in a two-dimensional scrolling grid. Grid views are often used to display images, lists, or other types of data in a grid-like format.
An Android ImageView is a view used to display images. It is a subclass of the Android View class and is used to show images in applications. ImageViews are used to display images such as graphics or photos. They can be used to display static images or to display images that are updated at runtime.
A View that displays web pages. Basic usage. In most cases, it is recommended to use a standard web browser, like Chrome, to deliver content to the user.
@@ -444,6 +456,9 @@
Your donation helps keep the app running and improve features. Thank you for your generosity.
Learn how to use progress bars in Android with this interactive lesson. This lesson includes two sections: one for a horizontal progress bar and one for a circular progress bar. In each section, you can see how the progress bar updates as a download progresses. You can also view the code for the lesson by clicking on the floating action button at the bottom of the screen.
Spinners present a dropdown menu that keeps your layout compact while still offering multiple choices. This lesson shows how to build a spinner backed by a string array, listen for selection changes, and surface the user\'s choice in the UI.
+ ConstraintLayout lets you place views by defining relationships between anchors. This approach helps you build complex responsive screens with a flat view hierarchy.
+ RecyclerView is designed for showing scrollable lists with high performance. It recycles item views and separates item rendering logic into an adapter.
+ ViewModel keeps UI state alive during configuration changes and separates state handling from your Activity or Fragment.
Android is a mobile operating system developed by Google. It was first released as a beta version on November 5, 2007 and the first commercial version, Android 1.0, was launched on September 23, 2008. Android is based on a modified version of the Linux kernel and other open source software.\n\nAndroid Studio is the official integrated development environment (IDE) for Android app development. It was announced by Google at its I/O conference on May 15, 2013 and released for public use on December 8, 2014. Android Studio is based on IntelliJ IDEA, a popular Java IDE.
Android is not only an operating system, but also a platform that offers a range of features and capabilities for users and developers. Some of the features of Android include:\n\n- Near Field Communication (NFC), which allows you to share data, make payments, and connect with other devices wirelessly.\n- Alternate keyboards, which let you customize your input method with different layouts, languages, and themes.\n- IR transmission, which enables you to use your phone as a remote control for TVs, air conditioners, and other appliances.\n- No-touch control, which lets you perform actions on your phone without touching the screen by using gestures or voice commands.\n- Automation, which allows you to set up routines and triggers for your phone to perform certain tasks automatically.\n- Wireless app downloads, which let you install apps from your computer or web browser without connecting your phone with a cable.\n- Storage and battery swap, which give you the option to expand your phone\'s memory or replace its battery easily.\n- Custom home screen, which lets you personalize your phone\'s appearance with widgets, wallpapers, icons, and launchers.\n\nAndroid Studio is the best tool for developing Android apps. It offers many features and benefits for developers such as:\n\n- Code editor with syntax highlighting, code completion, refactoring, debugging, testing, and linting tools.\n- Layout editor with drag-and-drop interface for designing user interfaces.\n- Emulator with fast boot and snapshot support for testing apps on different devices and configurations.\n- Firebase integration with services such as authentication, database, storage, analytics, crash reporting, and more. \n- Gradle-based build system with dependency management,\ncustomization,\noptimization,\nsigning,\ndistribution options, and more. \n\nWith Android Studio,\nyou can create amazing apps for Android devices using Java,\na powerful and widely-used programming language.
A Chronometer is a specialized widget in the Android framework that provides a timer-like functionality for displaying elapsed time. It can be configured to count up or down, and is commonly used in applications that require timekeeping, such as stopwatch or countdown timer apps. The Chronometer class is derived from the TextView class, which means that it inherits all of the properties and methods of a TextView. This allows developers to easily customize the appearance of the Chronometer, including its text size, color, and font.
diff --git a/app/src/main/res/xml/preferences_android_studio.xml b/app/src/main/res/xml/preferences_android_studio.xml
index 3551983e..d99c7a6b 100644
--- a/app/src/main/res/xml/preferences_android_studio.xml
+++ b/app/src/main/res/xml/preferences_android_studio.xml
@@ -87,6 +87,15 @@
android:targetClass="com.d4rk.androidtutorials.java.ui.screens.android.lessons.data.room.RoomActivity"
android:targetPackage="com.d4rk.androidtutorials.java" />
+
+
+
+
+
+
+
+
+