I am using a LayoutInflater to fill out a grid view using a GridAdapter, but when i try to place a textView below another textView within the layout i am inflating, it ends up being above my textView instead of below. When i change it to layout_above instead, it doesnt even appear on the screen.
Layout that i inflate:
<?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="match_parent"
android:id="#+id/menuBookModel">
<ImageView
android:id="#+id/bookImage"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="5dp"/>
<TextView
android:id="#+id/bookName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Text"
android:textSize="20sp"
android:textColor="#color/colorPrimaryDark"
android:layout_centerInParent="true"/>
<TextView
android:id="#+id/personalTag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/bookName"
android:text="(Personal)"
android:layout_centerHorizontal="true"
android:textColor="#color/colorPrimaryDark"
android:textSize="15sp" />
</RelativeLayout>
My java code where i am inflating:
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if(view == null){
view = inflater.inflate(R.layout.menu_book_model, null);
}
TextView bookName = view.findViewById(R.id.bookName);
TextView personalTag = view.findViewById(R.id.personalTag);
ImageView bookImage = view.findViewById(R.id.bookImage);
bookImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String s = String.valueOf(view.getTag());
aListener.chooseBook(s);
}
});
int id = context.getResources().getIdentifier(books[i], "string", context.getPackageName());
//if id == 0 the book is custom, and therefore it has the custom name
if(id == 0){
bookName.setText(books[i]);
} else {
bookName.setText(context.getString(id));
personalTag.setVisibility(View.GONE);
}
bookImage.setBackgroundColor(Color.rgb(random.nextInt(255),random.nextInt(255),random.nextInt(255)));
bookImage.setTag(books[i]);
return view;
}
How it looks in the preview:
Preview
But this is how it look in practice:
In practice
You also need to handle personalTag visibility when the id is 0, because it may not be visible when the view is being recycled:
if(id == 0){
bookName.setText(books[i]);
personalTag.setVisibility(View.VISIBLE);
} else {
bookName.setText(context.getString(id));
personalTag.setVisibility(View.GONE);
}
Also avoid setting your root RelativeLayout with match_parent as height, they usually break in AdapterViews, try wrap_content or any hard values, or adjust your layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="100dp"
android:id="#+id/menuBookModel">
<ImageView
android:id="#+id/bookImage"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_margin="5dp"/>
<TextView
android:id="#+id/bookName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Test Text"
android:layout_centerInParent="true"
android:textSize="20sp"
android:textColor="#color/colorPrimaryDark"/>
<TextView
android:id="#+id/personalTag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/bookName"
android:layout_centerHorizontal="true"
android:text="(Personal)"
android:textColor="#color/colorPrimaryDark"
android:textSize="15sp" />
</RelativeLayout>
Related
I've been trying to add radio buttons inside a radio group in a listview.
So, if I click a radio button it checks it but if I click another one, it doesn't remove the previous selection. I'm a beginner in android so forgive me If I'm doing something terribly wrong.
This is my Main Activity and I have the radio group outside the list
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingTop="20dp">
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/car_list_radio_group">
<ListView
android:id="#+id/vehicle_list"
android:clickable="true"
android:layout_width="fill_parent"
android:layout_height="wrap_content"></ListView>
</RadioGroup>
</LinearLayout>
This is my custom view for each item on the list
<?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="match_parent"
android:alwaysDrawnWithCache="true"
android:backgroundTint="#ffffff">
<RadioButton
android:id="#+id/car_selected"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:buttonTint="#color/tesla_red"
android:padding="10dp"
android:text=""
android:textColor="#android:color/white"
android:textSize="16sp"
android:textStyle="bold" />
<TextView
android:id="#+id/vin"
android:layout_width="183dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/car_selected"
android:layout_marginStart="30dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="#android:color/white"
android:textSize="12sp" />
</RelativeLayout>
This is my adapter for the list
private final class VehiclesAdapter extends BaseAdapter {
LayoutInflater inflter;
ArrayList<VehicleItem> vehiclesArray;
public VehiclesAdapter(Context applicationContext, ArrayList<VehicleItem> items) {
vehiclesArray = items;
inflter = (LayoutInflater.from(applicationContext));
}
#Override
public int getCount() {
return vehiclesArray.size();
}
#Override
public Object getItem(int position) {
return null;
}
#Override
public long getItemId(int position) {
return Long.parseLong(vehiclesArray.get(position).getId());
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
VehicleHolder holder;
VehicleItem vehicleItem = vehiclesArray.get(position);
if (convertView == null) { // if convertView is null
convertView = inflter.inflate(R.layout.vehicle_item, parent, false);
holder = new VehicleHolder();
holder.name = convertView.findViewById(R.id.car_selected);
holder.vin = convertView.findViewById(R.id.vin);
// initialize views
convertView.setTag(holder); // set tag on view
} else {
holder = (VehicleHolder) convertView.getTag();
// if not null get tag
// no need to initialize
}
if(vehicleItem.getId().equals(currentVehicle)){
holder.name.setChecked(true);
}
holder.name.setText(vehicleItem.getName());
holder.vin.setText(vehicleItem.getVin());
//update views here
return convertView;
}
}
If you need to see something else please let me know.
RadioGroup is a LinearLayout and is meant to have RadioButton children in order to handle check/uncheck properly. You will have to drop it and handle the check/uncheck logic yourself from the adapter.
add this in your list_item.xml
You will get radioGroup in each row
And remove RadioGroup from main_activity.xml
hope this will help you...
<?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="match_parent"
android:alwaysDrawnWithCache="true"
android:backgroundTint="#ffffff">
<RadioGroup
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/car_list_radio_group">
<RadioButton
android:id="#+id/car_selected"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:buttonTint="#color/tesla_red"
android:padding="10dp"
android:text=""
android:textColor="#android:color/white"
android:textSize="16sp"
android:textStyle="bold" />
<RadioButton
android:id="#+id/car_not_selected"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_torightof="#+id/car_selected"
android:buttonTint="#color/tesla_red"
android:padding="10dp"
android:text=""
android:textColor="#android:color/white"
android:textSize="16sp"
android:textStyle="bold"
</RadioGroup>
<TextView
android:id="#+id/vin"
android:layout_width="183dp"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_below="#+id/car_selected"
android:layout_marginStart="30dp"
android:paddingLeft="10dp"
android:paddingRight="10dp"
android:textColor="#android:color/white"
android:textSize="12sp" />
</RelativeLayout>
I'm currently struggling with a function I want to have in my application. The users Incomes are shown in a ListView. There are two types of incomes, normal "income" and "other income", this is selected in the application when the user submits the income to a SQLite Database that he or she receives. Now - I want to present the different incomes in a ListView with an image in the ListView relative to the type of category (two types of income category - "income" and "other income".
I cant figure out how I should do this ... can you do a switch-statement of some sort!?
My XML for the Custom ListView looks like this:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:weightSum="100">
<ImageView
android:orientation="vertical"
android:layout_width="48dp"
android:layout_height="48dp"
android:gravity="center_vertical"
android:id="#+id/icon1"/>
<LinearLayout
android:orientation="vertical"
android:layout_width="220dp"
android:layout_height="48dp"
android:layout_weight="33.3">
<TextView
android:text="TextView1"
android:textSize="18dp"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="30dp"
android:id="#+id/text1"/>
<TextView
android:text="Textview2"
android:textSize="14dp"
android:gravity="center_vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:="#id/text2"/>
</LinearLayout>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="48dp"
android:orientation="vertical">
<TextView
android:text="Textview3"
android:textSize="16dp"
android:layout_width="wrap_content"
android:layout_height="48dp"
android:layout_gravity=""
android:gravity="center_vertical"
android:id="#+id/text3"/>
</LinearLayout>
<LinearLayout
android:orientation="vertical"
android:layout_width="48dp"
android:layout_height="48dp">
<ImageView
android:orientation="vertical"
android:layout_width="48dp"
android:layout_height="48dp"
android:gravity="center_vertical"
android:id="#+id/icon2"/>
</LinearLayout>
</LinearLayout>
And my AdapterClass looks like this:
public class CustomIncomeListAdapter extends ArrayAdapter<IncomeModel> {
private ArrayList<IncomeModel> incomeList;
private Activity context;
private ViewHolder viewHolder;
int[] incomeIcon = {R.drawable.income, R.drawable.otherincome};
int[] forwardIcon = {R.drawable.forward};
public CustomIncomeListAdapter(Activity context, int[] incomeIcon, ArrayList<IncomeModel> incomeList) {
super(context, R.layout.adapter_view_layout, incomeList);
this.incomeList = incomeList;
this.context = context;
this.incomeIcon = incomeIcon;
}
private static class ViewHolder {
TextView incomeReference;
TextView incomeDate;
TextView incomeAmount;
ImageView incomeIcon;
ImageView forwardIcon;
}
public View getView(int position, View convertView, ViewGroup parent) {
IncomeModel incomeModel = getItem(position);
if (convertView == null) {
viewHolder = new ViewHolder();
LayoutInflater inflater = context.getLayoutInflater();
convertView = inflater.inflate(R.layout.adapter_view_layout, null, true);
viewHolder.incomeReference = (TextView) convertView.findViewById(R.id.text1);
viewHolder.incomeDate = (TextView) convertView.findViewById(R.id.text2);
viewHolder.incomeAmount = (TextView) convertView.findViewById(R.id.text3);
viewHolder.incomeIcon = (ImageView) convertView.findViewById(R.id.icon1);
viewHolder.forwardIcon = (ImageView) convertView.findViewById(R.id.icon2);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.incomeReference.setText(incomeModel.getIncomeCategory());
viewHolder.incomeDate.setText(incomeModel.getIncomeDate());
viewHolder.incomeAmount.setText(incomeModel.getIncomeAmount());
switch (...?) {
}
}
viewHolder.incomeAmount.setText(incomeModel.getIncomeAmount());
switch (income) {
//define your income to 1 for other income
case 1:
incomeIcon.setBackgroundResource(R.drawable.otherincome);
break;
default:
incomeIcon.setBackgroundResource(R.drawable.income);
break;
}
you can check type , if type is income means set corresponding image else set other image
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()));
}
}
}
}
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.
I am trying to add a listview to an existing android fragment. I made a layout xml file for items in the listview, modified the previous fragment.xml, wrote a new arrayadapter and added something to the fragment.java. But whenever I call the notifyDataSetChanged() method in the fragment.java, I got an error: android.content.res.Resources$NotFoundException: String resource ID #0x0, and then the app crashes. Below please find my codes.
layout.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="match_parent"
android:paddingBottom="7dp">
<ImageView
android:layout_width="72dp"
android:layout_height="72dp"
android:id="#+id/iv_checkIcon"
android:layout_margin="7dp"
android:background="#EEEEEE"
android:contentDescription="Provider icon"
/>
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_toRightOf="#id/iv_checkIcon"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_marginLeft="5dp"
>
<TextView
android:layout_width="200dp"
android:layout_height="wrap_content"
android:id="#+id/tv_checkName"
android:text="Provider name"
android:textSize="20dp"
/>
<TextView
android:layout_width="250dp"
android:layout_height="wrap_content"
android:id="#+id/tv_checkInDate"
android:text="Check In Date"
android:textSize="14dp"
android:textColor="#888888"
android:layout_marginTop="4dp"/>
</LinearLayout>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/tv_checkPoints"
android:layout_alignParentRight="true"
android:text="100分"
android:layout_marginTop="10dp"
android:layout_marginRight="10dp"
android:textSize="18dp"
android:textColor="#CF1A12"
/>
</RelativeLayout>
fragment.xml
<FrameLayout 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=".fragment.MeActivity">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/me_bg2"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/fake_head"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:id="#+id/iv_fake_head"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/iv_fake_head"
android:text="--"
android:textSize="22dp"
android:textColor="#ffffff"
android:layout_marginTop="15dp"
android:id="#+id/tv_name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/tv_name"
android:text="积分"
android:textColor="#ffffff"
android:layout_marginTop="15dp"
android:textSize="20dp"
android:background="#drawable/me_points_bg"
android:id="#+id/tv_points"
/>
</RelativeLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lv_histories"
android:layout_gravity="bottom" />
</FrameLayout>
Arrayadapter.java
public class RecordArrayAdapter extends ArrayAdapter<CheckInRecord.CheckInRec> {
private int resourceId;
private Context context;
private List<CheckInRecord.CheckInRec> checkInRecList;
public RecordArrayAdapter(Context context, int resourceId, List<CheckInRecord.CheckInRec> checkInRecList)
{
super(context, resourceId, checkInRecList);
this.resourceId = resourceId;
this.context = context;
this.checkInRecList = checkInRecList;
}
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null){
LayoutInflater inflater = ((Activity)context).getLayoutInflater();
convertView = inflater.inflate(resourceId, parent, false);
}
TextView textViewName = (TextView) convertView.findViewById(R.id.tv_checkName);
TextView textViewCheckInDate = (TextView) convertView.findViewById(R.id.tv_checkInDate);
TextView textViewPoints = (TextView) convertView.findViewById(R.id.tv_checkPoints);
ImageView imageViewIcon = (ImageView) convertView.findViewById(R.id.iv_checkIcon);
CheckInRecord.CheckInRec checkInRec = checkInRecList.get(position);
textViewName.setText(checkInRec.providerName);
textViewCheckInDate.setText(checkInRec.checkInDate);
textViewPoints.setText(checkInRec.providerPoints);
ImageLoader.getInstance().displayImage(checkInRec.providerIcon, imageViewIcon, Utility.displayImageOptions);
return convertView;
}
public int getIsPrize(int position) {return (this.checkInRecList.get(position).isPrize);}
}
fragment.java
public class MeFragment extends Fragment implements ApiRequestDelegate {
private TextView textViewName;
private TextView textViewPoints;
private ProgressDialog progressDialog;
private RecordArrayAdapter recordArrayAdapter;
private List<CheckInRecord.CheckInRec> checkInRecList = new ArrayList<CheckInRecord.CheckInRec>();
public MeFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ApiManager.getInstance().checkInHistories(AppDataManager.getInstance().getUserToken(), AppDataManager.getInstance().getUserPhone(),
Utility.getPictureSize(), this);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View fragmentView = inflater.inflate(R.layout.fragment_me, container, false);
textViewName = (TextView) fragmentView.findViewById(R.id.tv_name);
textViewPoints = (TextView) fragmentView.findViewById(R.id.tv_points);
ListView listViewRec = (ListView) fragmentView.findViewById(R.id.lv_histories);
recordArrayAdapter = new RecordArrayAdapter(this.getActivity(), R.layout.row_record, checkInRecList);
listViewRec.setAdapter(recordArrayAdapter);
return fragmentView;
}
#Override
public void apiCompleted(ApiResult apiResult, HttpRequest httpRequest) {
if (progressDialog!=null){
progressDialog.dismiss();
}
if (!apiResult.success){
ApiManager.handleMessageForReason(apiResult.failReason, getActivity());
return;
}
CheckInRecord checkInRecord = (CheckInRecord) apiResult.valueObject;
if (checkInRecord != null){
textViewName.setText(checkInRecord.userName);
textViewPoints.setText(String.format("积分%d分", checkInRecord.userPoints));
this.checkInRecList.clear();
this.checkInRecList.addAll(checkInRecord.checkInRecList);
recordArrayAdapter.notifyDataSetChanged();
}
}
}
Make sure checkInRec.providerName, checkInRec.checkInDate and checkInRec.providerPoints values that you set as TextView text have a type of String and cast it to String if it's integer.
// cast to String if checkInRec.checkInDate is integer
textViewPoints.setText(String.valueOf(checkInRec.providerPoints));
UPD:
It seems ListView is located behind header view. Try to change root view of fragment.xml from FrameLayout to LinearLayout with android:orientation="vertical" attribute. Like this:
<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="match_parent"
android:orientation="vertical"
tools:context=".fragment.MeActivity">
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/me_bg2"
>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/fake_head"
android:layout_centerHorizontal="true"
android:layout_marginTop="40dp"
android:id="#+id/iv_fake_head"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/iv_fake_head"
android:text="--"
android:textSize="22dp"
android:textColor="#ffffff"
android:layout_marginTop="15dp"
android:id="#+id/tv_name"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="#id/tv_name"
android:text="积分"
android:textColor="#ffffff"
android:layout_marginTop="15dp"
android:textSize="20dp"
android:background="#drawable/me_points_bg"
android:id="#+id/tv_points"
/>
</RelativeLayout>
<ListView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="#+id/lv_histories"
android:layout_gravity="bottom" />
</LinearLayout>