I have a simple custom multi select items dialog. If number of items is small, then the dialog works fine and shows OK and Cancel buttons at the bottom. But if there are many items (so you have to scroll the list) - no buttons are shown. I've searched the SO for my problem with no luck. I've tested my dialog on Android API 27..29 - it's the same. Maybe I'm missing something important in the layout properties etc...
Here is my code and xml:
package ru.vitvlkv.myapp.gui;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.fragment.app.DialogFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
import java.util.Set;
import ru.vitvlkv.myapp.R;
import ru.vitvlkv.myapp.playlists.Exercise;
public class SelectExercisesDialog extends DialogFragment {
private static final String TAG = SelectExercisesDialog.class.getSimpleName();
private final String message;
private final List<Exercise> exercises;
private RecyclerView recyclerView;
private final SelectExercisesDialog.OnOKClickListener onOKButtonClick;
private final Set<String> selectedExercisesIds;
public interface OnOKClickListener {
void onClick(Set<String> exerciseIds);
}
public SelectExercisesDialog(String message, List<Exercise> exercises, Set<String> selectedExercisesIds,
final SelectExercisesDialog.OnOKClickListener onButtonOKClick) {
this.message = message;
this.exercises = exercises;
this.selectedExercisesIds = selectedExercisesIds;
this.onOKButtonClick = onButtonOKClick;
}
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
LayoutInflater inflater = requireActivity().getLayoutInflater();
View view = inflater.inflate(R.layout.select_exercises_dialog, null);
recyclerView = view.findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(new AllExercisesAdapter(exercises, selectedExercisesIds));
setRetainInstance(true);
return new AlertDialog.Builder(getActivity())
.setView(view)
.setMessage(message)
.setPositiveButton(R.string.dialog_button_ok, (DialogInterface dialog, int id) -> {
onOKButtonClick.onClick(selectedExercisesIds);
})
.setNegativeButton(R.string.dialog_button_cancel, (DialogInterface dialog, int id) -> {
})
.create();
}
private static class AllExercisesAdapter extends RecyclerView.Adapter<ExerciseViewHolder> {
private final List<Exercise> exercises;
private final Set<String> checkedExercisesIds;
public AllExercisesAdapter(List<Exercise> exercises, Set<String> checkedExercisesIds) {
this.exercises = exercises;
this.checkedExercisesIds = checkedExercisesIds;
}
#NonNull
#Override
public ExerciseViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.select_exercise_item_view, parent, false);
return new ExerciseViewHolder(view, checkedExercisesIds);
}
#Override
public void onBindViewHolder(#NonNull ExerciseViewHolder holder, int position) {
Exercise exercise = exercises.get(position);
holder.setExercise(exercise);
}
#Override
public int getItemCount() {
return exercises.size();
}
}
private static class ExerciseViewHolder extends RecyclerView.ViewHolder {
private Exercise exercise = null;
private final TextView textView;
public final CheckBox checkBox;
private final Set<String> checkedExercisesIds;
public ExerciseViewHolder(#NonNull View view, Set<String> checkedExercisesIds) {
super(view);
this.checkedExercisesIds = checkedExercisesIds;
textView = view.findViewById(R.id.textView);
checkBox = view.findViewById(R.id.checkBox);
checkBox.setOnCheckedChangeListener((compoundButton, isChecked) -> {
if (isChecked) {
checkedExercisesIds.add(exercise.getId());
} else {
checkedExercisesIds.remove(exercise.getId());
}
});
}
public void setExercise(Exercise exercise) {
this.exercise = exercise;
textView.setText(exercise.getName());
checkBox.setChecked(checkedExercisesIds.contains(exercise.getId()));
}
}
}
layout/select_exercises_dialog.xml:
<?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">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
layout/select_exercise_item_view.xml:
<?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"
android:layout_width="match_parent"
android:layout_height="#dimen/list_item_height"
android:layout_marginLeft="#dimen/margin_medium"
android:layout_marginRight="#dimen/margin_medium"
android:gravity="center_vertical">
<androidx.constraintlayout.widget.ConstraintLayout
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_margin="#dimen/margin_medium"
android:text="MyExercise"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
And the Exercise class is just a POJO:
package ru.vitvlkv.myapp.playlists;
public class Exercise {
private final String id;
private final String name;
private Exercise(String id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public String getId() {
return id;
}
}
How can I fix this and make the dialog to show OK Cancel buttons in all the cases?
Any help is appreciated.
Thank you!
P.S. The screenshot of the dialog:
If you are Using dialog fragment It's fragment in style of dialog with the some of the dialog specs now if you want to add the ok and cancel you have two chooses
extend the class from AlertDialog.Builder and on create add the positive and the negative button handler and the text
example about the code will be look like this
class ExampleDialog(context: Context) : AlertDialog.Builder(context) {
private val view by lazy {
LayoutInflater.from(context).inflate(R.layout.dialog_exmaple, null, false)
}
override fun setView(layoutResId: Int): AlertDialog.Builder {
// do the recylceview init from the view code here
return super.setView(view)
}
override fun setPositiveButton(
text: CharSequence?,
listener: DialogInterface.OnClickListener?
): AlertDialog.Builder {
return super.setPositiveButton(
context.getText(R.string.action_ok)
) { p0, p1 ->
}
}
override fun setNegativeButton(
text: CharSequence?,
listener: DialogInterface.OnClickListener?
): AlertDialog.Builder {
return super.setNegativeButton(
context.getText(R.string.action_cancel)
) { p0, p1 ->
}
}
}
note I don't like this way allot
you can just add inside you'r xml two button's to the bottom of the recycle-view and add the text to them like ok and cancel and handle the onClick by high order function or by interface it's up to you I can show you and example below
I prefer this code more clean for me and add click listener in the dialogFragment class
<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">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/listData"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="#id/actionOk"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.button.MaterialButton
android:id="#+id/actionOk"
style="#style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="#string/action_ok"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="#id/listData" />
<com.google.android.material.button.MaterialButton
android:id="#+id/actionCancel"
style="#style/Widget.MaterialComponents.Button.OutlinedButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="16dp"
android:text="#string/action_cancel"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="#id/actionOk"
app:layout_constraintTop_toBottomOf="#id/listData" />
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val dialog = super.onCreateDialog(savedInstanceState)
val root = ConstraintLayout(activity)
root.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialog.setContentView(root)
dialog.window?.let {
it.setBackgroundDrawable(ColorDrawable(Color.TRANSPARENT))
it.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
it.setWindowAnimations(R.style.DialogAnimationNormal)
}
dialog.setCanceledOnTouchOutside(true)
return dialog
}
I improvised around the solution suggested by #radesh and came to this (still it's not exactly what I need):
<?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/linearLayout3"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="150dp">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
This layout at least displays the OK Cancel buttons and the list with items. But still in this case my dialog doesn't want to occupy all the available space of the device screen. The list recyclerView is very limited (it's only about 150dp in height). Of course I want the dialog to occupy as much space as available.
<?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"
android:minHeight= "200dp">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<?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"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/margin_medium"
android:layout_marginRight="#dimen/margin_medium"
android:gravity="center_vertical">
<androidx.constraintlayout.widget.ConstraintLayout
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_margin="#dimen/margin_medium"
android:text="MyExercise"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<CheckBox
android:id="#+id/checkBox"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
Related
I am working on this application and I'm trying to show my "expenses" database data in my personal fragment. I have created a recycler view file to replace the default layout. I am struggling to make this work. Can anyone help with the FirebaseRecycler Adapter and the holder class? I am not able to make this work, my fragment display the default layout with no information. I have tried and follow some codes but it is not working.
here is my personal fragment where the recycler view should appear
package uk.brighton.ama75.project;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.TextView;
import com.firebase.ui.database.FirebaseRecyclerAdapter;
import com.firebase.ui.database.FirebaseRecyclerOptions;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.Query;
import java.time.chrono.JapaneseDate;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
public class personalFragment extends Fragment {
private FirebaseAuth mAuth;
private String currentUserID;
private DatabaseReference databaseReference;
private RecyclerView recyclerView;
private Adapter adapter;
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View myView = inflater.inflate(R.layout.fragment_personal, container, false);
mAuth = FirebaseAuth.getInstance();
currentUserID = mAuth.getCurrentUser().getUid();
databaseReference = FirebaseDatabase.getInstance().getReference().child("Expenses").child(currentUserID);
recyclerView = myView.findViewById(R.id.recycler_expense);
LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity());
layoutManager.setStackFromEnd(true);
layoutManager.setReverseLayout(true);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
return myView;
}
#Override
public void onStart() {
super.onStart();
Query query = FirebaseDatabase.getInstance()
.getReference()
.child("expenses")
.limitToLast(5);
FirebaseRecyclerOptions<PersonalExpenses> options =
new FirebaseRecyclerOptions.Builder<PersonalExpenses>()
.setQuery(query, PersonalExpenses.class)
.build();
FirebaseRecyclerAdapter adapter = new FirebaseRecyclerAdapter<PersonalExpenses, MyViewHolder>(options) {
#Override
protected void onBindViewHolder(#NonNull MyViewHolder holder, int position, #NonNull PersonalExpenses model) {
holder.setDate(model.getDate());
holder.setDescription(model.getDescription());
holder.setAmount(model.getAmount());
holder.setType(model.getType());
}
#NonNull
#Override
public MyViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.expense_recycler, parent, false);
return new MyViewHolder(view);
}
};
recyclerView.setAdapter(adapter);
}
#Override
public void onStop() {
super.onStop();
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
private final View mView;
public MyViewHolder(View itemView) {
super(itemView);
mView = itemView;
}
private void setDate(String date) {
TextView mDate = mView.findViewById(R.id.date_income);
mDate.setText(date);
}
private void setType(String type) {
TextView mType = mView.findViewById(R.id.type_txt);
mType.setText(type);
}
private void setDescription(String description) {
TextView mNote = mView.findViewById(R.id.note_txt);
mNote.setText(description);
}
private void setAmount(String amount) {
TextView mAmount = mView.findViewById(R.id.amount_income);
String stramount = String.valueOf(amount);
mAmount.setText(stramount);
}
}
}
This is the expenses recycler view file
<?xml version="1.0" encoding="utf-8"?>
<androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/expense_recycler"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:elevation="5dp"
app:cardElevation="5dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="5dp"
android:orientation="horizontal">
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1">
<TextView
android:id="#+id/date_income"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="6 June 2019"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="2">
<TextView
android:id="#+id/type_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:text="Type"
android:textAlignment="center"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold" />
<TextView
android:id="#+id/note_txt"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/type_txt"
android:text="#string/description"
android:textAlignment="center"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold" />
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="3
">
<TextView
android:id="#+id/amount_income"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="0000"
android:textAlignment="center"
android:textAppearance="?android:textAppearanceSmall"
android:textStyle="bold" />
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
This is the personal layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:background="#FFF1F3FC"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
app:cardElevation="5dp"
android:elevation="10dp"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="1"
android:gravity="center"
android:layout_margin="10dp"
android:layout_height="wrap_content"
tools:ignore="Suspicious0dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="#android:color/black"
android:id="#+id/expenses"
android:text="expense"/>
</RelativeLayout>
<RelativeLayout
android:layout_width="0dp"
android:layout_weight="3"
android:gravity="center"
android:layout_margin="10dp"
android:layout_height="wrap_content"
tools:ignore="Suspicious0dp">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/expense_txt"
android:textAppearance="?android:textAppearanceMedium"
android:textColor="#android:color/black"
android:text="000.00"/>
</RelativeLayout>
</LinearLayout>
</androidx.cardview.widget.CardView>
<androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:id="#+id/recycler_expense"
android:layout_height="match_parent"/>
</LinearLayout>
I believe you are missing these two main code.
Set adapter.startListening() inside onStart()
Set adapter.stopListening() inside onStop()
Make sure to put the code before the scope end of onStart() as you are performing a lot of operations and setting your adapter above.
I wanna have same fab transformation behavior as shown in
Material Website in Full Screen (or morph) section.
I have tried default FabTransformationScrimBehavior and FabTransformationSheetBehavior. but scrim behavior doesn't do anything and sheet behavior don't animate just like I wanted and also it reduce the elevation of the fab to value 0f. and I haven't found any way to unexpand fab. and I wanna know how to use fab transformation behavior. Actually I didn't find any doc on how to use it. So Please help
Code
This is the code that I used:
this is the code of first activity:-
final FloatingActionButton actionButton = findViewById(R.id.add_fab);
actionButton.setOnClickListener(view -> {
actionButton.setExpanded(!actionButton.isExpanded());
});
And this is the xml of first activity:-
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="#style/AppTheme.AppBarOverlay">
<include layout="#layout/include_generic_toolbar" />
</com.google.android.material.appbar.AppBarLayout>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/list_rv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="76dp"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
tools:listitem="#layout/media_list_item_card" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/add_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
android:includeFontPadding="false"
android:text="Add Media"
android:textAllCaps="false"
android:visibility="visible"
app:srcCompat="#drawable/ic_add_24"/>
<com.google.android.material.circularreveal.CircularRevealFrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"
app:layout_behavior="com.google.android.material.transformation.FabTransformationSheetBehavior"
>
<fragment
android:id="#+id/fab_transformation"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="com.zimong.ssms.fragments.AddMediaFragment"
/>
</com.google.android.material.circularreveal.CircularRevealFrameLayout>
And the code of AddMediaFragment(second screen):-
package com.zimong.ssms.fragments;
import android.app.DatePickerDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.DialogFragment;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.zimong.ssms.R;
import com.zimong.ssms.common.model.User;
import com.zimong.ssms.extended.CallbackHandlerImpl;
import com.zimong.ssms.model.Source;
import com.zimong.ssms.model.ZResponse;
import com.zimong.ssms.service.AppService;
import com.zimong.ssms.service.ServiceLoader;
import com.zimong.ssms.util.Constants;
import com.zimong.ssms.util.Util;
import java.util.Calendar;
import java.util.Date;
import retrofit2.Call;
import retrofit2.Response;
public class AddMediaFragment extends DialogFragment {
private ArrayAdapter<Source> adapter;
private TextView source;
private int checkedItem = 0;
private TextView mediaDate;
private Date currentSelectedDate;
public static AddMediaFragment newInstance() {
AddMediaFragment fragment = new AddMediaFragment();
Bundle bundle = new Bundle();
fragment.setArguments(bundle);
return fragment;
}
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setStyle(DialogFragment.STYLE_NO_FRAME, R.style.AppTheme_Light);
setHasOptionsMenu(true);
}
private void getSources() {
final User user = Util.getUser(getActivity());
AppService service = ServiceLoader.createService(AppService.class);
Call<ZResponse> call = service.mediaGallerySources(Constants.DEFAULT_PLATFORM, user.getToken());
call.enqueue(new CallbackHandlerImpl<Source[]>(getActivity(), true, true, Source[].class) {
#Override
protected void failure(Throwable t) {
}
#Override
protected void failure(Response<ZResponse> response) {
}
#Override
protected void success(Source[] response) {
if (response.length > 0) {
source.setText(response[0].getName());
}
adapter = new ArrayAdapter<Source>(getContext(), R.layout.dialog_singlechoice_item, response) {
#Override
public long getItemId(int position) {
return getItem(position).getPk();
}
};
}
});
}
#Nullable
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.activity_add_media, container, false);
TextView headline = view.findViewById(R.id.media_headline);
Toolbar toolbar = view.findViewById(R.id.toolbar);
((AppCompatActivity) getContext()).setSupportActionBar(toolbar);
source = view.findViewById(R.id.source);
mediaDate = view.findViewById(R.id.media_date);
Calendar fromDateInstance = Calendar.getInstance();
currentSelectedDate = fromDateInstance.getTime();
mediaDate.setText(Util.formatDate(fromDateInstance.getTime(), "dd MMM yyyy"));
final DatePickerDialog fromDatePicker = new DatePickerDialog(getContext(), (datePicker, year, month, date) -> {
fromDateInstance.set(Calendar.YEAR, year);
fromDateInstance.set(Calendar.MONTH, month);
fromDateInstance.set(Calendar.DATE, date);
currentSelectedDate = fromDateInstance.getTime();
mediaDate.setText(Util.formatDate(currentSelectedDate, "dd MMM yyyy"));
}, fromDateInstance.get(Calendar.YEAR), fromDateInstance.get(Calendar.MONTH), fromDateInstance.get(Calendar.DATE));
mediaDate.setOnClickListener(v -> fromDatePicker.show());
source.setOnClickListener(v -> alertDialog());
getSources();
return view;
}
#Override
public boolean onOptionsItemSelected(#NonNull MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
getActivity().onBackPressed();
return true;
}
return super.onOptionsItemSelected(item);
}
private void alertDialog() {
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(getContext());
builder.setTitle("Source");
builder.setSingleChoiceItems(adapter, checkedItem, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
source.setText(adapter.getItem(which).getName());
checkedItem = which;
dialog.dismiss();
}
});
builder.show();
}
}
And the xml of Add Media is:-
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/myCoordinatorLayout"
android:layout_width="match_parent"
android:background="#color/white"
android:layout_height="match_parent"
android:orientation="vertical">
<com.google.android.material.appbar.AppBarLayout
android:id="#+id/bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$Behavior"
android:theme="#style/AppTheme.AppBarOverlay">
<include layout="#layout/include_toolbar" />
</com.google.android.material.appbar.AppBarLayout>
<include
layout="#layout/content_add_media"
android:layout_width="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"
android:layout_height="match_parent"/>
</com.google.android.material.circularreveal.coordinatorlayout.CircularRevealCoordinatorLayout>
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.google.android.material.circularreveal.CircularRevealLinearLayout
android:id="#+id/dial"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:orientation="horizontal"
android:layout_gravity="bottom|center_horizontal"
android:visibility="invisible"
android:layout_marginBottom="16dp"
app:layout_anchor="#id/fab"
app:layout_anchorGravity="top|center_horizontal"
android:background="#color/colorPrimary"
app:layout_behavior="com.google.android.material.transformation.FabTransformationSheetBehavior">
<ImageButton
android:id="#+id/back"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/back"/>
</com.google.android.material.circularreveal.CircularRevealLinearLayout>
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="#dimen/fab_margin"
android:backgroundTint="#color/colorPrimary"
app:srcCompat="#android:drawable/ic_dialog_email"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
For the FabTransformationSheetBehavior to work, you need to change the isExpanded value.
on change of this value, expand and collapse animation will be called and visibility of the linearlayout and fab button will be handled automatically. Don't change visibility manually as this would block transformation animation.
Use back button to transform back to FAB.
val fab: FloatingActionButton = findViewById<FloatingActionButton>(R.id.fab)
fab.setOnClickListener { fab.isExpanded = !fab.isExpanded } // this sets isExpanded as true
val back = findViewById<ImageButton>(R.id.back)
back.setOnClickListener{ fab.isExpanded = !fab.isExpanded } // this sets isExpanded as false
I am attempting to make a custom view that uses buttons, however, the android:Onclick for the two buttons cause the app to crash. The ClickListeners don't work either.
The error I am getting from running the debug tool is :
java.lang.IllegalStateException: Could not find a method addMenu(View) in the activity class com.android.tools.fd.runtime.BootstrapApplication for onClick handler on view class android.widget.Button with id 'increase'
This is My java code :
public class MenuItems extends LinearLayout{
private View plusButton;
private View negateButton;
private EditText priceBox;
private TextView total;
private TextView name;
private int totalItems;
private double totalPrice;
private double price;
public MenuItems(Context context) {
super(context);
init();
}
public MenuItems(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public void init()
{
LayoutInflater inflater=LayoutInflater.from(getContext());
inflater.inflate(R.layout.menu_item,this);
plusButton=findViewById(R.id.increase);
negateButton=findViewById(R.id.decrease);
total=(TextView)findViewById(R.id.total);
name=(EditText)findViewById(R.id.ItemName);
priceBox=(EditText)findViewById(R.id.Price) ;
total.setText("5");
negateButton.setBackgroundColor(Color.RED);
plusButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
plusButton.setBackgroundColor(Color.RED);
increase();
}
});
negateButton.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
decrease();
negateButton.setBackgroundColor(Color.RED);
}
});
price=0;
totalItems=0;
upDateTotal();
String pString=priceBox.getText().toString();
price=Double.parseDouble(pString);
}
public void increase(View view)
{
totalItems++;
upDateTotal();
System.out.println("plus");
plusButton.setBackgroundColor(Color.RED);
}
public void decrease(View v)
{
if(totalItems>0)
totalItems--;
upDateTotal();
System.out.println("minus");
}
This is all of my xml :
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/menu_items"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.mohs.joey.seniorproject.MenuItems">
<LinearLayout
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="textPersonName"
android:ems="10"
android:id="#+id/ItemName"
android:layout_weight="1"
android:textColor="#color/colorAccent"
android:text="name" />
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:inputType="numberDecimal"
android:ems="10"
android:id="#+id/Price"
android:textColor="#color/colorAccent"
android:hint="Price"
android:shadowColor="#color/colorAccent"
android:text="0.00" />
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<Button
android:text="-"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:id="#+id/decrease"
android:layout_weight="1"
android:backgroundTint="#color/colorAccent"
android:onClick="increase"/>
<TextView
android:text="Amount"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/total"
android:layout_weight="1"
android:textColor="#color/colorAccent" />
<Button
android:text="+"
android:layout_width="50dp"
android:layout_height="wrap_content"
android:id="#+id/increase"
android:layout_weight="1"
android:backgroundTint="#color/colorAccent"
android:elevation="0dp"
android:onClick="increase" />
</LinearLayout>
</LinearLayout>
</RelativeLayout>
I access MenuItems in this Method in a separate class :
public void addMenu(View view)
{
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.menu_item, null);
v.setId(menu);
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.backLayer);
insertPoint.addView(v, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
menu++;
}
This is my new main activity:
package com.mohs.joey.seniorproject;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.PopupWindow;
import android.widget.TextView;
public class ConcessionMenus extends AppCompatActivity {
int menu=0;
private View plusButton;
private View negateButton;
private EditText priceBox;
private TextView total;
private TextView name;
private int totalItems;
private double totalPrice;
private double price;
PopupWindow popup;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_concession_menus);
plusButton=findViewById(R.id.increase);
negateButton=findViewById(R.id.decrease);
total=(TextView)findViewById(R.id.total);
name=(EditText)findViewById(R.id.ItemName);
priceBox=(EditText)findViewById(R.id.Price) ;
// TextView totalPrice=(TextView)findViewById(R.id.totalPrice);
}
public void addMenu(View view)
{
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vw = vi.inflate(R.layout.menu_item, null);
vw.setId(menu);
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.backLayer);
insertPoint.addView(vw, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
menu++;
}
public Intent newIntent()
{
Intent intent=new Intent(this,Menu.class);
return intent;
}
public void increase(View v)
{
totalItems++;
upDateTotal();
System.out.println("plus");
plusButton.setBackgroundColor(Color.RED);
}
public void decrease(View v)
{
if(totalItems>0)
totalItems--;
upDateTotal();
System.out.println("minus");
}
public void upDateTotal()
{
total.setText(""+totalItems);
totalPrice=price*totalItems;
}
public double totalPrice()
{
return totalPrice;
}
}
Any help would be appreciated.
The problem is when the button want to perform the action when you click on it , it should be able to find the method increase() in your MainActivity class , since the method increase() is on an other class , the button will never find the method and they will crash because you set the your layout xml to your main activity not for the class MenuItem , to fix that just move these to methods to your MainActivity class
OR
Pass a reference of your buttons to the class MenuItems and do what you want there
PS : the ids can be found by typing R.id , but you cannot work with these id since you set the content view to your MainActivity
I want to have my items in listview looking like a conversation in messenger.
There is simple code of recieving messages:
if (arrayList2.get(y).toString().equals(myEmail)) {
arrayList.add(arrayList2.get(k).toString());
} else if (arrayList2.get(y).toString().equals(recipientEmail)) {
arrayList.add(arrayList2.get(k).toString());
}
arrayAdapter.notifyDataSetChanged();
When array.get.....equals(myEmail), the messages are from me so, they should stay like they are. When ...equals(recipientEmail), I want text to be on the right of the screen/or listview and have an background of image, like classically in messenger
I will recommend you to add all Your messages in one Arraylist and create two layouts one of sender with left gravity and one of receiver with right gravity then make a logic like-
if(arraylist.get(position).getUserID==currentUser){
senderLayout.setvisibility(View.VISIBLE);
senderTextview.setText(arraylist.get(position).getText)
}
else{
senderLayout.setvisibility(View.GONE);
receiverLayout.setvisibility(View.VISIBLE);
recieverTextview.setText(arraylist.get(position).getText)
}
Do this in getView method of your adapter.
You may create a row with 2 views. One on left and other on right. Based on your if condition you can make one of the views gone and the other visible. At any time only one view in that will be visible.
Another way of doing is to use single view in it and setting (left/right) gravity based on your condition.
You may refer http://www.uandblog.com/How-to-Create-Chat-Application-using-Firebase-in-Android-. See MainActivity.java and item.xml
Use two TextView in raw file
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.github.library.bubbleview.BubbleTextVew
android:id="#+id/tv_chatRecive"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="7dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="35dp"
android:layout_marginTop="8dp"
android:padding="10dp"
android:textColor="#android:color/white"
android:visibility="gone"
app:angle="5dp"
app:arrowHeight="12dp"
app:arrowLocation="left"
app:arrowPosition="5dp"
app:arrowWidth="12dp"
app:bubbleColor="#color/colorPrimary" />
<com.github.library.bubbleview.BubbleTextVew
android:id="#+id/tv_chatSend"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginBottom="7dp"
android:layout_marginLeft="35dp"
android:layout_marginRight="10dp"
android:layout_marginTop="8dp"
android:padding="10dp"
android:textColor="#color/text_labelColoe"
android:visibility="gone"
app:angle="5dp"
app:arrowHeight="12dp"
app:arrowLocation="right"
app:arrowPosition="5dp"
app:arrowWidth="12dp"
app:bubbleColor="#android:color/white" />
</RelativeLayout>
and in Adapter class use this kind of logic to manage textview
#Override
public void onBindViewHolder(final CustomViewHolder customViewHolder, final int position) {
if (listChat.get(position).CHAT_SEND_RECIVE.equalsIgnoreCase("right")) {
customViewHolder.tvSend.setVisibility(View.VISIBLE);
customViewHolder.tvRecive.setVisibility(View.GONE);
customViewHolder.tvSend.setText(listChat.get(position).CHAT_MESSAGE);
} else if (listChat.get(position).CHAT_SEND_RECIVE.equalsIgnoreCase("left")) {
customViewHolder.tvRecive.setVisibility(View.VISIBLE);
customViewHolder.tvSend.setVisibility(View.GONE);
customViewHolder.tvRecive.setText(listChat.get(position).CHAT_MESSAGE);
}
}
Add key in chat responce like just i add right and left
Here is complete example.
Resources under drawable:
activity_main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.example.andrii.myapplication.MainActivity">
<android.support.v7.widget.RecyclerView
android:id="#+id/chat"
android:background="#color/colorAccent"
android:layout_width="match_parent"
android:layout_height="match_parent">
</android.support.v7.widget.RecyclerView>
</RelativeLayout>
Message layout will looks like so (message.xml):
<?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="wrap_content">
<FrameLayout
android:id="#+id/container"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="15dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:paddingRight="10dp"
android:background="#drawable/in_9">
<TextView
android:id="#+id/message"
android:textSize="18sp"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:breakStrategy="balanced"
android:maxWidth="200dp"
android:text="test"
/>
</FrameLayout>
</LinearLayout>
And finally in MainActivity.java :
package com.example.andrii.myapplication;
import android.content.Context;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
import java.util.LinkedList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
List<Message> list= new LinkedList<>();
list.add(new Message(true, "hi"));
list.add(new Message(false, "hello"));
list.add(new Message(true, "how are you"));
list.add(new Message(false, "I'm fine"));
list.add(new Message(false, "Test test test test test"));
RecyclerView view = (RecyclerView) findViewById(R.id.chat);
view.setLayoutManager(new LinearLayoutManager(this));
view.setAdapter(new ChatAdapter(this, list));
}
private class Message {
private boolean misMine;
private String mMessage;
public Message (boolean mine, String message) {
misMine = mine;
mMessage = message;
}
public boolean isMine() { return misMine; }
public String getMessage() { return mMessage; }
}
private class MessageViewHolder extends RecyclerView.ViewHolder {
private View mContainer;
private TextView mMessage;
public MessageViewHolder(View itemView) {
super(itemView);
mMessage = (TextView) itemView.findViewById(R.id.message);
mContainer = itemView.findViewById(R.id.container);
}
public void setMessage(String message) {
mMessage.setText(message);
}
public void setMine(boolean isMine) {
LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) mContainer.getLayoutParams();
params.gravity = isMine ? Gravity.RIGHT : Gravity.LEFT;
mContainer.setBackgroundResource(isMine ? R.drawable.out_9 : R.drawable.in_9 );
mContainer.setLayoutParams(params);
}
}
private class ChatAdapter extends RecyclerView.Adapter<MessageViewHolder> {
private List<Message> mMessages;
public ChatAdapter(Context context, List<Message> list) {
mMessages = list;
}
#Override
public MessageViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.message, parent, false);
MessageViewHolder holder = new MessageViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MessageViewHolder holder, int position) {
Message message = mMessages.get(position);
holder.setMessage(message.getMessage());
holder.setMine(message.isMine());
}
#Override
public int getItemCount() {
return mMessages.size();
}
}
}
The result of code above:
I am trying to add a RecyclerView with GridLayoutManagerto my app. Everything works as expected, only problem is it seems the columns are left justified instead of center justified. Any ideas? Thanks in advance!
Here is an image showing how it looks:
Here is the single item layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:background="?android:selectableItemBackgroundBorderless"
android:clickable="true"
android:gravity="center_horizontal"
android:orientation="vertical">
<ImageView
android:id="#+id/iconSpot"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_launcher"
tools:ignore="MissingPrefix" />
<TextView
android:id="#+id/textLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Dummy Text"
android:textSize="16sp" />
</LinearLayout>
And here is the full activity layout:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/totalScreen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="#+id/fab"
android:layout_gravity="bottom|center"
android:gravity="bottom|center_vertical">
<TextView
android:id="#+id/sheetTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#424242"
android:padding="12dp"
android:text="Dummy Title"
android:textSize="18sp" />
<android.support.design.widget.FloatingActionButton
android:id="#+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignTop="#+id/sheetTitle"
android:layout_marginEnd="20dp"
android:layout_marginTop="-28dp"
android:visibility="gone"
app:fabSize="normal" />
<android.support.v7.widget.RecyclerView
android:id="#+id/gridScreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/sheetTitle"
android:background="#424242"
android:gravity="bottom|center"
android:layout_gravity = "center"
android:orientation="vertical"
android:paddingBottom="24dp" />
</RelativeLayout>
Ok! I figured it out, it ended up being the fact that I needed to make the item layout width set as match_parent instead of wrap_content. So that makes it look like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:layout_margin="10dp"
android:background="?android:selectableItemBackgroundBorderless"
android:clickable="true"
android:orientation="vertical">
<ImageView
android:id="#+id/iconSpot"
android:layout_width="44dp"
android:layout_height="44dp"
android:layout_gravity="center_horizontal"
android:src="#drawable/ic_launcher"
tools:ignore="MissingPrefix" />
<TextView
android:id="#+id/textLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Dummy Text"
android:textSize="16sp" />
</LinearLayout>
It is hard to fix with just the layout file since the item layout needs to be inflated and attached to the main layout in order to see the result.
So I decided to recreate it. I made modification to your layout file.
item layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:background="#color/colorPrimary"
android:layout_margin="2dp"
android:clickable="true"
android:orientation="vertical">
<ImageView
android:id="#+id/iconSpot"
android:layout_width="48dp"
android:layout_height="48dp"
android:layout_gravity="center_horizontal"
android:src="#android:drawable/ic_delete"
tools:ignore="MissingPrefix" />
<TextView
android:id="#+id/textLabel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:text="Dummy Text"
android:textSize="16sp" />
</LinearLayout>
Main activity layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/totalScreen"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignTop="#+id/fab"
android:layout_gravity="bottom|center"
android:gravity="bottom|center_vertical">
<TextView
android:id="#+id/sheetTitle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#424242"
android:padding="12dp"
android:text="Dummy Title"
android:textSize="18sp" />
<android.support.v7.widget.RecyclerView
android:id="#+id/gridScreen"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/sheetTitle"
android:background="#424242"
android:gravity="bottom|center"
android:layout_gravity = "center"
android:clipToPadding="false"
android:orientation="vertical"
android:paddingBottom="24dp" />
</RelativeLayout>
Main Activity class. This class (GridSpacingItemDecoration) used for item margin is copied from here
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.GridLayoutManager;
import android.support.v7.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MainActivity extends AppCompatActivity {
private GridLayoutManager layout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
layout = new GridLayoutManager(MainActivity.this, 2);
RecyclerView rView = (RecyclerView)findViewById(R.id.gridScreen);
rView.setHasFixedSize(true);
rView.setLayoutManager(layout);
int spanCount = 2;
int spacing = 50;
boolean includeEdge = true;
rView.addItemDecoration(new GridSpacingItemDecoration(spanCount, spacing, includeEdge));
RecyclerViewAdapter rcAdapter = new RecyclerViewAdapter(MainActivity.this, getAllItemList());
rView.setAdapter(rcAdapter);
}
private List<ItemObject> getAllItemList(){
List<ItemObject> allItems = new ArrayList<ItemObject>();
allItems.add(new ItemObject(android.R.drawable.ic_delete, "United"));
allItems.add(new ItemObject(android.R.drawable.ic_delete, "United"));
allItems.add(new ItemObject(android.R.drawable.ic_delete, "United"));
allItems.add(new ItemObject(android.R.drawable.ic_delete, "United"));
allItems.add(new ItemObject(android.R.drawable.ic_delete, "United"));
allItems.add(new ItemObject(android.R.drawable.ic_delete, "United"));
return allItems;
}
}
RecycleView Adapter Class
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import java.util.List;
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewHolders> {
private List<ItemObject> itemList;
private Context context;
public RecyclerViewAdapter(Context context, List<ItemObject> itemList) {
this.itemList = itemList;
this.context = context;
}
#Override
public RecyclerViewHolders onCreateViewHolder(ViewGroup parent, int viewType) {
View layoutView = LayoutInflater.from(parent.getContext()).inflate(R.layout.list, null);
RecyclerViewHolders rcv = new RecyclerViewHolders(layoutView);
return rcv;
}
#Override
public void onBindViewHolder(RecyclerViewHolders holder, int position) {
holder.displayedImage.setImageResource(itemList.get(position).getImage());
holder.textTitle.setText(itemList.get(position).getTitle());
}
#Override
public int getItemCount() {
return this.itemList.size();
}
}
ViewHolder class
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
public class RecyclerViewHolders extends RecyclerView.ViewHolder implements View.OnClickListener{
public ImageView displayedImage;
public TextView textTitle;
public RecyclerViewHolders(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
displayedImage = (ImageView)itemView.findViewById(R.id.iconSpot);
textTitle = (TextView)itemView.findViewById(R.id.textLabel);
}
#Override
public void onClick(View view) {
}
}
ObjectEntity class
public class ItemObject {
private int image;
private String title;
public ItemObject(int image, String title) {
this.image = image;
this.title = title;
}
public int getImage() {
return image;
}
public void setImage(int image) {
this.image = image;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
The Result is below. Try and see if it works for you.