Long click on row of recyclerview is not entered in onClick() I dont understand what is wrong with my code.Following are my MainActivity, adapter and row of my recyclerview which is made using cardview.
Following is my MainActivity.java
public class MainActivity extends AppCompatActivity implements RecyclerView.OnItemTouchListener,
View.OnClickListener,
ActionMode.Callback {
ArrayList<ProductPojo> lastNameList;
private RecyclerView recyclerView;
private ProductAdapter adapter;
private List<ProductPojo> albumList;
GestureDetectorCompat gestureDetector;
ActionMode actionMode;
/////
private ProgressDialog pDialog;
ApiClass apigetOfferList;
String response;
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
albumList = new ArrayList<>();
lastNameList = new ArrayList<ProductPojo>(12);
recyclerView.addOnItemTouchListener(
new RecyclerItemClickListener(MainActivity.this, new RecyclerItemClickListener.OnItemClickListener() {
#Override
public void onItemClick(View v, final int position) {
Toast.makeText(MainActivity.this, "" + position, Toast.LENGTH_SHORT).show();
final EditText edittext = new EditText(MainActivity.this);
AlertDialog.Builder alert = new AlertDialog.Builder(MainActivity.this);
alert.setMessage("Enter Your Last Name");
alert.setTitle("Fill me");
alert.setView(edittext);
alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
ProductPojo lNamePojo = new ProductPojo(edittext.getText().toString());
Log.d("lastNameList.size()", ""+lastNameList.size() +" "+position);
if(!albumList.isEmpty() && lastNameList.size() != 0) {
lastNameList.add(position, lNamePojo);
Log.d("lastNameList.size()", ""+lastNameList.size());
}
adapter.notifyDataSetChanged();
adapter = new ProductAdapter(MainActivity.this, albumList, lastNameList);
recyclerView.setAdapter(adapter);
// lName = edittext.getText().toString();
}
});
alert.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
dialog.dismiss();
}
});
alert.show();
}
})
);
/* LinearLayoutManager llm = new LinearLayoutManager(this);
llm.setOrientation(LinearLayoutManager.VERTICAL);
recyclerView.setLayoutManager(llm);
recyclerView.setAdapter( adapter );*/
gestureDetector = new GestureDetectorCompat(this, new RecyclerViewDemoOnGestureListener());
ListViewLoaderTask listViewLoaderTask = new ListViewLoaderTask();
listViewLoaderTask.execute();
}
/**
* RecyclerView item decoration - give equal margin around grid item
*/
public class GridSpacingItemDecoration extends RecyclerView.ItemDecoration {
private int spanCount;
private int spacing;
private boolean includeEdge;
public GridSpacingItemDecoration(int spanCount, int spacing, boolean includeEdge) {
this.spanCount = spanCount;
this.spacing = spacing;
this.includeEdge = includeEdge;
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
int position = parent.getChildAdapterPosition(view); // item position
int column = position % spanCount; // item column
if (includeEdge) {
outRect.left = spacing - column * spacing / spanCount; // spacing - column * ((1f / spanCount) * spacing)
outRect.right = (column + 1) * spacing / spanCount; // (column + 1) * ((1f / spanCount) * spacing)
if (position < spanCount) { // top edge
outRect.top = spacing;
}
outRect.bottom = spacing; // item bottom
} else {
outRect.left = column * spacing / spanCount; // column * ((1f / spanCount) * spacing)
outRect.right = spacing - (column + 1) * spacing / spanCount; // spacing - (column + 1) * ((1f / spanCount) * spacing)
if (position >= spanCount) {
outRect.top = spacing; // item top
}
}
}
}
/**
* Converting dp to pixel
*/
private int dpToPx(int dp) {
Resources r = getResources();
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp, r.getDisplayMetrics()));
}
private class ListViewLoaderTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
apigetOfferList = new ApiClass();
}
#Override
protected String doInBackground(String... args) {
response = apigetOfferList.xmlFetchFunction();
return response;
}
#Override
protected void onPostExecute(String res) {
Log.d("res", "" + res);
StringReader reader = new StringReader(res);
ProductXmlParser productXmlParser = new ProductXmlParser();
List<HashMap<String, String>> products = null;
try {
/** Getting the parsed data as a List construct */
products = productXmlParser.parse(reader);
} catch (Exception e) {
Log.d("Exception", e.toString());
}
Log.d("products", "" + products);
for (int i = 0; i < products.size(); i++) {
Log.d("productThumbnail", "" + products.get(i).get("productThumbnail"));
ProductPojo album = new ProductPojo(products.get(i).get("productThumbnail"), products.get(i).get("productName"), products.get(i).get("categoryName"), products.get(i).get("productDescription"), products.get(i).get("numberOfRatings"), products.get(i).get("rating"), products.get(i).get("averageRatingImageURL"));
albumList.add(album);
lastNameList.add(album);
}
adapter = new ProductAdapter(MainActivity.this, albumList, lastNameList);
adapter.notifyDataSetChanged();
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(MainActivity.this, 1);
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.addItemDecoration(new GridSpacingItemDecoration(2, dpToPx(10), true));
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
pDialog.dismiss();
}
}
#Override
public boolean onInterceptTouchEvent(RecyclerView rv, MotionEvent e) {//in
Log.d("RecyclerView","DemoActivity"+"onInterceptTouchEvent");
gestureDetector.onTouchEvent(e);
return false;
}
#Override
public void onTouchEvent(RecyclerView rv, MotionEvent e) {
}
#Override
public void onRequestDisallowInterceptTouchEvent(boolean disallowIntercept) {
}
private void myToggleSelection(int idx) {//in
Log.d("RecyclerView","DemoActivity"+"myToggleSelection");
adapter.toggleSelection(idx);
String title = getString(R.string.selected_count, adapter.getSelectedItemCount());
actionMode.setTitle(title);
}
#TargetApi(Build.VERSION_CODES.LOLLIPOP)
#Override
public void onClick(View view) {
if (view.getId() == R.id.container_list_item) {//in
// item click
Log.d("RecyclerView","DemoActivity"+"item click");
int idx = recyclerView.getChildLayoutPosition(view);
if (actionMode != null) {
myToggleSelection(idx);
return;
}
}
}
private class RecyclerViewDemoOnGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onSingleTapConfirmed(MotionEvent e) {//in
Log.d("RecyclerView","DemoActivity"+"onSingleTapConfirmed");
View view = recyclerView.findChildViewUnder(e.getX(), e.getY());
onClick(view);
return super.onSingleTapConfirmed(e);
}
public void onLongPress(MotionEvent e) {//in
Log.d("RecyclerView","DemoActivity"+"onLongPress");
View view = recyclerView.findChildViewUnder(e.getX(), e.getY());
if (actionMode != null) {
return;
}
// Start the CAB using the ActionMode.Callback defined above
actionMode = startActionMode(MainActivity.this);
int idx = recyclerView.getChildAdapterPosition(view);
myToggleSelection(idx);
super.onLongPress(e);
}
}
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {//in
// Inflate a menu resource providing context menu items
Log.d("RecyclerView","DemoActivity"+"onCreateActionMode");
MenuInflater inflater = actionMode.getMenuInflater();
inflater.inflate(R.menu.menu_cab_recyclerviewdemoactivity, menu);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
return false;
}
#Override
public void onDestroyActionMode(ActionMode mode) {
}
}
This is my Adapter class
public class ProductAdapter extends RecyclerView.Adapter<ProductAdapter.MyViewHolder> {
private Context mContext;
private List<ProductPojo> albumList;
String lName;
private List<DemoModel> items;
private SparseBooleanArray selectedItems;
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView lastName, cat_name, product_name, product_design, numOfRatings, rate;
public ImageView thumbnail1, thumbnail2;
public MyViewHolder(View view) {
super(view);
lastName = (TextView) view.findViewById(R.id.lastName);
product_name = (TextView) view.findViewById(R.id.product_name);
product_design = (TextView) view.findViewById(R.id.product_design);
cat_name = (TextView) view.findViewById(R.id.category_name);
rate = (TextView) view.findViewById(R.id.rate);
numOfRatings = (TextView) view.findViewById(R.id.noOfRatings);
thumbnail1 = (ImageView) view.findViewById(R.id.thumbnail);
thumbnail2 = (ImageView) view.findViewById(R.id.thumbnail2);
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(itemView.getContext(), " " + getItemId(), Toast.LENGTH_SHORT).show();
}
});
view.setOnLongClickListener(new View.OnLongClickListener()
{
#Override
public boolean onLongClick(View v)
{
Toast.makeText(v.getContext(), "Long Click Listerner Position is " + getAdapterPosition(), Toast.LENGTH_SHORT).show();
return false;
}
}
);
}
}
public ProductAdapter(Context mContext, List<ProductPojo> albumList, ArrayList<ProductPojo> lName) {
this.mContext = mContext;
this.albumList = albumList;
selectedItems = new SparseBooleanArray();
}
public int getSelectedItemCount() {
Log.d("RecyclerViewDemoAdapter","getSelectedItemCount");
return selectedItems.size();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.album_card, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
ProductPojo album = albumList.get(position);
holder.lastName.setText("Last Name : " + album.getlName());
holder.product_name.setText("Product Name : " + album.getpName());
holder.cat_name.setText("Category Name : " + album.getcName());
holder.product_design.setText("Product Description : " + album.getpDesc());
holder.rate.setText("Rating : " + album.getRating());
holder.numOfRatings.setText("No.of ratings : " + album.getNoOfRatings());
Drawable productDrawable = LoadImageFromProductLink(album.getpLink());
holder.thumbnail1.setImageDrawable(productDrawable);
// loading album cover using Glide library
Glide.with(mContext).load(album.getpLink()).into(holder.thumbnail1);
Drawable rateDrawable = LoadImageFromRateLink(album.getRateLink());
holder.thumbnail2.setImageDrawable(rateDrawable);
// loading album cover using Glide library
Glide.with(mContext).load(album.getRateLink()).into(holder.thumbnail2);
}
private Drawable LoadImageFromProductLink(String url) {
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
System.out.println("Exc=" + e);
return null;
}
}
private Drawable LoadImageFromRateLink(String url) {
try {
InputStream is = (InputStream) new URL(url).getContent();
Drawable d = Drawable.createFromStream(is, "src name");
return d;
} catch (Exception e) {
System.out.println("Exc=" + e);
return null;
}
}
#Override
public int getItemCount() {
return albumList.size();
}
#Override
public long getItemId(int position) {
return super.getItemId(position);
}
public void toggleSelection(int pos) {
if (selectedItems.get(pos, false)) {
Log.d("RecyclerViewDemoAdapter","IftoggleSelection");
selectedItems.delete(pos);
} else {
Log.d("RecyclerViewDemoAdapter","ElsetoggleSelection");
selectedItems.put(pos, true);
}
notifyItemChanged(pos);
}
}
**And this is my row**
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<android.support.v7.widget.CardView
android:id="#+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_margin="#dimen/card_margin"
android:elevation="3dp"
card_view:cardCornerRadius="#dimen/card_album_radius">
<LinearLayout
android:id="#+id/container_list_item"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<LinearLayout
android:id="#+id/first"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<ImageView
android:id="#+id/thumbnail"
android:layout_width="130dp"
android:layout_height="130dp"
android:layout_margin="5dp"
android:clickable="true"
android:padding="5dp"
android:scaleType="fitXY" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/lastName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="Product Name"
android:textColor="#color/colorPrimaryDark"
android:textSize="#dimen/backdrop_subtitle"
android:textStyle="bold"
android:visibility="gone" />
<TextView
android:id="#+id/product_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginTop="20dp"
android:text="Product Name"
android:textColor="#color/album_title"
android:textSize="#dimen/album_title" />
<TextView
android:id="#+id/category_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="Category Name"
android:textColor="#color/album_title"
android:textSize="#dimen/album_title" />
</LinearLayout>
</LinearLayout>
<TextView
android:id="#+id/product_design"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:gravity="center"
android:text="Product Design"
android:textColor="#color/album_title"
android:textSize="#dimen/album_title" />
<LinearLayout
android:id="#+id/second"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="5dp"
android:orientation="horizontal">
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="#+id/rate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="Rate"
android:textColor="#color/album_title"
android:textSize="#dimen/album_title" />
<TextView
android:id="#+id/noOfRatings"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:text="No. of Ratings"
android:textColor="#color/album_title"
android:textSize="#dimen/album_title" />
</LinearLayout>
<ImageView
android:id="#+id/thumbnail2"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp" />
</LinearLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
</LinearLayout>
Please help me guys..I'm waiting for ur answers..Thanks in Advance!
Detail below
class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
private Article mArticle;
private TextView mNameTextView;
public ViewHolder(View itemView) {
super(itemView);
itemView.setOnClickListener(this);
itemView.setOnLongClickListener(this);
mNameTextView = (TextView) itemView.findViewById(R.id.grid_item_article_name_textView);
}
public void bind(Article article) {
mArticle = article;
mNameTextView.setText(article.getName());
}
#Override
public void onClick(View view) {
// Context context = view.getContext();
// mArticle.getName()
}
#Override
public boolean onLongClick(View view) {
// Handle long click
}
}
Handle on item long click on recycler view
Related
I want to create a RecyclerView in Android which contains ViewHolders, that change their width and height as shown in the GIF below. I tried several LayoutManagers for the RecyclerView but I did not manage to get the result I wished for.
The RecyclerView should be a 1 dimensional row.
Hi you can use this to animate the views inside your RecyclerView as shown on the GIF below:
My adapter:
public class StringAdapter extends RecyclerView.Adapter<StringAdapter.StringHolder> {
private int defaultWidth = 0;
private int defaultHeight = 0;
private static final String[] strings = new String[]{"Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6", "Item 7", "Item 8", "Item 8", "Item 10"};
private int lastSelected = -1;
private final RecyclerView.LayoutManager layoutManager;
private static final int animValue = 50;
StringAdapter(RecyclerView.LayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
#NonNull
#Override
public StringHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.test_holder, parent, false);
return new StringHolder(v);
}
#Override
public void onBindViewHolder(#NonNull StringHolder holder, int position) {
holder.categories.setText(strings[position]);
ViewGroup.LayoutParams param = holder.card.getLayoutParams();
if (position == lastSelected) {
param.width = defaultWidth + animValue;
param.height = defaultHeight + animValue;
} else {
if (defaultWidth != 0 && defaultHeight != 0) {
param.width = defaultWidth;
param.height = defaultHeight;
}
}
}
#Override
public int getItemCount() {
return strings.length;
}
protected class StringHolder extends RecyclerView.ViewHolder {
private final TextView categories;
private final CardView card;
public StringHolder(#NonNull View itemView) {
super(itemView);
categories = itemView.findViewById(R.id.categories);
card = itemView.findViewById(R.id.cardCategories);
card.setOnClickListener(v -> {
int currentPosition = this.getAbsoluteAdapterPosition();
selection(currentPosition, lastSelected);
lastSelected = currentPosition;
});
}
private void selection(int newPosition, int oldPosition) {
if (newPosition != oldPosition) {
ConstraintLayout newView = (ConstraintLayout) layoutManager.findViewByPosition(newPosition);
ConstraintLayout oldView = (ConstraintLayout) layoutManager.findViewByPosition(oldPosition);
if (newView != null) {
defaultWidth = card.getWidth();
defaultHeight = card.getHeight();
selectAnimate(newView.getChildAt(0));
}
if (oldView != null) {
deselectAnimate(oldView.getChildAt(0));
} else {
notifyItemChanged(oldPosition);
}
}
}
private void selectAnimate(View view) {
ValueAnimator select = ValueAnimator.ofInt(defaultWidth, defaultWidth + animValue);
select.setInterpolator(new AccelerateDecelerateInterpolator());
select.setDuration(300);
select.start();
select.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.width = (int) animation.getAnimatedValue();
layoutParams.height = (int) (animation.getAnimatedValue()) + defaultHeight - defaultWidth;
view.requestLayout();
}
});
}
private void deselectAnimate(View view) {
ValueAnimator select = ValueAnimator.ofInt(defaultWidth + animValue, defaultWidth);
select.setInterpolator(new AccelerateDecelerateInterpolator());
select.setDuration(300);
select.start();
select.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override
public void onAnimationUpdate(ValueAnimator animation) {
ViewGroup.LayoutParams layoutParams = view.getLayoutParams();
layoutParams.width = (int) animation.getAnimatedValue();
layoutParams.height = (int) (animation.getAnimatedValue()) + defaultHeight - defaultWidth;
view.requestLayout();
}
});
}
}
}
My MainActivity :
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = findViewById(R.id.recyclerView);
LinearLayoutManager layoutManager = new LinearLayoutManager(this, RecyclerView.HORIZONTAL, false);
recyclerView.setLayoutManager(layoutManager);
StringAdapter adapter = new StringAdapter(layoutManager);
recyclerView.setAdapter(adapter);
}
}
My MainActivity Layout
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".test.MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="300dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
And finaly this MyHolder Layout :
<?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:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginStart="5dp">
<androidx.cardview.widget.CardView
android:id="#+id/cardCategories"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:cardCornerRadius="15dp"
app:cardUseCompatPadding="true"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent">
<TextView
android:id="#+id/categories"
android:layout_width="wrap_content"
android:layout_height="35dp"
android:layout_gravity="center"
android:gravity="center"
android:paddingStart="10dp"
android:paddingEnd="10dp"
android:text="Some Text"
android:textSize="16sp" />
</androidx.cardview.widget.CardView>
</androidx.constraintlayout.widget.ConstraintLayout>
Hey I'm doing filtering data on my project using bottom Sheet with view-pager and two fragments i can pass data from activity to view-pager adapter and get in fragment through constructor but how can i get data from fragment to activity using bottom-sheet
this is how i send data from activity
adapter = new PagerAdapters(this.getSupportFragmentManager(),
tabLayout.getTabCount(),_id);
and receive data with constructor in fragment
public Filterfragment(String _id) {
this._id = _id;
}
And I'm using recyclerview to show data like this
So how can i send id of the item to activity so i can reload my recyclerview data when the apply button click.
<?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"
android:id="#+id/bottom_sheet"
android:background="#android:color/white"
app:behavior_peekHeight="0dp"
app:layout_behavior="android.support.design.widget.BottomSheetBehavior"
android:orientation="vertical">
<android.support.design.widget.TabLayout
android:id="#+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
app:tabGravity="fill"
app:tabMode="fixed"
app:tabPadding="0dp"/>
<android.support.v4.view.ViewPager
android:id="#+id/viewpager"
android:layout_width="match_parent"
android:layout_below="#id/tabs"
android:layout_above="#id/applyBtn"
android:layout_height="match_parent"
/>
<Button
android:id="#+id/applyBtn"
android:layout_width="match_parent"
android:text="Apply"
android:layout_alignParentBottom="true"
android:layout_height="wrap_content" />
</RelativeLayout>
This is main recyclerview adapter
public class FilterAdapter extends RecyclerView.Adapter<FilterAdapter.FilterViewHolder> {
private static final String TAG = "FilterAdapter";
Context context;
List<TagTypeResult> tagTypeModels;
public static int current_pos = -1;
TagAdapter tagAdapter;
int rotationAngle = 0;
public FilterAdapter(Context context, List<TagTypeResult> tagTypeModels) {
this.context = context;
this.tagTypeModels = tagTypeModels;
}
#NonNull
#Override
public FilterViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.filter_row_item,parent,false);
return new FilterAdapter.FilterViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull FilterViewHolder filterViewHolder, int i) {
TagTypeResult tagTypeModel = tagTypeModels.get(i);
filterViewHolder.txt.setText(tagTypeModel.getName());
filterViewHolder.sub_list_recycler.setVisibility(View.GONE);
if (tagTypeModel.getTagsLists() != null) {
if (tagTypeModel.getTagsLists().size() <= 0) {
filterViewHolder.arrow.setVisibility(View.GONE);
filterViewHolder.arrow.setRotationX(180);
} else {
filterViewHolder.arrow.setVisibility(View.VISIBLE);
filterViewHolder.arrow.setRotationX(0);
}
}else {
filterViewHolder.arrow.setVisibility(View.GONE);
}
tagAdapter = new TagAdapter(context, tagTypeModel.getTagsLists(), new TagInterface() {
#Override
public void tagClick(View view, int pos, String tagID) {
Log.d(TAG, "tagClick: "+tagID);
}
});
filterViewHolder.sub_list_recycler.setAdapter(tagAdapter);
tagAdapter.notifyDataSetChanged();
if (current_pos == filterViewHolder.getAdapterPosition()){
if (filterViewHolder.sub_list_recycler.getVisibility() == View.GONE) {
filterViewHolder.sub_list_recycler.setVisibility(View.VISIBLE);
}else {
filterViewHolder.sub_list_recycler.setVisibility(View.GONE);
}
}else {
Log.i(TAG, "onBindViewHolder: sublist gone "+tagTypeModel.getName());
filterViewHolder.sub_list_recycler.setVisibility(View.GONE);
}
}
#Override
public int getItemCount() {
return tagTypeModels.size();
}
class FilterViewHolder extends RecyclerView.ViewHolder {
TextView txt;
ImageView arrow;
RecyclerView sub_list_recycler;
RelativeLayout linearLayout;
FilterViewHolder(#NonNull View itemView) {
super(itemView);
txt = itemView.findViewById(R.id.txt);
arrow = itemView.findViewById(R.id.arrow);
linearLayout = itemView.findViewById(R.id.main_cat_lay);
linearLayout.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG, "onClick: "+current_pos);
if (current_pos != getAdapterPosition()) {
current_pos = getAdapterPosition();
notifyDataSetChanged();
}
else{
current_pos = -1;
notifyDataSetChanged();
}
}
});
sub_list_recycler = itemView.findViewById(R.id.sub_list_recycler);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(context) {
#Override
public boolean canScrollVertically() {
return false;
}
};
sub_list_recycler.setLayoutManager(mLayoutManager);
sub_list_recycler.addItemDecoration(new SimpleDividerItemDecoration(context));
}
}
}
sub recyclerView adapter :
public class TagAdapter extends RecyclerView.Adapter<TagAdapter.TagViewHolder> {
private static final String TAG = "SublistAdapter";
Context context;
List<TagsList> tagsLists;
int pos = -1;
TagInterface tagInterface;
public TagAdapter(Context context, List<TagsList> tagsLists,TagInterface tagInterface) {
this.context = context;
this.tagsLists = tagsLists;
this.tagInterface = tagInterface;
}
#NonNull
#Override
public TagViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int i) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.tag_item,parent,false);
return new TagAdapter.TagViewHolder(v);
}
#Override
public void onBindViewHolder(#NonNull TagViewHolder tagViewHolder, int i) {
TagsList tagsList = tagsLists.get(i);
tagViewHolder.tagtxt.setText(tagsList.getName());
if (tagsList.isChecked()){
tagViewHolder.tagName.setChecked(true);
}else {
tagViewHolder.tagName.setChecked(false);
}
}
#Override
public int getItemCount() {
return tagsLists.size();
}
public class TagViewHolder extends RecyclerView.ViewHolder {
TextView tagtxt;
CheckBox tagName;
RelativeLayout childClik;
public TagViewHolder(#NonNull View itemView) {
super(itemView);
//pri_txt = itemView.findViewById(R.id.pri_txt);
tagName = itemView.findViewById(R.id.tagName);
tagtxt = itemView.findViewById(R.id.tagtxt);
childClik = itemView.findViewById(R.id.childClik);
tagName.setEnabled(false);
childClik.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
boolean isChecked = true;
if (isChecked)
{
tagsLists.get(getAdapterPosition()).setChecked(true);
tagName.setChecked(true);
tagInterface.tagClick(v,getAdapterPosition(),tagsLists.get(getAdapterPosition()).get_id());
Toast.makeText(context, "[pos]"+tagsLists.get(getAdapterPosition()).get_id(), Toast.LENGTH_SHORT).show();
}else
{
tagsLists.get(getAdapterPosition()).setChecked(false);
tagName.setChecked(false);
}
}
});
}
}
}
I'm parsing a JSON into a ExpandableListView, on each child the user can select the amount of each child he wants to have due +/- Buttons. The +/- Buttons are connected to a TextView where the total amount of each child gets displayed and the total cost will be displayed at the end of the line.
At the Bottom of the parent there should be a TextView with the summary of all the values calculated in every child of the ExpListView (Summary)
And the OK Button at the Bottom should send the amount of each child to the server (the amount is connected to a ID).
I'm having problems with reading out the amount of each child when I'm clicking on the "OK" Button - how can I build the bridge to the values of my Childs?
I also encounter problems reading out the cost of each childto calculate the total cost at the bottom. The onClickListener in the Child should somehow refresh the TextView at the bottom, but as far as I know, that's not going to be easy, right?
Has anyone an idea how to access the values?
This is the ChildView of my ListAdapter where the magic happens:
public class ExpandableListAdapterDrinks extends BaseExpandableListAdapter {
private Context context;
private List<String> listDataHeader,listDataHeaderPrice;
private HashMap<String,List<String>> listHashMap;
private List<Drink> drinksList;
class ViewHolder {
TextView childText,counterText, childUnitPrice, childFinalPrice;
Button btn_plus,btn_minus;
}
class DrinksListChildItem{
String name;
int quantity;
DrinksListChildItem(String name, int quantity){
this.name = name;
this.quantity = quantity;
}
}
class Pos{
int group;
int child;
Pos(int group, int child){
this.group = group;
this.child = child;
}
}
public ExpandableListAdapterDrinks(Context context, List<Drink> drinksList) {
this.context = context;
this.drinksList= drinksList;
}
#Override
public int getGroupCount() {
return drinksList.size();
}
#Override
public int getChildrenCount(int groupPosition) {
return drinksList.get(groupPosition).getContent().size();
}
#Override
public Object getGroup(int groupPosition) {
return drinksList.get(groupPosition);
}
#Override
public Object getChild(int groupPosition, int childPosition) {
return drinksList.get(groupPosition).getContent();
listHashMap.get(listDataHeader.get(groupPosition)).get(childPosition);
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public View getGroupView(final int groupPosition, boolean isExpanded, View view, ViewGroup parent) {
String headerTitle = (String) drinksList.get(groupPosition).getTitle();
/** HEADER TEXT HERE */
if(view==null) {
LayoutInflater inflater = (LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.vip_package_listgroup,null);
}
final LinearLayout bgcolor = view.findViewById(R.id.lblListHeaderLayout);
TextView lblListHeader = (TextView)view.findViewById(R.id.lblListHeader);
TextView lblListHeaderPrice = (TextView)view.findViewById(R.id.lblListHeader_Price);
Button lblListHeaderButton = view.findViewById(R.id.lblListHeaderButton);
lblListHeaderPrice.setVisibility(View.GONE);
lblListHeaderButton.setVisibility(View.GONE);
if(!drinksList.get(groupPosition).getBg().get(0).isEmpty() || !drinksList.get(groupPosition).getBg().get(1).isEmpty() ) {
List<String> colorGradientTopBottom = drinksList.get(groupPosition).getBg();
int[] colors = {Color.parseColor(colorGradientTopBottom.get(0)),Color.parseColor(colorGradientTopBottom.get(1))};
GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
gd.setCornerRadius(0f);
bgcolor.setBackground(gd);
} else {
bgcolor.setBackgroundColor(ContextCompat.getColor(context, R.color.cardview_bg));
}
lblListHeader.setText(headerTitle);
return view;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) {
/** Drinks List */
final ViewHolder viewHolder;
final List<String> childDrink = drinksList.get(groupPosition).getContent();
final List<Integer> childPrice = drinksList.get(groupPosition).getPricelist();
//final String childText = childDrink.get(childPosition);
if(view == null) {
LayoutInflater inflater = (LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.vip_drinks_listitem,null);
final TextView txtListChild = view.findViewById(R.id.lblListItemDrinks);
final TextView txtListDrinksUnitPrice = view.findViewById(R.id.lblListItemDrinksUnitPrice);
final TextView txtDrinksAmount = view.findViewById(R.id.vip_drinks_amount);
final TextView txtListDrinkPriceFinal = view.findViewById(R.id.lblListItemDrinksFinalPrice);
Button btn_plus = view.findViewById(R.id.vip_drinks_btn_plus);
Button btn_minus = view.findViewById(R.id.vip_drinks_btn_minus);
viewHolder = new ViewHolder();
viewHolder.childText = txtListChild;
viewHolder.childUnitPrice = txtListDrinksUnitPrice;
viewHolder.counterText = txtDrinksAmount;
viewHolder.childFinalPrice = txtListDrinkPriceFinal;
viewHolder.btn_plus = btn_plus;
viewHolder.btn_minus = btn_minus;
viewHolder.childText.setText(childDrink.get(childPosition));
viewHolder.counterText.setText("0");
viewHolder.childFinalPrice.setText("0");
final float headerPrice = childPrice.get(childPosition);
final int headerPriceInt = (int) headerPrice;
viewHolder.childUnitPrice.setText(String.format("%.02f",headerPrice).replace(".",",") +"€");
DrinksListChildItem child = childDrink.get(childPosition);
viewHolder.btn_plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int t = Integer.parseInt(viewHolder.counterText.getText().toString());
ChildItem selectedItem = viewHolder.counterText.getText().toString();
selectedItem.quantity = selectedItem.quantity+1;
notifyDataSetChanged();
viewHolder.counterText.setText(String.valueOf(t + 1));
viewHolder.childFinalPrice.setText(String.valueOf((t+1)* headerPriceInt) + "€");
}
});
viewHolder.btn_minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Pos pos = (Pos) v.getTag();
int t = Integer.parseInt(viewHolder.counterText.getText().toString());
DrinksListChildItem selectedItem = (DrinksListChildItem) getChild(pos.group,pos.child);
selectedItem.quantity = selectedItem.quantity-1;
notifyDataSetChanged();
viewHolder.counterText.setText(String.valueOf(t - 1));
viewHolder.counterText.setText(String.valueOf((t-1)* headerPriceInt) + "€");
}
});
} else {
viewHolder = (ViewHolder) view.getTag();
}
return view;
I'm having massive problems glueing your code to my Code (expand problem with a TextView): I don't understand exactly how to connect the ChildItem child = childDrink.get(childPosition); to my drinksList to make the setOnCLickListener increase the selectedItem.quantity. The Code works somehow, but it messes up the order of my childs and it also selects the quantity in the other childs
Drinks (Pojo)
public class Drink {
#SerializedName("title")
#Expose
private String title;
#SerializedName("bg")
#Expose
private List<String> bg = null;
#SerializedName("content")
#Expose
private List<String> content = null;
#SerializedName("pricelist")
#Expose
private List<Integer> pricelist = null;
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public List<String> getBg() {
return bg;
}
public void setBg(List<String> bg) {
this.bg = bg;
}
public List<String> getContent() {
return content;
}
public void setContent(List<String> content) {
this.content = content;
}
public List<Integer> getPricelist() {
return pricelist;
}
public void setPricelist(List<Integer> pricelist) {
this.pricelist = pricelist;
}
}
VipDrinks(Pojo):
public class VipDrinks {
#SerializedName("drinks")
#Expose
private List<Drink> drinks = null;
public List<Drink> getDrinks() {
return drinks;
}
public void setDrinks(List<Drink> drinks) {
this.drinks = drinks;
}
}
JSON has the following structure:
{
"drinks":[ {
"title":,
"bg":[],
"content":[],
"pricelist":[],
},
{...}
]
}
Here is the Activity with the Parsing Request:
public class drinks_selection extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_drinks_selection);
final ExpandableListView listView = findViewById(R.id.vip_drinks_listview);
/** PARSING JSON FROM SERVER */
final JsonObjectRequest galleryUrls = new JsonObjectRequest(Request.Method.GET, PARSE_URL, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
try {
JSONArray packageArray = response.getJSONArray("drinks");
Log.e("response", String.valueOf(response));
GsonBuilder gsonBuilder = new GsonBuilder();
Gson gson = gsonBuilder.create();
List<Drink> vipDrinks = Arrays.asList(gson.fromJson(String.valueOf(packageArray),Drink[].class));
List<Drink> arrayList = new ArrayList<>(vipDrinks);
ExpandableListAdapterDrinks listAdapter = new ExpandableListAdapterDrinks(getApplicationContext(),arrayList);
listView.setAdapter( listAdapter);
listView.expandGroup(0);
} catch (JSONException e) {
e.printStackTrace();
}
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
Log.e("ERROR", String.valueOf(error));
}
});
RequestQueue rQ = Volley.newRequestQueue(this);
rQ.add(galleryUrls);
}
}
VIP Package List Group.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
android:id="#+id/lblListHeaderLayout"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="#dimen/default_padding"
android:background="#drawable/bg_vip_booking"
android:orientation="horizontal"
>
<RelativeLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:paddingStart="?android:attr/expandableListPreferredItemPaddingLeft"
android:paddingEnd="#dimen/feed_item_padding_left_right"
android:layout_weight="0.9"
>
<TextView
android:id="#+id/lblListHeader"
android:textSize="#dimen/text_title_list_header"
android:textColor="#color/Textwhite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/mont_bold"
/>
<TextView
android:id="#+id/lblListHeader_Price"
android:textSize="#dimen/text_title_list_header"
android:textColor="#color/Textwhite"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
android:fontFamily="#font/mont_bold"
/>
</RelativeLayout>
<Button
android:id="#+id/lblListHeaderButton"
android:layout_width="60dp"
android:layout_height="30dp"
android:background="#drawable/bg_btn_ripple_dark"
android:text="#string/btn_ok"
android:textColor="#color/Textwhite"
android:fontFamily="#font/mont_bold"
android:focusable="false"
/>
</LinearLayout>
VIP Drinks ListItem.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="60dip"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_centerInParent="true"
>
<TextView
android:id="#+id/lblListItemDrinks"
android:paddingTop="#dimen/padding_small"
android:paddingBottom="#dimen/padding_small"
android:textSize="#dimen/text_normal"
android:paddingLeft="#dimen/default_padding"
android:layout_width="150dp"
android:layout_height="wrap_content"
android:fontFamily="#font/mont_medium"
android:textColor="#color/Textwhite"
app:layout_constraintStart_toStartOf="parent"
/>
<RelativeLayout
android:id="#+id/vip_drinks_layout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="#id/lblListItemDrinks"
android:paddingStart="#dimen/default_padding"
android:layout_centerInParent="true"
android:paddingEnd="#dimen/default_padding"
app:layout_constraintEnd_toEndOf="parent"
>
<TextView
android:id="#+id/lblListItemDrinksUnitPrice"
android:textSize="#dimen/text_normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/mont_light"
android:textColor="#color/Textwhite"
android:paddingEnd="#dimen/padding_small"
/>
<Button
android:id="#+id/vip_drinks_btn_minus"
android:layout_toEndOf="#id/lblListItemDrinksUnitPrice"
android:layout_width="30dp"
android:layout_height="20dp"
android:text="-"
android:background="#drawable/bg_btn_ripple_dark"
android:textColor="#color/white"
android:textSize="14sp"
android:layout_marginEnd="#dimen/padding_small"
/>
<TextView
android:id="#+id/vip_drinks_amount"
android:layout_toEndOf="#+id/vip_drinks_btn_minus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/white"
android:fontFamily="#font/mont_light"
android:textSize="#dimen/text_normal"
android:layout_marginEnd="#dimen/padding_small"
/>
<Button
android:id="#+id/vip_drinks_btn_plus"
android:layout_toEndOf="#+id/vip_drinks_amount"
android:layout_width="30dp"
android:layout_height="20dp"
android:text="+"
android:background="#drawable/bg_btn_ripple_dark"
android:textColor="#color/white"
android:textSize="14sp"
android:layout_marginEnd="#dimen/padding_small"
/>
<TextView
android:id="#+id/lblListItemDrinksFinalPrice"
android:layout_toEndOf="#id/vip_drinks_btn_plus"
android:textSize="#dimen/text_normal"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:fontFamily="#font/mont_light"
android:textColor="#color/Textwhite"
/>
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Add a new class SelectedDrink like this:
public class SelectedDrink {
String content;
int qty;
}
Then try this adapter code:
public class ExpandableListAdapterDrinks extends BaseExpandableListAdapter {
private Context context;
private List<Drink> drinksList;
private Button btReset, btOk;
private List<Integer> groupSum;
private List<List<Integer>> qty;
private int totalSum = 0;
class ViewHolder {
TextView childText,counterText, childUnitPrice, childFinalPrice;
Button btn_plus,btn_minus;
}
class Pos{
int group;
int child;
Pos(int group, int child){
this.group = group;
this.child = child;
}
}
public ExpandableListAdapterDrinks(Context context, List<Drink> drinksList,
Button btReset, Button btOk) {
this.context = context;
this.drinksList= drinksList;
this.btReset = btReset;
this.btOk = btOk;
groupSum = new ArrayList<>();
qty = new ArrayList<>();
for(int i=0; i<drinksList.size(); i++) {
groupSum.add(0);
List<Integer> orderedQty = new ArrayList<>();
for(int j=0; j<drinksList.get(i).getContent().size(); j++) orderedQty.add(0);
qty.add(orderedQty);
}
}
private void resetGroupSum(int groupPosition) {
totalSum -= groupSum.get(groupPosition);
groupSum.set(groupPosition, 0);
resetGroupChildrenQty(groupPosition);
}
private void resetGroupChildrenQty(int groupPosition) {
for(int i=0; i<qty.get(groupPosition).size(); i++) qty.get(groupPosition).set(i, 0);
}
#Override
public int getGroupCount() {
return drinksList.size();
}
#Override
public int getChildrenCount(int groupPosition) {
return drinksList.get(groupPosition).getContent().size();
}
#Override
public Drink getGroup(int groupPosition) {
return drinksList.get(groupPosition);
}
#Override
public String getChild(int groupPosition, int childPosition) {
return drinksList.get(groupPosition).getContent().get(childPosition);
}
#Override
public long getGroupId(int groupPosition) {
return groupPosition;
}
#Override
public long getChildId(int groupPosition, int childPosition) {
return childPosition;
}
#Override
public boolean hasStableIds() {
return false;
}
#Override
public View getGroupView(int groupPosition, boolean isExpanded, View view, ViewGroup parent) {
String headerTitle = drinksList.get(groupPosition).getTitle();
/** HEADER TEXT HERE */
if(view==null) {
LayoutInflater inflater = (LayoutInflater)this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.vip_package_listgroup,null);
}
LinearLayout bgcolor = view.findViewById(R.id.lblListHeaderLayout);
TextView lblListHeader = (TextView)view.findViewById(R.id.lblListHeader);
TextView lblListHeaderPrice = (TextView)view.findViewById(R.id.lblListHeader_Price);
Button lblListHeaderButton = view.findViewById(R.id.lblListHeaderButton);
if(groupSum.get(groupPosition) > 0){
lblListHeaderPrice.setVisibility(View.VISIBLE);
lblListHeaderPrice.setText(String.format("%.02f", (float)groupSum.get(groupPosition)).replace(".", ",") + "€");
}else{
lblListHeaderPrice.setVisibility(View.GONE);
lblListHeaderButton.setVisibility(View.GONE);
}
if(!drinksList.get(groupPosition).getBg().get(0).isEmpty() || !drinksList.get(groupPosition).getBg().get(1).isEmpty() ) {
List<String> colorGradientTopBottom = drinksList.get(groupPosition).getBg();
int[] colors = {Color.parseColor(colorGradientTopBottom.get(0)),Color.parseColor(colorGradientTopBottom.get(1))};
GradientDrawable gd = new GradientDrawable(GradientDrawable.Orientation.TOP_BOTTOM, colors);
gd.setCornerRadius(0f);
bgcolor.setBackground(gd);
} else {
//bgcolor.setBackgroundColor(ContextCompat.getColor(context, R.color.cardview_bg));
}
lblListHeader.setText(headerTitle);
return view;
}
#Override
public View getChildView(int groupPosition, int childPosition, boolean isLastChild, View view, ViewGroup parent) {
/** Drinks List */
ViewHolder viewHolder;
String childDrink = getChild(groupPosition, childPosition);
int childPrice = getGroup(groupPosition).getPricelist().get(childPosition);
if (view == null) {
LayoutInflater inflater = (LayoutInflater) this.context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
view = inflater.inflate(R.layout.vip_drinks_listitem, null);
viewHolder = new ViewHolder();
viewHolder.childText = view.findViewById(R.id.lblListItemDrinks);
viewHolder.childUnitPrice = view.findViewById(R.id.lblListItemDrinksUnitPrice);
viewHolder.counterText = view.findViewById(R.id.vip_drinks_amount);
viewHolder.childFinalPrice = view.findViewById(R.id.lblListItemDrinksFinalPrice);
viewHolder.btn_plus = view.findViewById(R.id.vip_drinks_btn_plus);
viewHolder.btn_minus = view.findViewById(R.id.vip_drinks_btn_minus);
viewHolder.btn_plus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Pos pos = (Pos) v.getTag();
int orderedQty = qty.get(pos.group).get(pos.child);
orderedQty++;
qty.get((pos.group)).set(pos.child, orderedQty);
groupSum.set(pos.group, groupSum.get(pos.group) + getGroup(pos.group).getPricelist().get(pos.child));
notifyDataSetChanged();
totalSum += getGroup(pos.group).getPricelist().get(pos.child);
btOk.setText(String.format("%.02f", (float)totalSum).replace(".", ",") + "€");
btReset.setEnabled(true);
}
});
viewHolder.btn_minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Pos pos = (Pos) v.getTag();
int orderedQty = qty.get(pos.group).get(pos.child);
if (orderedQty > 0) {
orderedQty--;
qty.get((pos.group)).set(pos.child, orderedQty);
groupSum.set(pos.group, groupSum.get(pos.group) - getGroup(pos.group).getPricelist().get(pos.child));
notifyDataSetChanged();
totalSum -= getGroup(pos.group).getPricelist().get(pos.child);
if (totalSum == 0) resetTotalSum();
else btOk.setText(String.format("%.02f", (float)totalSum).replace(".", ",") + "€");
}
}
});
} else {
viewHolder = (ViewHolder) view.getTag();
}
viewHolder.childText.setText(childDrink);
viewHolder.childUnitPrice.setText(String.format("%.02f", (float)childPrice).replace(".", ",") + "€");
int orderedQty = qty.get(groupPosition).get(childPosition);
viewHolder.counterText.setText(String.valueOf(orderedQty));
viewHolder.childFinalPrice.setText(String.format("%.02f", (float)orderedQty*childPrice).replace(".", ",") + "€");
viewHolder.btn_minus.setTag(new Pos(groupPosition, childPosition));
viewHolder.btn_plus.setTag(new Pos(groupPosition, childPosition));
view.setTag(viewHolder);
return view;
}
#Override
public boolean isChildSelectable(int i, int i1) {
return false;
}
public void resetTotalSum() {
for(int i=0; i<drinksList.size(); i++) {
resetGroupSum(i);
}
notifyDataSetChanged();
btReset.setEnabled(false);
btOk.setText(String.valueOf(0));
}
public ArrayList<SelectedDrink> getOrderList() {
ArrayList<SelectedDrink> orderList = new ArrayList<>();
for(int i=0; i<drinksList.size(); i++) {
for(int j=0; j<drinksList.get(i).getContent().size(); j++) {
if(qty.get(i).get(j) > 0) {
SelectedDrink selectedDrink = new SelectedDrink();
selectedDrink.content = getGroup(i).getContent().get(j);
selectedDrink.qty = qty.get(i).get(j);
orderList.add(selectedDrink);
}
}
}
return orderList;
}
}
I test the above with this activity:
public class MainActivity extends AppCompatActivity {
final private static int NUM_OF_GROUP = 5;
List<Drink> drinksList;
ExpandableListView listView;
ExpandableListAdapterDrinks expandableListAdapterDrinks;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btRest = findViewById(R.id.btReset);
Button btOk = findViewById(R.id.btOK);
listView = findViewById(R.id.elvDrinks);
initDataList();
expandableListAdapterDrinks =
new ExpandableListAdapterDrinks(getApplicationContext(), drinksList, btRest, btOk);
listView.setAdapter(expandableListAdapterDrinks);
listView.expandGroup(0);
btRest.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
expandableListAdapterDrinks.resetTotalSum();
for(int i=0; i<drinksList.size(); i++) listView.collapseGroup(i);
listView.expandGroup(0);
}
});
btOk.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String msg = "Nothing Selected";
Button button = (Button)view;
if(!button.getText().equals("0")) {
msg = "Upload!\n";
ArrayList<SelectedDrink> selectedDrinks = expandableListAdapterDrinks.getOrderList();
for(SelectedDrink selectedDrink: selectedDrinks) {
msg += selectedDrink.content + " " + selectedDrink.qty + "\n";
}
msg += "Total: " + button.getText();
}
Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_LONG).show();
}
});
}
private void initDataList(){
drinksList = new ArrayList<>();
List<String> content;
List<Integer> pricelist;
List<String> bg;
for(int i=1; i<=NUM_OF_GROUP; i++) {
content = new ArrayList<>();
pricelist = new ArrayList<>();
bg = new ArrayList<>();
for(int j = 1; j<(NUM_OF_GROUP + new Random().nextInt(5)); j++){
content.add("Drink " + i + "-" + j);
pricelist.add(new Random().nextInt(1000));
bg.add("#008577");
bg.add("#D81B60");
}
Drink drink = new Drink();
drink.setTitle("Group " + i);
drink.setContent(content);
drink.setPricelist(pricelist);
drink.setBg(bg);
drinksList.add(drink);
}
}
}
and this 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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<LinearLayout
android:id="#+id/llBtns"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:orientation="horizontal">
<Button
android:id="#+id/btReset"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:enabled="false"
android:text="Reset" />
<Button
android:id="#+id/btOK"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="0.5"
android:text="0" />
</LinearLayout>
<ExpandableListView
android:id="#+id/elvDrinks"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="#id/llBtns">
</ExpandableListView>
</RelativeLayout>
Also, your Drink class, vip_package_listgroup.xml and vip_drinks_listitem.xml are also needed. Hope that helps!
I have a problem with my BaseAdapter.
When I add items to my listview I get this:
When I remove the items one by one I get this problem:
BaseAdapter.java
public class TipsterAdapter extends BaseAdapter implements ListAdapter {
private ArrayList<String> list = new ArrayList<String>();
private Context context;
AlertDialog dialog;
private static final int TYPE_ITEM = 0;
private static final int TYPE_SEPARATOR = 1;
private TreeSet<Integer> sectionHeader = new TreeSet<Integer>();
private LayoutInflater mInflater;
DataBase datb;
ImageButton removeBttn;
ImageButton editBttn;
Button visit;
public TipsterAdapter(Context context, DataBase datb) {
mInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
this.datb = datb;
this.context = context;
}
#Override
public int getCount() {
return list.size();
}
#Override
public Object getItem(int pos) {
if(list.size() == 0) {
return null;
}
return list.get(pos);
}
#Override
public long getItemId(int pos) {
return pos;
//just return 0 if your list items do not have an Id variable.
}
public static class ViewHolder {
public TextView textView;
}
#Override
public int getItemViewType(int position) {
return sectionHeader.contains(position) ? TYPE_SEPARATOR : TYPE_ITEM;
}
#Override
public int getViewTypeCount() {
return 2;
}
public void addItem(final String item) {
list.add(item);
notifyDataSetChanged();
}
public void addSectionHeaderItem(final String item) {
list.add(item);
sectionHeader.add(list.size() - 1);
notifyDataSetChanged();
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
int rowType = getItemViewType(position);
final View bieg = convertView;
if (convertView == null) {
holder = new ViewHolder();
switch (rowType) {
case TYPE_ITEM:
convertView = mInflater.inflate(R.layout.row, null);
holder.textView = (TextView) convertView.findViewById(R.id.textView1);
removeBttn = (ImageButton)convertView.findViewById(R.id.remove_btn);
editBttn = (ImageButton)convertView.findViewById(R.id.edit_btn);
visit = (Button) convertView.findViewById(R.id.visitar);
if(getItem(position).toString().equals("Los tipsters agregados aparecerán aquí")) {
holder.textView.setTextSize(15);
removeBttn.setVisibility(View.INVISIBLE);
editBttn.setVisibility(View.INVISIBLE);
visit.setVisibility(View.INVISIBLE);
} else if (getItem(position).toString().equals("TasmaTenis ITF") || getItem(position).toString().equals("KrlosTM") || getItem(position).toString().equals("GreengoSIR") || getItem(position).toString().equals("Ribe Experience")) {
removeBttn.setVisibility(View.INVISIBLE);
editBttn.setVisibility(View.INVISIBLE);
visit.setVisibility(View.VISIBLE);
} else {
visit.setVisibility(View.INVISIBLE);
removeBttn.setVisibility(View.VISIBLE);
editBttn.setVisibility(View.VISIBLE);
}
visit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(getItem(position).toString().equals("KrlosTM")) {
String url = "https://t.me/KrlosTMpicks";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
context.startActivity(i);
} else if(getItem(position).toString().equals("TasmaTenis ITF")) {
String url = "https://t.me/TasmaPicksTenis";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
context.startActivity(i);
} else if(getItem(position).toString().equals("GreengoSIR")) {
String url = "https://t.me/GreengoSIR";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
context.startActivity(i);
} else if(getItem(position).toString().equals("Ribe Experience")) {
String url = "https://t.me/ribexperience";
Intent i = new Intent(Intent.ACTION_VIEW);
i.setData(Uri.parse(url));
context.startActivity(i);
} else {
}
}
}
);
final View finalConvertView = convertView;
final ViewHolder finalHolder = holder;
removeBttn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v) {
OperacionesBaseDatos db = new OperacionesBaseDatos();
db.eliminarTipster(getItem(position).toString());
Toast.makeText(v.getContext(), "Tipster borrado", Toast.LENGTH_LONG).show();
list.clear();
sectionHeader = new TreeSet<Integer>();
list = new ArrayList<String>();
notifyDataSetChanged();
Cursor cursor=datb.GetAllTipsterData();
list.clear();
addSectionHeaderItem("Mis Tipsters");
SQLiteDatabase db2 = datb.getWritableDatabase();
long numRows = DatabaseUtils.queryNumEntries(db2, "tipster");
if(numRows==0) {
final ImageButton removeBttn = (ImageButton) finalConvertView.findViewById(R.id.remove_btn);
final ImageButton editBttn = (ImageButton) finalConvertView.findViewById(R.id.edit_btn);
final Button visit = (Button) finalConvertView.findViewById(R.id.visitar);
Activity act = (Activity)context;
act.runOnUiThread(new Runnable(){
#Override
public void run() {
removeBttn.setVisibility(View.INVISIBLE);
editBttn.setVisibility(View.INVISIBLE);
visit.setVisibility(View.INVISIBLE);
} });
addItem("Los tipsters agregados aparecerán aquí");
}
while(cursor.moveToNext()) {
addItem(cursor.getString(0));
}
addSectionHeaderItem("Tipsters Recomendados");
addItem("TasmaTenis ITF");
addItem("KrlosTM");
addItem("GreengoSIR");
addItem("Ribe Experience");
datb.close();
notifyDataSetChanged();
}
});
editBttn.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(final View v23) {
AlertDialog.Builder alertDialog = new AlertDialog.Builder(new ContextThemeWrapper(v23.getContext(), R.style.AlertDialogCustom));
alertDialog.setTitle("Editar Tipster");
alertDialog.setTitle("Editar Tipster");
alertDialog.setMessage("Escribe el nuevo nombre del tipster:");
final EditText input = new EditText(v23.getContext());
input.setTextColor(ContextCompat.getColor(v23.getContext(), android.R.color.black));
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT);
input.setLayoutParams(lp);
alertDialog.setView(input);
alertDialog.setPositiveButton("Cambiar",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
String fechaActual = Calendar.getInstance().getTime().toString();
//if (string.trim().length() == 0) {
try {
SQLiteDatabase db=datb.getWritableDatabase();
String sql="UPDATE tipster set nombre='" + input.getText().toString() + "' where nombre like '" + getItem(position).toString() + "'";
try{
db.execSQL(sql);
}catch(SQLException ex){
Log.d(TAG,"update data failure");
}
} finally {
Toast.makeText(v23.getContext(),
"Tipster modificado", Toast.LENGTH_SHORT).show();
}
list.clear();
sectionHeader = new TreeSet<Integer>();
Cursor cursor=datb.GetAllTipsterData();
addSectionHeaderItem("Mis Tipsters");
while(cursor.moveToNext()) {
addItem(cursor.getString(0));
}
addSectionHeaderItem("Tipsters Recomendados");
addItem("TasmaTenis ITF");
addItem("KrlosTM");
addItem("GreengoSIR");
addItem("Ribe Experience");
datb.close();
notifyDataSetChanged();
}
});
alertDialog.setNegativeButton("Cancelar",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
dialog.cancel();
}
});
dialog = alertDialog.create();
dialog.setOnShowListener(new DialogInterface.OnShowListener() {
#Override
public void onShow(DialogInterface dialog) {
((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
}
});
input.addTextChangedListener(new TextWatcher() {
#Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
}
#Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
#Override
public void afterTextChanged(Editable s) {
// Check if edittext is empty
if (TextUtils.isEmpty(s) || s.toString().trim().length() == 0) {
// Disable ok button
((AlertDialog) dialog).getButton(
AlertDialog.BUTTON_POSITIVE).setEnabled(false);
} else {
// Something into edit text. Enable the button.
((AlertDialog) dialog).getButton(
AlertDialog.BUTTON_POSITIVE).setEnabled(true);
}
}
});
dialog.show();
notifyDataSetChanged();
}
});
break;
case TYPE_SEPARATOR:
convertView = mInflater.inflate(R.layout.listview_sections, null);
holder.textView = (TextView) convertView.findViewById(R.id.textSeparator);
break;
}
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.textView.setText(list.get(position));
View view = convertView;
//Handle TextView and display string from your list
//TextView listItemText = (TextView)view.findViewById(R.id.textView1);
//listItemText.setText(list.get(position));
//Handle buttons and add onClickListeners
//holder.textView.setText(list.get(position));
return view;
}
An I call this from Tipster.java with this:
public void displayList(View view){
db = new DataBase ((MainActivity)getActivity());
Cursor cursor=db.GetAllTipsterData();
ArrayList<String> mArrayList = new ArrayList<String>();
adapter = new TipsterAdapter((MainActivity)getActivity(), db);
adapter.addSectionHeaderItem("Mis Tipsters");
Log.e("COLUMNAS: ", ""+cursor.getColumnCount());
SQLiteDatabase db2 = db.getWritableDatabase();
long numRows = DatabaseUtils.queryNumEntries(db2, "tipster");
if(numRows==0) {
adapter.addItem("Los tipsters agregados aparecerán aquí");
}
while(cursor.moveToNext()) {
adapter.addItem(cursor.getString(0));
}
adapter.addSectionHeaderItem("Tipsters Recomendados");
adapter.addItem("TasmaTenis ITF");
adapter.addItem("KrlosTM");
adapter.addItem("GreengoSIR");
adapter.addItem("Ribe Experience");
ListView lv = (ListView) view.findViewById(R.id.listita);
lv.setAdapter(adapter);
db.close();
}
row.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" >
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:layout_alignParentLeft="true"
android:paddingLeft="8dp"
android:textSize="20sp"
android:textStyle="bold" />
<ImageButton
android:id="#+id/remove_btn"
android:layout_width="50dp"
android:src="#drawable/ic_removebttn"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="5dp"
android:layout_alignTop="#+id/edit_btn"
android:layout_alignBottom="#+id/edit_btn" />
<ImageButton
android:id="#+id/edit_btn"
android:layout_width="50dp"
android:src="#drawable/ic_editbttn"
android:layout_height="50dp"
android:layout_toLeftOf="#id/remove_btn"
android:layout_centerVertical="true"
android:layout_marginRight="10dp" />
<Button
android:text="Visitar"
android:layout_width="89dp"
android:layout_height="wrap_content"
android:layout_alignTop="#+id/remove_btn"
android:id="#+id/visitar"
android:visibility="gone"
android:layout_alignRight="#+id/remove_btn"
android:layout_alignEnd="#+id/remove_btn" />
listview_sections.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#52b1ff"
android:gravity="center_vertical" >
<TextView
android:id="#+id/textSeparator"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:padding="8dp"
android:text=""
android:textAllCaps="true"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="#ffffff"
android:textStyle="bold"
android:visibility="visible" />
</LinearLayout>
Hope anybody can help me. Thanks!
Be sure to add and remove items of the ListView thru the Adapter. After adding/removing items call the function below to reflect your changes.
adapter.notifyDataSetChanged();
Hope this works for you.
I'm trying to take a RecyclerView with a StaggeredGridLayout and make it a fixed height by having it measure the views and set the height dynamically. I'm overriding the onMeasure(), but it does not always seem to measure correctly. I'd say it works about 50% of the time. The other 50% of the time it under measures it. I think it has to do with when the text wraps in the view_tile_small.xml, but I'm not sure.
Fragment
public class AtTheMuseumFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
//Odds n Ends Variables
private MapFragment mapFragment;
private FragmentTransaction fragmentTransaction;
private User user = new User();
private MuseumCollection museumCollection;
private Context context;
//Story Grid Adapter Variables
private AtTheMuseumAdapter nearMeAdapter;
private TileFactory tileFactory;
//Interfaces
private OnFragmentChangeListener changeListener;
#Bind(R.id.stories_list_view) RecyclerView storiesListView;
#Bind(R.id.swipe_container) SwipeRefreshLayout swipeRefreshLayout;
public static AtTheMuseumFragment newInstance(MuseumCollection museumCollection) {
AtTheMuseumFragment fragment = new AtTheMuseumFragment();
Bundle args = new Bundle();
fragment.setArguments(args);
return fragment;
}
public AtTheMuseumFragment() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
museumCollection = ((MainActivity) getActivity()).getMuseumCollection();
context = getActivity().getApplicationContext();
tileFactory = new TileFactory();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_museum, container, false);
ButterKnife.bind(this, view);
//Sets up the layoutManager to the Mason View
storiesListView.setLayoutManager(new MeasuredStaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL));
//Sets up The map
try{
fragmentTransaction = getChildFragmentManager().beginTransaction();
mapFragment = MapFragment.newInstance(MapFragment.MUSEUM);
fragmentTransaction.add(R.id.museum_map, mapFragment).commit();
}catch (Exception e){
Log.d("Map - Initial Inflate:", e.getMessage());
}
//Sets up the swipe to refresh jawn
swipeRefreshLayout.setOnRefreshListener(this);
setNearMeAdapter();
return view;
}
#Override
public void onResume(){
super.onResume();
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
try {
changeListener = (OnFragmentChangeListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnFragmentInteractionListener");
}
}
#Override
public void onDetach() {
super.onDetach();
changeListener = null;
}
/**
* Loads the adapter once the data is ready
*
*/
public void setNearMeAdapter(){
List<MuseumObject> newList = museumCollection.getObjectsNearUser(User.position, 4);
List<Tile> tiles = tileFactory.createAtMuseumFeed(newList, true);
nearMeAdapter = new AtTheMuseumAdapter(context, tiles, getActivity());
storiesListView.setAdapter(nearMeAdapter);
}
/**
* Refreshes Adapter with new data
*
*/
public void refreshNearMeAdapter(){
//TODO CHANGE THIS TO LOCATION BASED WHEN TIME IS RIGHT - Peter
//nearMeAdapter.setNewData(MuseumCollection.getObjectsNearUser(User.position, 4));
List<MuseumObject> newList = museumCollection.getRandomOrder();
nearMeAdapter.setNewData(tileFactory.createAtMuseumFeed(newList,false));
}
/**
* Adds past data to the Adapter
*
*/
public void loadPastObjects(){
//TODO MAKE THIS NOT ONLY LOAD RANDOM DATA - Peter
List<MuseumObject> newList = museumCollection.getRandomOrder();
nearMeAdapter.addNewData(tileFactory.createAtMuseumFeed(newList, false));
nearMeAdapter.notifyDataSetChanged();
}
#Override
public void onRefresh() {
user.updateUserLocation();
refreshNearMeAdapter();
mapFragment.refreshMap(museumCollection.getObjectFeed());
swipeRefreshLayout.setRefreshing(false);
}
public interface OnFragmentChangeListener {
void onFragmentChange(String fragment);
}
#OnClick(R.id.explore_map)
public void exploreMap(){
changeListener.onFragmentChange("map");
}
#OnClick(R.id.load_more)
public void loadMore(){
loadPastObjects();
}
}
MeasuredStaggeredGridLayoutManager
public class MeasuredStaggeredGridLayoutManager extends StaggeredGridLayoutManager {
public MeasuredStaggeredGridLayoutManager(int spanCount, int orientation) {
super(spanCount, orientation);
}
private int[] mMeasuredDimension = new int[2];
#Override
public void onMeasure(RecyclerView.Recycler recycler, RecyclerView.State state,
int widthSpec, int heightSpec) {
final int widthMode = View.MeasureSpec.getMode(widthSpec);
final int heightMode = View.MeasureSpec.getMode(heightSpec);
final int widthSize = View.MeasureSpec.getSize(widthSpec);
final int heightSize = View.MeasureSpec.getSize(heightSpec);
int width = 0;
int height = 0;
int heightR = 0;
int heightL = 0;
for (int i = 0; i < getItemCount(); i++) {
measureScrapChild(recycler, i,
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
View.MeasureSpec.makeMeasureSpec(i, View.MeasureSpec.UNSPECIFIED),
mMeasuredDimension);
if (getOrientation() == HORIZONTAL) {
width = width + mMeasuredDimension[0];
if (i == 0) {
height = mMeasuredDimension[1];
}
} else {
if(i % 2 == 0){
heightL += mMeasuredDimension[1];
}else{
heightR += mMeasuredDimension[1];
}
if (i == 0) {
width = mMeasuredDimension[0];
}
}
}
switch (widthMode) {
case View.MeasureSpec.EXACTLY:
width = widthSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
switch (heightMode) {
case View.MeasureSpec.EXACTLY:
height = heightSize;
case View.MeasureSpec.AT_MOST:
case View.MeasureSpec.UNSPECIFIED:
}
if(heightL != 0 || heightR != 0){
height = (heightL > heightR) ? heightL : heightR;
}
//TODO come up with a better way to fix the slightly wrong height
// must be not accounting for padding or margin or something - Peter
height += (20 * (getItemCount() / 2)) + 5;
setMeasuredDimension(width, height);
}
private void measureScrapChild(RecyclerView.Recycler recycler, int position, int widthSpec,
int heightSpec, int[] measuredDimension) {
View view = recycler.getViewForPosition(position);
if (view != null) {
RecyclerView.LayoutParams p = (RecyclerView.LayoutParams) view.getLayoutParams();
int childWidthSpec = ViewGroup.getChildMeasureSpec(widthSpec,
getPaddingLeft() + getPaddingRight(), p.width);
int childHeightSpec = ViewGroup.getChildMeasureSpec(heightSpec,
getPaddingTop() + getPaddingBottom(), p.height);
view.measure(childWidthSpec, childHeightSpec);
measuredDimension[0] = view.getMeasuredWidth() + p.leftMargin + p.rightMargin;
measuredDimension[1] = view.getMeasuredHeight() + p.bottomMargin + p.topMargin;
recycler.recycleView(view);
}
}
}
AtTheMuseumAdapter
public class AtTheMuseumAdapter extends RecyclerView.Adapter<AtTheMuseumAdapter.MuseumStoriesViewHolder> {
private List<Tile> tiles;
private LayoutInflater inflater;
private AdapterCallback mListener;
private Context context;
public AtTheMuseumAdapter(Context context, List<Tile> tiles, Activity activity) {
this.tiles = tiles;
this.context = context;
inflater = LayoutInflater.from(this.context);
//Sets up interface between Stock Adapter and Fragment
try {
this.mListener = ((AdapterCallback) activity);
} catch (ClassCastException e) {
throw new ClassCastException("Fragment must implement AdapterCallback.");
}
}
#Override
public MuseumStoriesViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
View view = inflater.inflate(R.layout.view_tile_small, viewGroup, false);
MuseumStoriesViewHolder holder = new MuseumStoriesViewHolder(view);
return holder;
}
#Override
public void onBindViewHolder(MuseumStoriesViewHolder holder, int position) {
Tile currentTile = tiles.get(position);
holder.title.setText(currentTile.getTitle());
holder.desc.setText(currentTile.getDescription());
holder.type.setText(currentTile.getObjectTypeName());
//Using Picasso since it handles caching and all that jazz
Picasso.with(context)
.load(currentTile.getImg())
.into(holder.img);
}
#Override
public int getItemCount() {
return tiles.size();
}
public void setNewData(List<Tile> newItems){
tiles = newItems;
notifyDataSetChanged();
}
public void addNewData(final List<Tile> newItems){
tiles.addAll(newItems);
notifyDataSetChanged();
}
class MuseumStoriesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView type,title,desc;
public ImageView img;
public MuseumStoriesViewHolder(View itemView) {
super(itemView);
//Tried Butterknife, but it doesn't seem like it was working in the view holder. - Peter
type = (TextView) itemView.findViewById(R.id.small_box_type);
title = (TextView) itemView.findViewById(R.id.small_box_title);
desc = (TextView) itemView.findViewById(R.id.small_box_desc);
img = (ImageView) itemView.findViewById(R.id.small_box_image);
itemView.setOnClickListener(this);
}
#Override
public void onClick(View view) {
Tile t = tiles.get(getPosition());
switch (t.getObjectTypeName()){
case Tile.OBJECT_NAME:
mListener.onObjectClick(t.getObjectID());
break;
case Tile.TOUR_NAME:
mListener.onTourCLick(t.getTourID());
break;
case Tile.STORY_NAME:
mListener.onStoryClick(t.getObjectID(), t.getStoryID());
break;
}
}
}
public interface AdapterCallback {
public void onObjectClick(String objectID);
public void onStoryClick(String objectID, String storyID);
public void onTourCLick(String tourID);
}
}
view_tile_small.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"
android:layout_margin="#dimen/margin_small"
android:background="#color/small_box_background_color">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<!--TODO Make layout_height wrap contenet -->
<ImageView
android:id="#+id/small_box_image"
android:layout_width="match_parent"
android:layout_height="150dp"
android:adjustViewBounds="true"
android:scaleType="centerCrop"
android:maxHeight="150dp"
android:background="#color/transparent"/>
<ImageView
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_gravity="right"
android:src="#drawable/abc_btn_rating_star_off_mtrl_alpha"
/>
<TextView
android:id="#+id/small_box_type"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="#dimen/margin_normal"
android:paddingBottom="#dimen/margin_normal"
android:textSize="#dimen/font_small"
android:textColor="#color/font_white"
android:background="#drawable/small_box_text_bottom_border"
android:layout_gravity="bottom"
android:text="Object Story"
/>
</FrameLayout>
<TextView
android:id="#+id/small_box_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/margin_larger"
android:layout_marginBottom="#dimen/margin_normal"
android:layout_marginRight="#dimen/margin_larger"
android:layout_marginTop="#dimen/margin_larger"
android:textSize="#dimen/font_large"
android:textColor="#color/font_black"
android:text="Sample Text Here"
/>
<TextView
android:id="#+id/small_box_desc"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="#dimen/margin_larger"
android:layout_marginBottom="#dimen/margin_larger"
android:textSize="#dimen/font_normal"
android:textColor="#color/font_black"
android:textStyle="italic"
android:text="Sample Text Here"
/>
</LinearLayout>
fragment_museum
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.bluecadet.android.nasm.ui.AtTheMuseumFragment"
android:id="#+id/swipe_container"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginBottom="100dp">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#FFFFFF"
android:descendantFocusability="blocksDescendants"
>
<TextView
android:id="#+id/museum_header"
style="#style/header"
android:text="#string/museum_header"
android:layout_margin="#dimen/margin_larger"
android:elevation="8dp"
/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="275dp"
android:elevation="2dp"
>
<FrameLayout
android:id="#+id/museum_map"
android:layout_height="fill_parent"
android:layout_width="match_parent"
/>
<include
layout="#layout/view_explore_map" />
</FrameLayout>
<android.support.v7.widget.RecyclerView
android:id="#+id/stories_list_view"
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="#dimen/margin_normal"
android:layout_marginLeft="#dimen/margin_small"
android:layout_marginRight="#dimen/margin_small"
android:layout_marginTop="#dimen/margin_normal"
android:stretchMode="columnWidth"
/>
<Button
android:id="#+id/load_more"
style="#style/home_button"
android:gravity="center"
android:text="#string/button_load_more"
/>
</LinearLayout>
</ScrollView>
</android.support.v4.widget.SwipeRefreshLayout>
ViewTreeObserver code I'm playing with now. It's in Fragment.
mTopStoriesListView.setLayoutManager(new NewMeasuredStaggeredLayoutManager(2, StaggeredGridLayoutManager.VERTICAL, mTopStoriesListView));
mTopStoriesListView.setNestedScrollingEnabled(false);
//Testing Issue 54
final ViewTreeObserver viewTreeObserver = mTopStoriesListView.getViewTreeObserver();
if (viewTreeObserver.isAlive()) {
viewTreeObserver.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
mTopStoriesListView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
int l = 0,r = 0;
for(int i = 0 ; i < mNearMeAdapter.getItemCount(); i++){
int h = mTopStoriesListView.getLayoutManager().findViewByPosition(i).getHeight();
ViewGroup.MarginLayoutParams layout = (ViewGroup.MarginLayoutParams) mTopStoriesListView.getLayoutManager()
.findViewByPosition(i).getLayoutParams();
int t = layout.topMargin;
int b = layout.bottomMargin;
if(i % 2 == 0){
l += h + t + b;
}else{
r += h + t + b;
}
}
int viewHeight = (l > r) ? l : r;
mTopStoriesListView.getLayoutParams().height = viewHeight;
Log.d("TAG", String.valueOf(viewHeight));
}
});
}
//END TEST
Have you look at ViewTreeObserver ?
I got a similar problem on a passed project and I have found it more reliable than onMesure to dynamically get Layout properties
You can go through it from here : http://developer.android.com/reference/android/view/ViewTreeObserver.html