I just started app developing recently and stumbled upon a problem that I basically can't figure out : https://rubensousa.github.io/2016/08/viewpagercards
He instructed that on CardPagerAdapter.java in instantiateItem, I need to set the data according to the position. But how do I do it?
I want the first card to have a title of "FIRST CARD" while the second "SECOND CARD" and so on.. hope someone could help.
CardPagerAdapter.java
import android.support.v4.view.PagerAdapter;
import android.support.v7.widget.CardView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.List;
public class CardPagerAdapter extends PagerAdapter implements CardAdapter {
private List<CardView> mViews;
private List<CardItem> mData;
private float mBaseElevation;
public CardPagerAdapter() {
mData = new ArrayList<>();
mViews = new ArrayList<>();
}
public void addCardItem(CardItem item) {
mViews.add(null);
mData.add(item);
}
public float getBaseElevation() {
return mBaseElevation;
}
#Override
public CardView getCardViewAt(int position) {
return mViews.get(position);
}
#Override
public int getCount() {
return mData.size();
}
#Override
public boolean isViewFromObject(View view, Object object) {
return view == object;
}
#Override
public Object instantiateItem(ViewGroup container, int position) {
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.fragment_adapter, container, false);
container.addView(view);
bind(mData.get(position), view);
CardView cardView = (CardView) view.findViewById(R.id.cardView);
if (mBaseElevation == 0) {
mBaseElevation = cardView.getCardElevation();
}
cardView.setMaxCardElevation(mBaseElevation * MAX_ELEVATION_FACTOR);
mViews.set(position, cardView);
return view;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
container.removeView((View) object);
mViews.set(position, null);
}
private void bind(CardItem item, View view) {
TextView title = (TextView) view.findViewById(R.id.title);
TextView description = (TextView) view.findViewById(R.id.description);
Button button = (Button) view.findViewById(R.id.button);
title.setText(item.getTitle());
description.setText(item.getText());
button.setText(item.getButton());
}
}
Related
I copied code for a recycler View from a Youtube tutorial but it won't work out for me. The new View.OnClickListener() is greyed out, with Android Studio suggesting to replace out with lambda. This is the only difference from my code to the one from the tutorial... The App runs through, but doesn't show the Layout, as I get the error message E/RecyclerView: No adapter attached; skipping layout.
what can I do to fix this?
This is the Adapter class:
package com.example.yourfoodweek;
import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.cardview.widget.CardView;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.Glide;
import java.util.ArrayList;
public class MealsRecViewAdapter extends RecyclerView.Adapter<MealsRecViewAdapter.ViewHolder>{
private static final String TAG = "MealsRecViewAdapter";
private ArrayList <Food> meals = new ArrayList<>();
private Context mContext;
public MealsRecViewAdapter(Context mContext) {
this.mContext = mContext;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_meals_list, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: Called");
holder.txtName.setText(meals.get(position).getName());
Glide.with(mContext)
.asBitmap()
.load(meals.get(position).getImageUrl())
.into(holder.imgFood);
holder.parent.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick (View v){
Toast.makeText(mContext, meals.get(position).getName() + "Selected", Toast.LENGTH_SHORT).show();
}
});
}
#Override
public int getItemCount() {
return meals.size();
}
public void setMeals(ArrayList<Food> meals) {
this.meals = meals;
notifyDataSetChanged();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private CardView parent;
private ImageView imgFood;
private TextView txtName;
public ViewHolder(#NonNull View itemView){
super(itemView);
parent = itemView.findViewById(R.id.parent);
txtName = itemView.findViewById(R.id.txtMealName);
imgFood = itemView.findViewById(R.id.imgFood);
}
}
}
both problems are totally different. first one was suggestion means if you don't want to apply you can skip it. but i will not suggest to do that.
for example:
(without Lambda)
myButton.setOnClickListener(new View.OnClickListerner(){
#Override
void onClick(View v) {
// do some stuff related to action
}
});
(with Lambda)
myButton.setOnClickListener(v -> {
// do some stuff related to action
})
for other question
no layout manager attached:
if your RecyclerView doesn't have any LayoutManager attached to it then it will skip cause it will not know how to arrange/show items.
Some LayoutManagers:
LinearLayoutManager
GridLayoutManager
StaggeredGridLayoutManager
if you want to create your own LayoutManager you can do it by just extending class LayoutManager
how to use it:
....
LinearLayoutManager layoutManager = new LinearLayoutManager();
layoutManager.setOrientation = LinearLayoutManager.HORIZONTAL
myRecyclerViewObj.setLayoutManager(layoutManager);
....
no adapter attached
similar to no layout manager this will be shown when no adapter attached to recycler view for this you have to use setAdapter method to set your adapater
for example:
....
MealsRecViewAdapter adapter = new MealsRecViewAdapter(this);
myRecyclerViewObj.setAdapter(adapter);
....
Thank you in advance and dont be very hard with me, it is my first question.
I was trying to add a new item to my recyclerView through the adapter by declaring a method in my adapter called addItem(String newItem)
Then I tried to call this method when the floating button is clikced and the problem is that the method does not even appear when i hit cntrl+space and if i write it down it gets on red.
I have already tried to rebuild the project and nothing changes.
¿Any ideas about how to solve it?
MainActivity class
package com.example.sakur.recyclerviewapp;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.design.widget.FloatingActionButton;
import android.support.design.widget.Snackbar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.DefaultItemAnimator;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
public class MainActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private FloatingActionButton mFloatingActionButton;
private List<String> recyclerItems = Collections.emptyList();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerItems = new ArrayList<>();
recyclerItems.add("First item");
mRecyclerView = (RecyclerView) findViewById(R.id.my_recycler_view);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter(recyclerItems);
mRecyclerView.setAdapter(mAdapter);
mRecyclerView.setItemAnimator(new DefaultItemAnimator());
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.floating_action_button);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
String itemNuevo = "New Card";
mAdapter.addItem(itemNuevo);
Snackbar.make(view, "Item added successfully", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
and the MyAdapter class
package com.example.sakur.recyclerviewapp;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.Collections;
import java.util.List;
/**
* Created by Sakur on 19/12/2015.
*/
public class MyAdapter extends RecyclerView.Adapter<MyAdapter.ViewHolder> {
private List<String> mDataset= Collections.emptyList();
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
// Provide a suitable constructor (depends on the kind of dataset)
public MyAdapter(List<String> myDataset) {
mDataset = myDataset;
}
public void addItem(String newItem){
mDataset.add(newItem);
notifyDataSetChanged();
}
// Create new views (invoked by the layout manager)
#Override
public MyAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recycler_card, parent, false);
// set the view's size, margins, paddings and layout parameters
//...
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
// - get element from your dataset at this position
// - replace the contents of the view with that element
holder.mTextView.setText(mDataset.get(position));
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
return mDataset.size();
}
public static class ViewHolder extends RecyclerView.ViewHolder {
// each data item is just a string in this case
public TextView mTextView;
public ImageView mImageView;
public ViewHolder(View v) {
super(v);
mTextView = (TextView) v.findViewById(R.id.text_card);
}
}
}
addItem(String) is not a method of RecyclerView.Adapter, but of your MyAdapter subclass. Obviously, RecyclerView.Adapter has no knowledge of the existence neither of your MyAdapter nor of your addItem(String).
you can either change
private RecyclerView.Adapter mAdapter;
into
private MyAdapter mAdapter;
or cast mAdapter. E.g.
if (mAdater instanceof MyAdapter) {
((MyAdapter) mAdapter).addItem(...);
}
I would like to implement a new intent when my card from CardView is clicked. I have already implemented for one of the cards. Is there any other way in which the adapter is able to identify the position and bring to a new activity for each card? Like linking the each card to their individual activity with a template layout. (The new activity for each card will be of the same layout, just different texts and images).
I have added an ImageButton on my cards. However, when I click on the ImageButton, it does not bring me to the new activity. Clicking on the card edges/portion and not the image itself would work. Is there something I missed out on my code? I can't seem to get it.
Here are my codes:
MuaActivity.java
package android.com.example.weddingappfinale;
import android.content.Intent;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.inputmethod.EditorInfo;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.SearchView;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import Adapters.MuaAdapter;
import CustomerActivities.ShimaMatinActivity;
public class MuaActivity extends AppCompatActivity {
private RecyclerView mRecyclerView;
private MuaAdapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mua_list);
getSupportActionBar().setTitle("Make Up Artists");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
final ArrayList<MuaView> muaView = new ArrayList<>();
muaView.add(new MuaView(R.drawable.mua_image, "Shima Matin Bridal Services"));
muaView.add(new MuaView(R.drawable.mua_image, "Aake Up Artist Pte Ltd"));
muaView.add(new MuaView(R.drawable.mua_image, "Lake Up Artist 3Pte Ltd"));
muaView.add(new MuaView(R.drawable.mua_image, "f Up Artist Pte Ltd"));
// ArrayList
mRecyclerView = findViewById(R.id.recycler_view_list);
mRecyclerView.setHasFixedSize(true);
mLayoutManager = new LinearLayoutManager(this);
mAdapter = new MuaAdapter(muaView);
mRecyclerView.setLayoutManager(mLayoutManager);
mRecyclerView.setAdapter(mAdapter);
mAdapter.setOnItemClickListener(new MuaAdapter.OnItemClickListener() {
#Override
public void onItemClick(int position) {
Intent i = new Intent (MuaActivity.this, ShimaMatinActivity.class);
startActivity(i);
finish();
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.search, menu);
MenuItem searchItem = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) searchItem.getActionView();
searchView.setImeOptions(EditorInfo.IME_ACTION_DONE);
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String query) {
return false;
}
#Override
public boolean onQueryTextChange(String newText) {
mAdapter.getFilter().filter(newText);
return false;
}
});
return true;
}
}
MuaAdapter.java
package Adapters;
import android.com.example.weddingappfinale.MuaView;
import android.com.example.weddingappfinale.R;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageButton;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class MuaAdapter extends RecyclerView.Adapter<MuaAdapter.MuaViewHolder> implements Filterable {
private ArrayList<MuaView> mMuaView;
private ArrayList<MuaView> mMuaViewFull;
private OnItemClickListener mListener;
public interface OnItemClickListener {
void onItemClick(int position);
}
public void setOnItemClickListener(OnItemClickListener listener) {
mListener = listener;
}
public static class MuaViewHolder extends RecyclerView.ViewHolder {
public ImageButton mImageButton;
public TextView mTextView1;
public MuaViewHolder(#NonNull View itemView, final OnItemClickListener listener) {
super(itemView);
mImageButton = itemView.findViewById(R.id.mua_imageButton);
mTextView1 = itemView.findViewById(R.id.mua_title);
itemView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if (listener != null) {
int position = getAdapterPosition();
if (position != RecyclerView.NO_POSITION) {
listener.onItemClick(position);
}
}
}
});
}
}
public MuaAdapter(ArrayList<MuaView> muaView) {
this.mMuaView = muaView;
mMuaViewFull = new ArrayList<>(muaView);
}
#NonNull
#Override
public MuaViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.mua_view, parent, false);
MuaViewHolder mvh = new MuaViewHolder(v, mListener);
return mvh;
}
#Override
public void onBindViewHolder(#NonNull MuaViewHolder holder, int position) {
MuaView currentView = mMuaView.get(position);
holder.mImageButton.setImageResource(currentView.getImageResource());
holder.mTextView1.setText(currentView.getText1());
}
#Override
public int getItemCount() {
return mMuaView.size();
}
public Filter getFilter() {
return MuaFilter;
}
private Filter MuaFilter = new Filter() {
#Override
protected FilterResults performFiltering(CharSequence constraint) {
List<MuaView> filteredList = new ArrayList<>();
if (constraint == null || constraint.length() == 0) {
filteredList.addAll(mMuaViewFull);
} else {
String filterPattern = constraint.toString().toLowerCase().trim();
for (MuaView item : mMuaViewFull) {
if (item.getText1().toLowerCase().contains(filterPattern)) {
filteredList.add(item);
}
}
}
FilterResults results = new FilterResults();
results.values = filteredList;
return results;
}
#Override
protected void publishResults(CharSequence constraint, FilterResults results) {
mMuaView.clear();
mMuaView.addAll((ArrayList) results.values);
notifyDataSetChanged();
}
};
}
Answer for first question:
You could pass the position of the item to the new activity with intent.putExtra().
In the new activity you can read out the number with intent.getExtra() and setup your layout content as you want depending on the number you got.
This way you only have one Activity instead of many.
Activity 1
Intent intent = new Intent(this, Shima.class);
intent.putExtra("position_value", position);
startActivity(intent);
Activity 2
Intent intent = getIntent();
int position = intent.getIntExtra("position_value", 0); // 0 is the default value
// set a layout based on position with switch case or if...
switch (position){
case 1:
setContentView(R.layout.activity_card_one);
break;
case 2:
setContentView(R.layout.activity_card_two);
break;
....
Second question:
See here.
Basicaly the same way like
itemView.setOnClickListener(new View.OnClickListener() {...
You can set a image depending on what item has been clicked using something like this
private Integer images[] = {R.drawable.pic1, R.drawable.pic2, R.drawable.pic3}
and
imageView.setImageResource(images[position]);
(maybe position -1, not sure if first item in recyclerView is 1 or 0)
I have pasted the whole class below from android studio. Im trying to create a gallery using image view and GridView.
package com.example.sc.loginappexercise;
import android.content.Context;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
/**
* Created by sc on 16/03/2017.
*/
public class ImageAdapter extends BaseAdapter {
public Context context;
public int[] images = {
R.drawable.gallery1, R.drawable.gallery2,
R.drawable.gallery3, R.drawable.gallery4,
R.drawable.gallery5, R.drawable.gallery6,
R.drawable.gallery7, R.drawable.gallery8,
R.drawable.gallery9, R.drawable.gallery10,
};
public ImageAdapter(Context c){
context = c;
}
#Override
public int getCount() {
return images.length;
}
#Override
public Object getItem(int position) {
return images [position];
}
#Override
public long getItemId(int position) {
return 0;
}
}
**Below where it says setLayoutParams - it stays red and throws an error. cannot be referenced from a static context? **
#Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView = new ImageView(context);
imageView.setImageResource(images[position]);
imageView.setScaleType(ImageView.ScaleType.CENTER_CROP);
ImageView.setLayoutParams(new GridView.LayoutParams(240, 240));
return imageView;
}
}
ImageView.setLayoutParams(new GridView.LayoutParams(240, 240)); => imageView.setLayoutParams(new GridView.LayoutParams(240, 240));
I => i
That's all!
I'm making an app that requires the use of a Gallery. My problem is, the Gallery is really choppy. My code is pretty much similar to the sample code that android provides, but rather than just having the ImageAdapter return an ImageView, I have it return a LinearLayout, because I need text underneath the image. Any suggestions?
Here's my code:
package org.example.gallery;
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.os.Bundle;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.BaseAdapter;
import android.widget.Gallery;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Toast;
public class GalleryTestActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Gallery gallery = (Gallery) this.findViewById(R.id.gallery);
gallery.setAdapter(new ItemAdapter(this));
gallery.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View v,
int position, long id) {
Toast.makeText(GalleryTestActivity.this, "" + position,
Toast.LENGTH_SHORT).show();
}
});
}
public class ItemAdapter extends BaseAdapter {
private Context mContext;
private final Integer[] mImageIds = { R.drawable.sample_1,
R.drawable.sample_2, R.drawable.sample_3, R.drawable.sample_4,
R.drawable.sample_5, R.drawable.sample_6, R.drawable.sample_7,
R.drawable.sample_8 };
private final String[] mStringIds = { "1-pc. Chicken with Rice",
"2-pc. Chicken with Rice", "Tower Burger", "Bucket", "Barrel",
"Chicken Fillet", "Chicken burger", "Another Chicken Burger" };
public ItemAdapter(Context c) {
this.mContext = c;
}
public int getCount() {
return mImageIds.length;
}
public Object getItem(int position) {
return position;
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
LinearLayout l = new LinearLayout(this.mContext);
l.setOrientation(LinearLayout.VERTICAL);
ImageView iv = new ImageView(this.mContext);
iv.setImageResource(mImageIds[position]);
iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
TextView tv = new TextView(this.mContext);
tv.setText(mStringIds[position]);
tv.setTextSize(20);
tv.setTextColor(Color.RED);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
l.addView(iv);
l.addView(tv);
return l;
}
}
}
use ViewHolder(so u will not inflating/creating view in every getView call(views are recycling)) pattern like in this example:
http://developer.android.com/resources/samples/ApiDemos/src/com/example/android/apis/view/List14.html
EDIT:
static class ViewHolder {
TextView tv;
ImageView iv;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder = null;
if(convertView == null){
LinearLayout l = new LinearLayout(this.mContext);
l.setOrientation(LinearLayout.VERTICAL);
ImageView iv = new ImageView(this.mContext);
iv.setScaleType(ImageView.ScaleType.FIT_CENTER);
TextView tv = new TextView(this.mContext);
tv.setTextSize(20);
tv.setTextColor(Color.RED);
tv.setGravity(Gravity.CENTER_HORIZONTAL);
l.addView(iv);
l.addView(tv);
convertView = l;
holder = new ViewHolder();
holder.tv = tv;
holder.iv = iv;
} else {
holder = (ViewHolder)convertView.getTag();
}
holder.tv.setText(mStringIds[position]);
holder.iv.setImageResource(mImageIds[position]);
return convertView;
}