Android Recyclerview with Viewholder changing width and height onClick - java

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>

Related

RecyclerView Android Dynamic Height

I am looking at creating dynamic heights in my RecyclerView to be responsive across all devices. Currently this works fine but for the first two rows at the start I have a double cell and the height of these two rows gets set to the first cell. I want instead this cell on both the first and second row to match the height of the last cell and become a rectangle. I have tried a few ways but none seem to work I am not sure where the problem is but I hope someone can show me. I will attach screenshots and the code below.
SquareLayout.java
public class SquareLayout extends LinearLayout {
public SquareLayout(Context context) {
super(context);
}
public SquareLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
public SquareLayout(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onMeasure(int width, int height) {
// int width = MeasureSpec.getSize(widthMeasureSpec);
//int height = MeasureSpec.getSize(heightMeasureSpec);
// note we are applying the width value as the height
//if(width>=370){
// super.onMeasure(widthMeasureSpec, widthMeasureSpec/2);
// }
// else{
// super.onMeasure(widthMeasureSpec, widthMeasureSpec);
// }
super.onMeasure(width, width);
// Log.d("int","int is: "+ width);
}
}
DataAdapter.java
public class DataAdapter extends RecyclerView.Adapter<DataAdapter.ViewHolder> {
private ArrayList<AndroidVersion> android;
private Context context;
public DataAdapter(Context context,ArrayList<AndroidVersion> android) {
this.android = android;
this.context = context;
}
#Override
public DataAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.row_layout, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(DataAdapter.ViewHolder viewHolder, int i) {
// int width = viewHolder.tv_android.getMeasuredWidth() / 2; //returns -1
Log.d("MYINT", "value: " + i);
//Picasso.with(context).load(android.get(i).getAndroid_image_url()).resize(240, 120).into(viewHolder.img_android);
}
#Override
public int getItemCount() {
return android.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private LinearLayout testheight;
private ImageView img_android;
public ViewHolder(View view) {
super(view);
}
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private final String android_version_names[] = {
"test1",
"test2",
"test3",
"test4",
"test5",
"test6",
"test7",
"test8",
"test9",
"test10"
};
private final String android_image_urls[] = {
"http://example.com/images/test.png",
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
}
private void initViews(){
RecyclerView recyclerView = (RecyclerView)findViewById(R.id.card_recycler_view);
recyclerView.setHasFixedSize(true);
RecyclerView.LayoutManager mLayoutManager = new GridLayoutManager(getApplicationContext(),3);
ArrayList<AndroidVersion> androidVersions = prepareData();
((GridLayoutManager) mLayoutManager).setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {
#Override
public int getSpanSize(int position) {
if (position == 0 || position == 2) {
return 2; // ITEMS AT POSITION 1 AND 6 OCCUPY 3 SPACES
}
else {
return 1; // OTHER ITEMS OCCUPY ONLY A SINGLE SPACE
}
}
});
recyclerView.setLayoutManager(mLayoutManager);
DataAdapter adapter = new DataAdapter(getApplicationContext(), androidVersions);
recyclerView.setAdapter(adapter);
}
private ArrayList<AndroidVersion> prepareData(){
ArrayList<AndroidVersion> android_version = new ArrayList<>();
for(int i=0;i<android_version_names.length;i++){
AndroidVersion androidVersion = new AndroidVersion();
androidVersion.setAndroid_version_name(android_version_names[i]);
androidVersion.setAndroid_image_url(android_image_urls[i]);
android_version.add(androidVersion);
}
return android_version;
}
}
row_layout.xml
<?xml version="1.0" encoding="utf-8"?>
<example.SquareLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:background="#android:color/transparent"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:layout_marginBottom="10dp"
android:layout_marginStart="10dp"
android:background="#color/reloadedpurple"
android:elevation="6dp"
android:orientation="vertical">
<ImageView
android:id="#+id/img_android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true" />
<TextView
android:id="#+id/tv_android"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:textColor="#FFFFFF"
android:textStyle="bold" />
</LinearLayout>
</example.SquareLayout>

Carousel in RecyclerView

I want to display a carousel like an item in the RecyclerView. I use lib CarouselView.
MainActivity.java
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView list = (RecyclerView) findViewById(R.id.list);
list.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
list.setLayoutManager(layoutManager);
List<Integer> numbers = new ArrayList<>();
for (int i = 0; i < 10; i++) {
numbers.add(i);
}
final CarouselAdapter adapter = new CarouselAdapter(this, numbers);
list.setAdapter(adapter);
final SwipeRefreshLayout swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh);
swipeRefresh.setColorSchemeResources(R.color.green);
swipeRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
swipeRefresh.setRefreshing(false);
adapter.notifyDataSetChanged();
}
});
}
}
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.SwipeRefreshLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/green"
android:scrollbars="vertical"/>
</android.support.v4.widget.SwipeRefreshLayout>
CarouselAdapter.java
public class CarouselAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context context;
private List<Integer> numbers;
public CarouselAdapter(Context context, List<Integer> numbers) {
this.context = context;
this.numbers= numbers;
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_list, null);
return new CarouselViewHolder(view);
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
((CarouselViewHolder) holder).carousel.setPageCount(numbers.size());
((CarouselViewHolder) holder).carousel.setViewListener(viewListener);
}
#Override
public int getItemCount() {
return numbers.size();
}
private ViewListener viewListener = new ViewListener() {
#Override
public View setViewForPosition(int position) {
TextView textView = (TextView) LayoutInflater.from(context).inflate(R.layout.item_carousel, null);
textView.setText(String.valueOf(numbers.get(position)));
return textView;
}
};
private class CarouselViewHolder extends RecyclerView.ViewHolder {
public CarouselView carousel;
private CarouselViewHolder(View itemView) {
super(itemView);
carousel = (CarouselView) itemView.findViewById(R.id.carousel);
}
}
}
item_list.xml
<?xml version="1.0" encoding="utf-8"?>
<com.synnapps.carouselview.CarouselView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/carousel"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:fillColor="#color/green"/>
item_carousel.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp"/>
I change CarouselViewPager from CarouselView, added next code
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int height = 0;
if (getChildCount() != 0) {
for (int i = 0; i < getChildCount(); i++) {
View child = getChildAt(i);
child.measure(widthMeasureSpec, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
int h = child.getMeasuredHeight();
if (h > height) height = h;
}
} else {
height = heightMeasureSpec;
}
heightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY);
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
}
But when call swipe refresh and adapter update, all views in carousel disappear. I think that the problem is not called onMeasure after adapter.notifyDataSetChanged(). How I can fix it?

Multi selection in recyclerview is not working

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

Dynamically Setting a Fixed Height for a Staggered Grid View

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

Blurring the background of a textview - IllegalArgumentException width and height must be > 0

I have 2 layout files, one for the listview and one for customizing the row layout inside the listview. Then I have the Activity class of the listview, a class with Utils that blurs the background of a view and the custom ListAdapter class. I am trying to blur a TextView name of the row with the method blur() from Utils.java inside the listviewActivity, but I get the following exception:
java.lang.IllegalArgumentException: width and height must be > 0
listview.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/background2"
android:id="#+id/listviewactivity">
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="#+id/listview"
android:choiceMode="singleChoice"
android:divider="#ffc8cabe"
android:dividerHeight="4px"/>/>
</RelativeLayout>
row.xml
<?xml version="1.0" encoding="UTF-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:minHeight="140dp"
android:maxHeight="140dp"
android:padding="5dp">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:textStyle="bold"
android:textSize="20sp"
android:textColor="#fff4f4f4"
/>
<TextView
android:id="#+id/start"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="14sp"
android:textColor="#fff4f4f4"
/>
</LinearLayout>
ListViewActivity.java
public class ListViewActivity extends ActionBarActivity {
private List<ListModel> list = new ArrayList<ListModel>();
private ListView listView;
private CustomListAdapter adapter;
public static Drawable resizedDrawable;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.challenges_view);
Intent intent = getIntent();
ListModel listmodel = new ListModel();
listmodel.setChallengeName("Test text");
listmodel.setChallengeStart("Start");
list.add(listmodel);
resizedDrawable = Utils.getResizedDrawable(this, R.drawable.image, 362, 161);
LayoutInflater factory = getLayoutInflater();
View textEntryView = factory.inflate(R.layout.row, null);
TextView bluredname = (TextView) textEntryView.findViewById(R.id.name);
Utils.blur(bluredname);
listView = (ListView) findViewById(R.id.listView);
adapter = new CustomListAdapter(this, list);
listView.setAdapter(adapter);
}
}
This is the getView in the custom ListAdapter class:
public class CustomListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<ListModel> items;
public static TextView name;
public CustomListAdapter(Activity activity, List<ListModel> challengeItems) {
this.activity = activity;
this.items = items;
}
#Override
public int getCount() {
return items.size();
}
#Override
public Object getItem(int location) {
return items.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.row, null);
name = (TextView) convertView.findViewById(R.id.name);
TextView startdate = (TextView) convertView.findViewById(R.id.start);
convertView.setBackground(ListViewActivity.resizedDrawable);
ListModel m = items.get(position);
name.setText(m.getName());
startdate.setText(m.getStart());
return convertView;
}
}
And the error occurs in my Utils class in the method createBitmap():
public class Utils {
private static final float BITMAP_SCALE = 0.4f;
private static final float BLUR_RADIUS = 7.5f;
public static Drawable getResizedDrawable(Context context,
int drawableResourceId, int imgWidth, int imgHeight) {
Drawable drawableResource = ContextCompat.getDrawable(context, drawableResourceId);
Bitmap bitmap = ((BitmapDrawable) drawableResource).getBitmap();
Drawable drawableResizedBitmap = new BitmapDrawable(
context.getResources(), Bitmap.createScaledBitmap(bitmap,
imgWidth, imgHeight, true));
return drawableResizedBitmap;
}
public static Bitmap blur(View v) {
return blur(v.getContext(), getScreenshot(v));
}
public static Bitmap blur(Context ctx, Bitmap image) {
int width = Math.round(image.getWidth() * BITMAP_SCALE);
int height = Math.round(image.getHeight() * BITMAP_SCALE);
Bitmap inputBitmap = Bitmap.createScaledBitmap(image, width, height, false);
Bitmap outputBitmap = Bitmap.createBitmap(inputBitmap);
RenderScript rs = RenderScript.create(ctx);
ScriptIntrinsicBlur theIntrinsic = ScriptIntrinsicBlur.create(rs, Element.U8_4(rs));
Allocation tmpIn = Allocation.createFromBitmap(rs, inputBitmap);
Allocation tmpOut = Allocation.createFromBitmap(rs, outputBitmap);
theIntrinsic.setRadius(BLUR_RADIUS);
theIntrinsic.setInput(tmpIn);
theIntrinsic.forEach(tmpOut);
tmpOut.copyTo(outputBitmap);
return outputBitmap;
}
private static Bitmap getScreenshot(View v) {
Bitmap b = Bitmap.createBitmap(v.getWidth(), v.getHeight(), Bitmap.Config.ARGB_8888);
Canvas c = new Canvas(b);
v.draw(c);
return b;
}
}
bluredname.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
#Override
public boolean onPreDraw() {
bluredname.getViewTreeObserver().removeOnPreDrawListener(this);
Utils.blur(bluredname);
return false;
}
});

Categories