How to use GridView or GridLayout? - java

I'm creating a seat selection screen but I'm confused, how can I achieve this view. I want to access all selected seats into one single Java file. Plz, help me
EDIT: I've tried this code but with this code, I'm not able to create a view like this into single gridview. Now I'm using 2 separate gridviews for that and two Java files with the separate adapter with them.
Seat_Select.java
public class Seat_Select extends AppCompatActivity {
GridView androidgridview;
int[] image = {
R.drawable.rect_select, R.drawable.rect_select,
R.drawable.rect_select, R.drawable.rect_select,
R.drawable.rect_select, R.drawable.rect_select,
R.drawable.rect_select, R.drawable.rect_select,
R.drawable.rect_select, R.drawable.rect_select,
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_seat__select);
androidgridview = findViewById(R.id.grid);
SeatAdapter seatAdapter=new SeatAdapter(Seat_Select.this,image);
androidgridview.setAdapter(seatAdapter);
androidgridview.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getBaseContext(), "Grid Item " + (position + 1) + " Selected", Toast.LENGTH_LONG).show();
}
});
}
SeatAdapter.java
public class SeatAdapter extends BaseAdapter {
Context context;
LayoutInflater layoutInflater;
int image[];
public SeatAdapter(Context context,int[] image) {
this.context = context;
this.image=image;
layoutInflater=(LayoutInflater.from(context));
}
#Override
public int getCount() {
return image.length;
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
convertView =layoutInflater.inflate(R.layout.grid2col,null);
ImageView imageView= convertView.findViewById(R.id.grid_image);
imageView.setImageResource(image[position]);
return convertView;
}
}
grid2col.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/grid_image"
android:layout_width="30dp"
android:layout_height="70dp">
</ImageView>
</LinearLayout>
activity_seat_select.xml
<RelativeLayout>
<android.support.v7.widget.CardView
android:layout_width="190dp"
android:layout_height="390dp"
android:layout_below="#+id/relativeLayout"
android:layout_centerHorizontal="true"
android:layout_marginTop="24dp">
<GridView
android:id="#+id/grid"
android:layout_width="70dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:columnWidth="30dp"
android:gravity="center"
android:numColumns="2"
android:stretchMode="columnWidth"
android:horizontalSpacing="1dp"
android:verticalSpacing="8dp"
/>
<GridView
android:id="#+id/grid2"
android:layout_width="35dp"
android:numColumns="1"
android:layout_height="match_parent"
android:layout_gravity="start"
android:gravity="center">
</GridView>
</android.support.v7.widget.CardView>
</RelativeLayout>

Please check SeatBookingRecylerView. This example has full source code. It may be helpful for you. This is using RecyclerView.

GridView
GridView is a ViewGroup that displays items in a two-dimensional, scrollable grid. The grid items are automatically inserted to the layout using a ListAdapter. you can GridView in your layout file like below.
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/gridview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:columnWidth="80dp"
android:numColumns="auto_fit"
android:verticalSpacing="16dp"
android:horizontalSpacing="16dp"
android:padding="16dp"
android:stretchMode="columnWidth"
android:gravity="center"
/>
GridLayout
Grid layout is mainly used to align its child views in cells which are the horizontal and vertical intercepts of an invisible line. Each view child is place in a cell and the cells are numbered with the horizontal and vertical indexes.
<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/GridLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:columnCount="3"
android:rowCount="3"
android:orientation="horizontal">
<Space />
<Button
android:id="#+id/button1"
android:layout_gravity="left|top"
android:text="#string/button_name" />
<Button
android:id="#+id/button3"
android:layout_gravity="left|top"
android:text="#string/button_name" />
<Button
android:id="#+id/button2"
android:layout_column="0"
android:layout_gravity="left|top"
android:layout_row="0"
android:text="#string/button_name" />
<Button
android:id="#+id/button4"
android:layout_column="0"
android:layout_gravity="left|top"
android:layout_row="2"
android:text="#string/button_name" />
<Button
android:id="#+id/button5"
android:layout_column="1"
android:layout_row="2"
android:layout_columnSpan="2"
android:layout_gravity="fill"
android:text="#string/button_name" />
</GridLayout>

Related

Remove Excess Space in Gridview

Current Gridview
I want the 3rd image to take up the white space. The gridview looks good when the height of the images are equal but when its unequal it shows blank to match up with the next images height. i just want the below image to come up and fill up the space.
Adapter
public class Adapter extends BaseAdapter {
Context context;
int logos[];
LayoutInflater inflter;
public Adapter(Context applicationContext, int[] logos) {
this.context = applicationContext;
this.logos = logos;
inflter = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return logos.length;
}
#Override
public Object getItem(int i) {
return null;
}
#Override
public long getItemId(int i) {
return 0;
}
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
view = inflter.inflate(R.layout.custom_grid, null); // inflate the layout
ImageView icon = view.findViewById(R.id.icon); // get the reference of ImageView
icon.setImageResource(logos[i]); // set logo images
return view;
}
}
Custom View
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="1dp"
android:orientation="vertical">
<ImageView
android:id="#+id/icon"
android:scaleType="center"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
android:src="#drawable/logo" />
</LinearLayout>
XML
<LinearLayout
android:padding="5dp"
android:orientation="vertical"
android:background="#color/white"
android:layout_below="#id/appbar"
android:layout_width="match_parent"
android:layout_height="match_parent">
<GridView
android:stretchMode="columnWidth"
android:numColumns="2"
android:id="#+id/grid"
android:gravity="center"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
Java
GridView mGridView = findViewById(R.id.grid);
Adapter customAdapter = new Adapter(getApplicationContext(), logos);
mGridView.setAdapter(customAdapter);
mGridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(getApplicationContext(),position,Toast.LENGTH_LONG).show();
}
});
Usually use recycler view but needed columns so switched to gridview. I found sources on making the images equal height. But i dont want that. I dont want it to keep aspect ratio but just fill up all the available space
Solution:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="1dp"
android:orientation="vertical">
<ImageView
android:id="#+id/icon"
android:scaleType="center"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:layout_gravity="center_horizontal"
android:src="#drawable/logo" />
</LinearLayout>

buttons in Onclick Recycler View doesn't work

when Click on Button it suppose to Open a browser but it didn't get to the code to start the Activity
public class RecyclerViewAdapterDetailsScreen extends RecyclerView.Adapter<RecyclerViewAdapterDetailsScreen.ViewHolder> {
private Context mContext;
private int numberOfButtons;
private String [] trailers;
public RecyclerViewAdapterDetailsScreen(Context mContext, int numberOfButtons,String [] trailers) {
this.numberOfButtons=numberOfButtons;
this.mContext = mContext;
this.trailers=trailers;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_listitem2, parent, false);
ViewHolder holder = new ViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, final int position) {
/*** Toast.makeText(mContext, trailers[position]+" From OnBindViewHolder", Toast.LENGTH_SHORT).show();
* Toast is working from Here but no sign from on click
*/
holder.parentlayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view)
{
// TOAST IS NOT WORKING SO THE CODE DOESNT gett HERE...............................
Toast.makeText(mContext, trailers[position], Toast.LENGTH_SHORT).show();
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(trailers[position]));
mContext.startActivity(browserIntent);
}
});
}
#Override
public int getItemCount() {
return trailers.length;
}
public class ViewHolder extends RecyclerView.ViewHolder
{
Button mbutton;
RelativeLayout parentlayout;
public ViewHolder(#NonNull View itemView) {
super(itemView);
mbutton=itemView.findViewById(R.id.button);
parentlayout = itemView.findViewById(R.id.parent_layout2);
}
}
}
layout_listitem2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/parent_layout2"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
/>
</RelativeLayout>
activity_details_screen.xml that has the recyclerview
<?xml version="1.0" encoding="utf-8"?>
<ScrollView 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"
tools:context=".DetailsScreen">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:id="#+id/image_thumbnail"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
/>
<TextView
android:id="#+id/original_title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="25sp"
android:layout_below="#+id/image_thumbnail"
android:layout_centerHorizontal="true"
/>
<TextView
android:id="#+id/overview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/original_title"
android:textSize="18sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="vote average "
android:id="#+id/vote"
android:layout_below="#+id/overview"
android:textStyle="bold"
android:textSize="20sp"/>
<TextView
android:id="#+id/vote_average"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/vote"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="release date"
android:layout_below="#id/vote_average"
android:textStyle="bold"
android:textSize="20sp"
android:id="#+id/release"
/>
<TextView
android:id="#+id/release_date"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/release"
/>
<TextView
android:id="#+id/trailers"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="25sp"
android:layout_below="#+id/release_date"
android:layout_centerHorizontal="true"
android:text="Trailers"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view_details"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="#+id/trailers"
android:padding="8dp"
/>
</RelativeLayout>
</ScrollView>
it has to get in the onClick and start new activity to open youtube app or browser if any missing code you wanna review tell me
Your code is perfect.
Only one problem is here, your parent_layout2 is not getting click-event it is consumed by child(the button).As by Android definition first priority is given to child.
Just update parents width to match_parent. It will work. I have tested your code just now.
Here is your updated xml
layout_listitem2.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/parent_layout2"
>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/button"
/>
</RelativeLayout>
Happy Coding. Please Vote if it works.
Thanks

How to get some components in recycelrview adapter from main layout?

I have recyclerview in activity_main.xml and I have there the image which shows to user - empty or not empty recyclerview. activity_main.xml:
<RelativeLayout
android:id="#+id/main_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:visibility="gone"
android:id="#+id/main_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical" />
<LinearLayout
android:visibility="visible"
android:id="#+id/block_no_alarms"
android:orientation="vertical"
android:layout_centerInParent="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<ImageView
android:src="#drawable/ic_nothing"
android:layout_width="match_parent"
android:layout_height="70dp" />
<TextView
android:text="#string/no_alarms"
android:textColor="#color/colorWhite"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</RelativeLayout>
And I have recyclerview one item xml file
<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
app:cardCornerRadius="7dp"
app:cardBackgroundColor="#color/colorDark"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginTop="8dp"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/tv_time_alarm_one_item"
android:textColor="#color/colorWhite"
android:layout_margin="15dp"
android:textSize="25sp"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<TextView
android:id="#+id/tv_description_alarm_one_item"
android:textColor="#color/colorWhite"
android:layout_toRightOf="#id/tv_time_alarm_one_item"
android:textSize="14sp"
android:maxLines="2"
android:layout_marginRight="60dp"
android:ellipsize="end"
android:layout_centerVertical="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/tv_time_alarm_one_item"
android:layout_marginEnd="60dp" />
<Switch
android:id="#+id/s_switch_alarm_one_item"
android:layout_alignParentRight="true"
android:checked="true"
android:layout_centerVertical="true"
android:layout_margin="15dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true" />
</RelativeLayout>
</android.support.v7.widget.CardView>
And I wanna during long press click to this cardview to delete one item from the recyclerview. Adapter:
public class AlarmsAdapterMain extends RecyclerView.Adapter<AlarmsAdapterMain.ViewHolder> {
private List<String> listTimes = new ArrayList<>();
private List<String> listDescriptions = new ArrayList<>();
private List<Boolean> listStarted = new ArrayList<>(); // checked a switch
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.alarm_item, viewGroup, false);
return new ViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder viewHolder, int i) {
viewHolder.time.setText(listTimes.get(i));
viewHolder.description.setText(listDescriptions.get(i));
viewHolder.aSwitch.setChecked(listStarted.get(i));
}
#Override
public int getItemCount() {
return listTimes.size();
}
public void deleteAll() {
listDescriptions.clear();
listTimes.clear();
listStarted.clear();
}
public void add(String time, String description) {
listTimes.add(time);
listDescriptions.add(description);
listStarted.add(true); // by default
}
class ViewHolder extends RecyclerView.ViewHolder {
private TextView time, description;
private Switch aSwitch;
ViewHolder(#NonNull final View itemView) {
super(itemView);
time = itemView.findViewById(R.id.tv_time_alarm_one_item);
description = itemView.findViewById(R.id.tv_description_alarm_one_item);
aSwitch = itemView.findViewById(R.id.s_switch_alarm_one_item);
// I try to set long listener here
}
}
}
I've done it, but I need to show or hide image or recyclerview if it need. For example, I have one alarm, user deletes it alarm and he sees empty layout but he must see image(LinearLayout) and hide recyclerview. So, how can I do it inside my adapter?
control your arrayLists from outside of your adapter, for example in your activity you should have a list of your data and pass the arrayList to your adapter's constructor, and manipulate your adapter data from activity and just notifyDataChange after any changes on your arrayList. so when you delete data or add some data, you can check your arrayList size in last line of your ad or delete operations (in your activity), and if arrayList size equals to 0 you should do changes on your UI.
also there is another way, you can have an interface that implements in your activity and it should have two methods for zeroMode or nonZeroMode and you can pass this interface to your adapter and invoke these methods when your arrayList size become zero or non-zero in your adapter.

Android - OnClick inside gridview row

I'm trying to launch a activity from a button inside my gridview item, meaning that when user click on gridview Item it should do one function and when the user click on the button inside the gridview item it should do another function, let me elaborate, here is my single item layout that is being populated inside of my gridview;
<android.support.v7.widget.CardView 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:foreground="?android:attr/selectableItemBackground"
android:orientation="horizontal"
app:cardCornerRadius="5dp"
app:cardElevation="3dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<RelativeLayout
android:id="#+id/single_row"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="10dp"
android:paddingTop="10dp">
<com.mikhaellopez.circularimageview.CircularImageView
android:id="#+id/imgFood"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
app:civ_border_color="#ffffff"
app:civ_border_width="2dp"
app:civ_shadow="true"
app:civ_shadow_color="#000000"
app:civ_shadow_radius="10" />
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_toRightOf="#+id/imgFood">
<TextView
android:id="#+id/txtName"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="16sp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/currentid"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:layout_below="#+id/txtName"
android:text="Current ID : "
android:visibility="visible"
/>
<TextView
android:id="#+id/studentid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="ID"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="16sp"
android:layout_below="#+id/txtName"
android:layout_toRightOf="#+id/currentid"
android:layout_marginEnd="30dp"
android:layout_marginRight="30dp"
/>
</RelativeLayout>
<Button
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="end"
android:layout_alignParentRight="true"
android:layout_alignParentEnd="true"
android:id="#+id/editit"
android:background="#android:drawable/btn_dialog"/>
</RelativeLayout>
here is how the above layout looks:
and here is my adapter getview from where I try to do the intent/actions from;
#Override
public View getView(int position, View view, ViewGroup viewGroup) {
View row = view;
ViewHolder holder = new ViewHolder();
if (row == null) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
row = inflater.inflate(layout, null);
holder.txtName = (TextView) row.findViewById(R.id.txtName);
holder.txtPrice = (TextView) row.findViewById(R.id.studentid);
holder.imageView = (CircularImageView) row.findViewById(R.id.imgFood);
holder.dit = (Button) row.findViewById(R.id.editit);
final ViewHolder finalHolder = holder;
holder.dit.setOnClickListener(new View.OnClickListener() {
String getname = finalHolder.txtName.getText().toString();
String gethandicap = finalHolder.txtPrice.getText().toString();
#Override
public void onClick(View v) {
// Do something
Intent editintent = new Intent(context, MainActivity.class);
editintent.putExtra("studentname", getname);
editintent.putExtra("studentid", getID);
context.startActivity(editintent);
}
});
row.setTag(holder);
} else {
holder = (ViewHolder) row.getTag();
}
Sudentdb student = studentsList.get(position);
holder.txtName.setText(student.getName());
holder.txtPrice.setText(student.getID());
if (student.getImage() != null && student.getImage().length > 0) {
Glide.with(context)
.load(student.getImage())
.into(holder.imageView);
} else {
holder.imageView.setImageBitmap(null);
}
return row;
}
The problem I'm having is that the button inside the gridview item is not performing any actions, in log it only says ACTION_DOWN and since I added a button inside the item the item onclick also doesn't work.
EDIT; ADDING GRIDVIEW ONCLICK AND LAYOUT
gridView = (GridView) findViewById(R.id.gridView);
list = new ArrayList<>();
adapter = new StudentListAdapter(this, R.layout.food_items, list);
gridView.setAdapter(adapter);
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String dataFromGrid;
dataFromGrid = ((TextView)(view.findViewById(R.id.txtName))).getText().toString();
Intent i = new Intent(getApplicationContext(), Student.class);
i.putExtra("unfromstudent",dataFromGrid);
startActivity(i);
gridview layout (I have tried focusable and clickable)
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:focusable="true"
>
<GridView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:id="#+id/gridView"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:columnWidth="120dp"
android:gravity="center"
android:layout_margin="2dp"
android:numColumns="1"
/>
</RelativeLayout>
Change you XML, i have tested below xml its works fine with
GridView
<android.support.v7.widget.CardView 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:foreground="?android:attr/selectableItemBackground"
android:orientation="horizontal"
app:cardCornerRadius="5dp"
app:cardElevation="3dp"
app:cardPreventCornerOverlap="false"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="false"
android:orientation="horizontal">
<com.mikhaellopez.circularimageview.CircularImageView
android:id="#+id/imgFood"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_margin="10dp"
app:civ_border_color="#ffffff"
app:civ_border_width="2dp"
app:civ_shadow="true"
app:civ_shadow_color="#000000"
app:civ_shadow_radius="10" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal|center_vertical"
android:layout_weight="1"
android:gravity="center_horizontal|center_vertical"
android:orientation="vertical">
<TextView
android:id="#+id/txtName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:text="Name"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/currentid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/txtName"
android:layout_marginLeft="5dp"
android:layout_marginStart="5dp"
android:text="Current ID : "
android:visibility="visible" />
<TextView
android:id="#+id/studentid"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/txtName"
android:layout_marginEnd="30dp"
android:layout_marginRight="30dp"
android:layout_toRightOf="#+id/currentid"
android:text="ID"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textSize="16sp" />
</LinearLayout>
</LinearLayout>
<LinearLayout
android:layout_width="30dp"
android:layout_height="30dp">
<Button
android:id="#+id/editit"
android:layout_width="30dp"
android:layout_height="30dp"
android:layout_gravity="end"
android:background="#android:drawable/btn_dialog"
android:focusable="false" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
Your Grid View XML will be Like this.
<GridView
android:id="#+id/grid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true">
</GridView>
I don't have enough reputation so i can't comment your question, why don't you use a recyclerview with a gridLayoutManager? You can see a basic example here .
After that you can implement your recyclerview adapter this way:
public class StudentsAdapter extends RecyclerView.Adapter<StudentsAdapter.ViewHolder> {
private final OnStudentItemClickListener mListener;
private Context mContext;
private List<Student> mStudents;
public StudentsAdapter(Context context, List<Student> items, OnStudentItemClickListener listener) {
mContext = context;
mStudents =items;
mListener = listener;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.list_item_student, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final ViewHolder holder, int position) {
Student student = mStudents.get(position);
holder.mTextName.setText(student.getName());
holder.mTextPrice.setText(student.getID());
if (student.getImage() != null && student.getImage().length > 0) {
Glide.with(context)
.load(student.getImage())
.into(holder.imageView);
} else {
holder.imageView.setImageBitmap(null);
}
}
#Override
public int getItemCount() {
return mStudents.size();
}
public interface OnStudentItemClickListener {
void onStudentItemClick(Student student);
void onStudentButtonClick(Student student);
}
public class ViewHolder extends RecyclerView.ViewHolder
implements View.OnClickListener {
TextView mTextName;
TextView mTextPrice;
CircleImageView mImageView;
Button mDit;
public ViewHolder(View view) {
super(view);
mTextName = (TextView) view.findViewById(R.id.txtName);
mTextPrice = (TextView) view.findViewById(R.id.studentid);
mImageView = (CircleImageView) view.findViewById(R.id.imgFood);
mDit = (Button) view.findViewById(R.id.editit);
mDit.setOnClickListener(view1 -> {
if (null != mListener) {
mListener.onStudentButtonClick(mStudents.get(getAdapterPosition()));
}
});
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
if (null != mListener) {
mListener.onStudentItemClick(mStudents.get(getAdapterPosition()));
}
}
}
}

Expanding / Collapsing Cards in Recycler View sometimes result in whitespaces and drawing bugs

The Problem
I have a recycler view with card items. These card items contain only text and are expandable.It looks like this Collapsed Expanded
Now I expand and collapse one of them sometimes and scroll around and somehow there appears now more whitespace between the cards:
Whitespace between cards
Moreover, for cards with long text when I click to collapse them, this appears:
Big Cards
The Code
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">
<com.ramotion.foldingcell.FoldingCell
android:id="#+id/folding_cell"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
app:backSideColor="#F5F5F5">
<FrameLayout
android:id="#+id/cell_content_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="300dp"
android:visibility="gone">
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/movie_card2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
android:minHeight="300dp"
cardview:cardBackgroundColor="#color/card_background"
cardview:cardCornerRadius="1dp"
cardview:cardElevation="4dp"
cardview:cardUseCompatPadding="true">
<RelativeLayout
android:id="#+id/review_item2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:orientation="vertical">
<View
android:id="#+id/review_detail_header"
android:layout_width="match_parent"
android:layout_height="50dp"
android:background="#color/material_red_400" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignBottom="#id/review_detail_header"
android:layout_alignTop="#id/review_detail_header"
android:layout_centerHorizontal="true"
android:gravity="center"
android:text="Review Details"
android:textColor="#color/text_secondary" />
<ImageView
android:id="#+id/ic"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/review_detail_header"
android:layout_marginTop="#dimen/material_layout_keylines_horizontal_margin"
android:adjustViewBounds="true"
android:paddingLeft="#dimen/material_layout_keylines_horizontal_margin"
android:paddingRight="#dimen/material_layout_keylines_horizontal_margin"
android:src="#drawable/ic_account_circle_white_24dp"
android:tint="#color/accent"
tools:ignore="ContentDescription" />
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_author2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/review_detail_header"
android:layout_gravity="center_vertical"
android:layout_marginTop="#dimen/material_layout_keylines_horizontal_margin"
android:layout_toRightOf="#id/ic"
android:textSize="14sp"
custom:robotoType="bold"
tools:text="User Name" />
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_body2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/review_author2"
android:layout_marginBottom="#dimen/material_layout_keylines_horizontal_margin"
android:layout_marginLeft="56dp"
android:layout_marginRight="24dp"
android:layout_marginTop="#dimen/material_layout_vertical_spacing_between_content_areas"
android:layout_weight="1"
android:ellipsize="none"
android:maxLines="100"
android:scrollHorizontally="false"
android:textSize="14sp"
custom:robotoType="regular"
tools:text="The movie's review goes here..." />
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_spoiler2"
style="#style/ReviewBodyStyle"
android:text="#string/reviews_alert"
android:textColor="#color/primary"
android:visibility="gone"
custom:robotoType="bold" />
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_time2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_below="#+id/review_body2"
android:layout_margin="#dimen/material_layout_keylines_horizontal_margin"
android:textSize="#dimen/material_layout_keylines_horizontal_margin"
android:visibility="gone"
custom:robotoType="regular"
tools:text="01 Jan 2016" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
​
<FrameLayout
android:id="#+id/cell_title_view"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:cardview="http://schemas.android.com/apk/res-auto"
xmlns:custom="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/movie_card"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:clickable="true"
android:foreground="?attr/selectableItemBackground"
cardview:cardBackgroundColor="#color/card_background"
cardview:cardCornerRadius="1dp"
cardview:cardElevation="4dp"
cardview:cardUseCompatPadding="true">
<RelativeLayout
android:id="#+id/review_item"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:clickable="true"
android:orientation="vertical"
android:padding="#dimen/material_layout_keylines_horizontal_margin">
<ImageView
android:id="#+id/ic2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:adjustViewBounds="true"
android:src="#drawable/ic_account_circle_white_24dp"
android:tint="#color/accent"
tools:ignore="ContentDescription" />
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_author"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/material_layout_keylines_horizontal_margin"
android:layout_toRightOf="#+id/ic2"
custom:robotoType="bold"
android:textSize="14sp"
tools:text="User Name" />
<!-- Review open icon -->
<ImageView
android:id="#+id/review_open"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:adjustViewBounds="true"
android:src="#drawable/ic_open_in_new_white_24dp"
android:tint="#color/accent"
tools:ignore="contentDescription" />
<!-- Review Body -->
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_body"
style="#style/ReviewBodyStyle"
android:layout_marginLeft="40dp"
android:layout_marginRight="8dp"
android:layout_below="#+id/review_spoiler"
custom:robotoType="regular"
tools:text="The movie's review goes here..." />
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_spoiler"
style="#style/ReviewBodyStyle"
android:layout_below="#id/review_open"
android:text="#string/reviews_alert"
android:textColor="#color/primary"
android:layout_marginLeft="40dp"
android:layout_marginRight="8dp"
android:visibility="gone"
custom:robotoType="bold" />
<com.mt.moviesiwanttowatch.ui.widget.TextViewRoboto
android:id="#+id/review_time"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true"
android:layout_below="#+id/review_body"
android:layout_margin="#dimen/material_layout_keylines_horizontal_margin"
android:textSize="#dimen/material_layout_keylines_horizontal_margin"
android:visibility="gone"
custom:robotoType="regular"
tools:text="01 Jan 2016" />
</RelativeLayout>
</android.support.v7.widget.CardView>
</FrameLayout>
</com.ramotion.foldingcell.FoldingCell>
</layout>
The adapter:
public class ReviewAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
public ArrayList<Review> reviewList;
public int foldingCellPosition = -1;
public FoldingCell currentFoldingCell;
// Constructor
public ReviewAdapter(ArrayList<Review> reviewList) {
this.reviewList = reviewList;
}
// RecyclerView methods
#Override
public int getItemCount() {
return reviewList.size();
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ViewGroup v = (ViewGroup) LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list_review, parent, false);
return new ReviewViewHolder(v);
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
Review review = reviewList.get(position);
ReviewViewHolder holder = (ReviewViewHolder) viewHolder;
if (position == foldingCellPosition) {
holder.binding.foldingCell.unfold(true);
holder.binding.reviewBody2.setText(review.getComment());
holder.binding.reviewAuthor2.setText(review.getUsername());
return;
}
holder.binding.foldingCell.fold(true);
holder.binding.reviewAuthor.setText(review.getUsername());
if (review.isHasSpoiler()) {
holder.binding.reviewBody.setVisibility(View.GONE);
holder.binding.reviewSpoiler.setVisibility(View.VISIBLE);
} else {
holder.binding.reviewBody.setText(review.getComment());
holder.binding.reviewBody.setVisibility(View.VISIBLE);
holder.binding.reviewSpoiler.setVisibility(View.GONE);
}
holder.binding.reviewTime.setText(review.getCreatedAt());
}
// ViewHolder
public class ReviewViewHolder extends RecyclerView.ViewHolder {
ItemListReviewBinding binding;
public ReviewViewHolder(final ViewGroup itemView) {
super(itemView);
binding = DataBindingUtil.bind(itemView);
binding.reviewItem.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// onReviewClickListener.onReviewClicked(getAdapterPosition());
Log.e("TEST", "CLIKC");
if (foldingCellPosition != -1) {
currentFoldingCell.fold(false);
}
currentFoldingCell = binding.foldingCell;
binding.reviewBody2.setText(reviewList.get(getAdapterPosition()).getComment());
binding.reviewAuthor2.setText(reviewList.get(getAdapterPosition()).getUsername());
binding.foldingCell.toggle(false);
foldingCellPosition = getAdapterPosition();
}
});
binding.reviewItem2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
binding.reviewItem2.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
foldingCellPosition = -1;
binding.foldingCell.fold(false);
}
});
}
});
}
}
}
How the recycler view is created:
layoutManager = new LinearLayoutManager(getContext());
mBinding.movieDetailReviewListRvReviews.setHasFixedSize(true);
mBinding.movieDetailReviewListRvReviews.setLayoutManager(layoutManager);
mBinding.movieDetailReviewListRvReviews.setAdapter(adapter);
What I tried so far
I really dont have any idea why this happens.
However I tried notifyDataSetChanged() after each collapse/expand as well as invalidate().
Edit
For the collapsing / expanding effect I use this library:https://github.com/Juriv/folding-cell-android
Actually there were a lot of problems with my code. First of all, as rom4ek mentioned, I had to change foldingCellPosition = getAdapterPosition() to foldingCellPosition = getLayoutPosition(). The next Problem, was this call:
if(foldingCellPosition != -1) {
currentFoldingCell.fold(false);
}
Not visible views should fold, which resulted in strange behaviour, so I added this code:
public void checkForHide(int first, int last){
if(foldingCellPosition != -1){
if(foldingCellPosition < first || foldingCellPosition > last){
foldingCellPosition = -1;
}
}
}
If the unfolded view is not visible the folding cellposition will set to -1 instead of folding it manually.
It is called from the Fragment here:
mBinding.movieDetailReviewListRvReviews.addOnScrollListener(new RecyclerView.OnScrollListener() {
#Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
// Load more data if reached the end of the list
adapter.checkForHide(layoutManager.findFirstVisibleItemPosition(), layoutManager.findLastVisibleItemPosition());
if (layoutManager.findLastVisibleItemPosition() == adapter.reviewList.size() - 1 && !isLoadingLocked && !isLoading) {
if (pageToDownload < totalPages) {
mBinding.layoutContent.pbLoadingMore.setVisibility(View.VISIBLE);
downloadMovieReviews();
}
}
}
});
Try leaving cardview:cardUseCompatPadding false, which is the default.
From https://developer.android.com/reference/android/support/v7/widget/CardView.html#setUseCompatPadding(boolean)
setUseCompatPadding
added in version 24.2.0 void setUseCompatPadding (boolean
useCompatPadding) CardView adds additional padding to draw shadows on
platforms before Lollipop.
This may cause Cards to have different sizes between Lollipop and
before Lollipop. If you need to align CardView with other Views, you
may need api version specific dimension resources to account for the
changes. As an alternative, you can set this flag to true and CardView
will add the same padding values on platforms Lollipop and after.
Since setting this flag to true adds unnecessary gaps in the UI,
default value is false.
This implies that the CardView may be adding padding when you collapse/expand cards.

Categories