I'm trying to show a list of data with RecyclerView and add an AdMob after 3 data showed. I have followed this stackoverflow Q&A because it's almost the same as my code but I'm using Retrofit.
But my result is just showing test AdMob rows only... It's not show my data's name String.
This is my MainActivity:
public class Nilai extends AppCompatActivity implements NilaiView {
RecyclerView recyclerView;
SwipeRefreshLayout swipeRefresh;
NilaiPresenter presenter;
RecyclerViewAdopter adapter;
List<modelNilai> score;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nilai);
MobileAds.initialize(this, "ID_APP");
recyclerView = findViewById(R.id.recyclerView);
swipeRefresh = findViewById(R.id.swipe_refresh);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
presenter = new NilaiPresenter(this);
presenter.getNilai();
swipeRefresh.setOnRefreshListener(
() -> presenter.getNilai()
);
}
#Override
public void showLoading() {
swipeRefresh.setRefreshing(true);
}
#Override
public void hideLoading() {
swipeRefresh.setRefreshing(false);
}
#Override
public void onGetNilai(List<modelNilai> scores) {
adapter = new RecyclerViewAdopter(Nilai.this, scores);
adapter.notifyDataSetChanged();
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.setAdapter(adapter);
score = scores;
for (int i = 0; i <= scores.size(); i += 3)
{
modelNilai myString2 = new modelNilai();
myString.setId(i);
scores.add(i,myString);
}
}
}
My Adapter:
public class RecyclerViewAdopter extends RecyclerView.Adapter<RecyclerView.ViewHolder>{
private Context mContext;
private List<modelNilai> mList;
public RecyclerViewAdopter(Context mContext, List<modelNilai> mList) {
this.mList = mList;
this.mContext = mContext;
}
public static class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name;
public MyViewHolder(View view) {
super(view);
name = view.findViewById(R.id.namaSoal);
}
}
public static class ViewHolderAdMob extends RecyclerView.ViewHolder {
public AdView mAdView;
public ViewHolderAdMob(View view) {
super(view);
mAdView = view.findViewById(R.id.adView);
AdRequest adRequest = new AdRequest.Builder()
.addTestDevice("CEE26DC1A5BBF0E603B08A5460483046")
.build();
mAdView.loadAd(adRequest);
}
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
switch(viewType){
case 1:
{
View v = inflater.inflate(R.layout.list_nilai_ad, parent, false);
viewHolder = new MyViewHolder(v);
break;
}
case 2:
default:
{
View v = inflater.inflate(R.layout.banner_ad_row, parent, false);
viewHolder = new ViewHolderAdMob(v);
break;
}
}
return viewHolder;
}
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
modelNilai model = mList.get(holder.getAdapterPosition());
switch(holder.getItemViewType()){
case 1:{
MyViewHolder viewHolder = (MyViewHolder) holder;
viewHolder.name.setText(model.getName());
break;
}
case 2:{
break;
}
}
}
#Override
public int getItemViewType(int position)
{
return mList.get(position).getId();
}
#Override
public int getItemCount() {
return mList.size();
}
}
My presenter:
public class NilaiPresenter {
private NilaiView view;
public NilaiPresenter(NilaiView view) {
this.view = view;
}
void getNilai() {
view.showLoading();
ApiInterface apiInterface = ApiClient.getApiClient().create(ApiInterface.class);
Call<List<modelNilai>> call = apiInterface.getNilai();
call.enqueue(new Callback<List<modelNilai>>() {
#Override
public void onResponse(#NonNull Call<List<modelNilai>> call, #NonNull Response<List<modelNilai>> response) {
view.hideLoading();
if (response.isSuccessful() && response.body() != null) {
view.onGetNilai(response.body());
}
}
#Override
public void onFailure(#NonNull Call<List<modelNilai>> call, #NonNull Throwable t) {
view.hideLoading();
view.onRequestError(t.getLocalizedMessage());
}
});
}
}
My model class:
public class modelNilai {
#Expose
#SerializedName("id") private int id_nilai;
#Expose
#SerializedName("name") private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
And My view interface:
public interface NilaiView {
void showLoading();
void hideLoading();
void onGetNilai(List<modelNilai> scores);
}
Result on phone:
It should show something like 3 rows of name and 1 row of Admob, and repeat that again per 4 rows.
Parhaps, the getItemViewType() method should be like this:
#Override
public int getItemViewType(int position)
{
return (position + 1) % 4 == 0 ? 2 : 1;
}
You also have to modify the getItemCount() method. Because it should return the count of all of your mList rows and PLUS of your Admob rows.
#Override
public int getItemCount() {
return mList.size() + mList.size / 4;
}
In addition to that the onBindViewHolder method is affected:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, final int position) {
modelNilai model = mList.get(holder.getAdapterPosition() - holder.getAdapterPosition() / 4);
if ((position + 1) % 4 != 0) {
MyViewHolder viewHolder = (MyViewHolder) holder;
viewHolder.name.setText(model.getName());
}
}
Related
I try to implement Native Ads inside RecyclerView. The ad should be placed every 3 items in recycler view. I use a native ads template. Ads are loaded but they have overlapped items in RecyclerView. I try couple of solution but they didn't work. Please help me, thank you in advance.
Below is the code for Adapter class:
public class MyAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
Context c;
ArrayList<Model> models;
private static final int CONTENT_TYPE = 1;
private static final int AD_TYPE = 0;
public MyAdapter(Context c, ArrayList<Model> models) {
this.c = c;
this.models = models;
}
#Override
public int getItemViewType(int position) {
if (position % 3 == 0) {
return AD_TYPE;
} else {
return CONTENT_TYPE;
}
}
class adViewHolder extends RecyclerView.ViewHolder {
TemplateView adTemplate;
public adViewHolder(#NonNull View itemView) {
super(itemView);
adTemplate = itemView.findViewById(R.id.native_ad);
}
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
if (viewType == AD_TYPE) {
adViewHolder myadViewHolder = new adViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_ads, null, false));
return myadViewHolder;
} else {
MyHolder myHolder = new MyHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.single_list_item, null, false));
return myHolder;
}
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == CONTENT_TYPE) {
((MyHolder) holder).mTitle.setText(models.get(position).getTitle());
((MyHolder) holder).mDescription.setText(models.get(position).getDesc());
((MyHolder) holder).mImageView.setImageResource(models.get(position).getImage());
} else if (getItemViewType(position) == AD_TYPE) {
final AdLoader adLoader = new AdLoader.Builder(c, "ca-app-pub-3940256099942544/2247696110")
.forUnifiedNativeAd(new UnifiedNativeAd.OnUnifiedNativeAdLoadedListener() {
#Override
public void onUnifiedNativeAdLoaded(UnifiedNativeAd unifiedNativeAd) {
NativeTemplateStyle styles = new NativeTemplateStyle.Builder().build();
TemplateView template = ((adViewHolder) holder).adTemplate;
template.setStyles(styles);
template.setNativeAd(unifiedNativeAd);
}
})
.withAdListener(new AdListener() {
#Override
public void onAdFailedToLoad(int errorCode) {
}
})
.withNativeAdOptions(new NativeAdOptions.Builder()
.build())
.build();
adLoader.loadAd(new AdRequest.Builder().build());
}
}
#Override
public int getItemCount() {
return models.size();
}
I am working with RecyclerView which support pagination with Firestore database.I want to showing into 10 items recylcerview an Ads,i try serveral times without succes,help me please to find the right code.
Here is my code of pagination.
//Initialize FirebasePagingOptions
DatabasePagingOptions<Pubs> options = new DatabasePagingOptions.Builder<Pubs>()
.setLifecycleOwner(this)
.setQuery(mDatabase, config, Pubs.class)
.build();
//Initialize Adapter
mAdapter = new FirebaseRecyclerPagingAdapter<Pubs, PubsViewHolder>(options) {
#Override
public int getItemViewType(int position)
{
if (position % 5 == 0)
return AD_TYPE;
return CONTENT_TYPE;
}
#NonNull
#Override
public PubsViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
return new PubsViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_pub, parent, false));
}
#Override
protected void onBindViewHolder(#NonNull PubsViewHolder holder,
int position,
#NonNull Pubs model) {
holder.setItem(model);
}
this is a full example to how to use multi type recyclerview with custom adapter with Model and Ads Type
and for paging issue you have to handle it outside adapter class it can be more easier.
public class SiteAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<SiteModel> dataList;
private Context context;
private static final int AD_TYPE = 1;
private static final int CONTENT_TYPE = 2;
public SiteAdapter(Context context) {
this.context = context;
dataList = new ArrayList<>();
}
#Override
public int getItemViewType(int position) {
if (dataList.get(position) == null)
return AD_TYPE;
return CONTENT_TYPE;
}
public List<SiteModel> getDataList() {
return dataList;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = null;
RecyclerView.ViewHolder vh = null;
if (viewType == AD_TYPE) {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.ad_view_item, parent, false);
vh = new AdViewHolder(v);
} else {
v = LayoutInflater.from(parent.getContext()).inflate(R.layout.site_list_item, parent, false);
vh = new SitesViewHolder(v);
}
return vh;
}
#Override
public void onBindViewHolder(#NonNull final RecyclerView.ViewHolder holder, int position) {
holder.setIsRecyclable(false);
if (getItemViewType(position) == CONTENT_TYPE) {
} else {
AdViewHolder adViewHolder = (AdViewHolder) holder;
AdRequest request = new AdRequest.Builder().build();
adViewHolder.adView.loadAd(request);
}
}
#Override
public int getItemCount() {
return dataList.size();
}
public void add(SiteModel siteModel, int i) {
dataList.add(siteModel);
notifyItemInserted(i);
}
public void add(List<SiteModel> moreData) {
dataList.addAll(moreData);
notifyDataSetChanged();
}
public void updateItem(String desc, boolean isFavourites, int adapterPosition) {
dataList.get(adapterPosition).setDesc(desc);
notifyItemChanged(adapterPosition);
}
public class SitesViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public SitesViewHolder(View itemView) {
super(itemView);
}
#Override
public void onClick(View v) {
if (clickListener != null) {
switch (v.getId()) {
}
}
}
private class AdViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
AdView adView;
public AdViewHolder(View itemView) {
super(itemView);
adView = itemView.findViewById(R.id.adView);
}
#Override
public void onClick(View v) {
}
}
}
I've got a RecylerView that is displaying a list of data. I need to add dividers or spacers that I need to add two Dividers or spacers too that I can add text to as shown in the image below(with the text DEFAULT or OTHER).
*NOTE Headers are in the image below with the text "DEFAULT" and another that says "OTHER".
The CC's shown are drag and drop items but i don't want the "spaces or headers" marked as default and other to be moved.
I've started adding the divider as shown in the code below but I cannot figure out how to add text.
#Override
public void onViewCreated(#NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
ButterKnife.bind(this, view);
LinearLayoutManager mAdapterLayoutManager = new LinearLayoutManager(context);
recyclerView.setLayoutManager(mAdapterLayoutManager);
billingMethodRecyclerViewAdapter = new BillingMethodRecyclerViewAdapter(context, billingMethods, paymentService, ListPaymentMethods.this );
billingMethodRecyclerViewAdapter.setMasterpassService(masterpassService);
billingMethodRecyclerViewAdapter.setChoosePaymentMode(choosePaymentMode);
DividerItemDecoration itemDecor = new DividerItemDecoration(context, mAdapterLayoutManager.getOrientation());
recyclerView.addItemDecoration(itemDecor);
recyclerView.setAdapter(billingMethodRecyclerViewAdapter);
billingMethodRecyclerViewAdapter.clear();
if (!choosePaymentMode) {
setupSwipeListener(billingMethodRecyclerViewAdapter);
}
if (!BuildConfig.SHOW_AVAILABILITY_INRIX) {
parkmobileProAd.setVisibility(View.GONE);
}
if (getArguments() != null) {
isAddPaymentZoneDetails = getArguments().getBoolean(AddPaymentActivity.ADD_PAYMENT_FROM_ZONE_DETAIL);
}
}
and the xml for the recylcerview
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="wrap_content"/>
EDIT
Adapter:
public class BillingMethodRecyclerViewAdapter extends RecyclerView.Adapter<BillingMethodHolder> {
private static final int PENDING_REMOVAL_TIMEOUT = 3000; // in milliseconds
private ArrayList<BillingMethod> billingMethods;
private Handler handler = new Handler(); // handler for running delayed runnables
private HashMap<BillingMethod, Runnable> pendingRunnables = new HashMap<>(); // map of items to pending runnables, so we can cancel a removal if need be
private BillingMethodHolder.BillingMethodListener billingMethodListener;
private PaymentService paymentService;
private MasterpassService masterpassService;
private boolean choosePaymentMode = false;
private Context mContext;
private int maxPaymentMethods = 6;
public BillingMethodRecyclerViewAdapter(Context context, ArrayList<BillingMethod> objects, PaymentService paymentService, BillingMethodHolder.BillingMethodListener billingMethodListener) {
this.billingMethods = objects;
this.billingMethodListener = billingMethodListener;
this.mContext = context.getApplicationContext();
this.paymentService = paymentService;
}
public int getMaxPaymentMethods() {
return maxPaymentMethods;
}
public void setMaxPaymentMethods(int maxPaymentMethods) {
this.maxPaymentMethods = maxPaymentMethods;
}
public void setMasterpassService(MasterpassService masterpassService) {
this.masterpassService = masterpassService;
}
public boolean onItemMove(int fromPosition, int toPosition) {
if (fromPosition < toPosition) {
for (int i = fromPosition; i < toPosition; i++) {
Collections.swap(billingMethods, i, i + 1);
}
} else {
for (int i = fromPosition; i > toPosition; i--) {
Collections.swap(billingMethods, i, i - 1);
}
}
notifyItemMoved(fromPosition, toPosition);
return true;
}
public List<BillingMethod> getBillingMethods() {
return billingMethods;
}
public void setChoosePaymentMode(boolean choosePaymentMode) {
this.choosePaymentMode = choosePaymentMode;
}
#NonNull
#Override
public BillingMethodHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_payment_methods, parent, false);
return new BillingMethodHolder(v);
}
#Override
public void onBindViewHolder(#NonNull BillingMethodHolder holder, final int position) {
holder.bind(getBillingMethods().get(position), billingMethodListener, choosePaymentMode);
}
#Override
public int getItemCount() {
return billingMethods.size();
}
public void pendingRemoval(int position) {
final BillingMethod billingMethod = billingMethods.get(position);
billingMethod.setPendingDeletion(true);
this.notifyItemChanged(position); // redraw row in "undo" state
Runnable pendingRemovalRunnable = () -> {
deleteBillingMethod(position);
};
handler.postDelayed(pendingRemovalRunnable, PENDING_REMOVAL_TIMEOUT);
pendingRunnables.put(billingMethod, pendingRemovalRunnable);
}
public void savePaymentOrder() {
List<BillingMethod> newOrder = new ArrayList<>();
int order = 0;
for (BillingMethod method : billingMethods) {
if (order == 0) {
method.setPreferred(true);
LocalyticsUtil.getInstance(mContext).setPrimaryPaymentMethod(method);
} else {
method.setPreferred(false);
}
method.setSortOrder(order);
newOrder.add(method);
order++;
}
paymentService.setPaymentMethodsOrder(newOrder, new PaymentService.GenericListener() {
#Override
public void onSuccess() {
Log.d("TAG", "Saved");
}
#Override
public void onError(String errorMessage) {
Log.d("TAG", "Saved");
}
});
}
private void deleteBillingMethod(int position) {
BillingMethod method = billingMethods.get(position);
if (method.getBillingType() == BillingType.CREDIT_CARD) {
paymentService.deleteCreditCard(method.getCreditCard().getCardStatus(), new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.PREPAID) {
paymentService.deleteWallet(new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.PAYPAL) {
paymentService.deletePaypal(new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.CHASEPAY) {
paymentService.deleteChasepay(new PaymentService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else if (method.getBillingType() == BillingType.MASTERPASSV7) {
masterpassService.deleteMasterpassV7(String.valueOf(method.getBillingMethodId()), new MasterpassService.GenericListener() {
#Override
public void onSuccess() {
billingMethods.remove(position);
notifyItemRemoved(position);
}
#Override
public void onError(String errorMessage) {
}
});
} else {
notifyDataSetChanged();
}
}
public void clear() {
billingMethods.clear();
notifyDataSetChanged();
}
public void stopRemoval(BillingMethod billingMethod) {
Runnable pendingRemovalRunnable = pendingRunnables.get(billingMethod);
pendingRunnables.remove(billingMethod);
if (pendingRemovalRunnable != null) {
handler.removeCallbacks(pendingRemovalRunnable);
}
billingMethod.setPendingDeletion(false);
this.notifyItemChanged(billingMethods.indexOf(billingMethod));
}
}
I took a bit of time but I was able to do it.
This is the output
1) MainActivity.java
public class MainActivity extends AppCompatActivity implements OnStartDragListener{
RecyclerView recyclerView;
private ItemTouchHelper mItemTouchHelper;
private List<Item> itemList = new ArrayList<>();
private RecyclerViewAdapter mAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
mAdapter = new RecyclerViewAdapter(itemList, MainActivity.this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new SeparationDecorator());
recyclerView.setAdapter(mAdapter);
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(mAdapter);
mItemTouchHelper = new ItemTouchHelper(callback);
mItemTouchHelper.attachToRecyclerView(recyclerView);
prepareItemData();
}
private void prepareItemData() {
Item item = new Item("Apple Pay");
itemList.add(item);
item = new Item("1706-XXXX-XXXX-1112");
itemList.add(item);
item = new Item("Google pay");
itemList.add(item);
mAdapter.notifyDataSetChanged();
}
#Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
mItemTouchHelper.startDrag(viewHolder);
}
}
2) OnStartDragListener.java
public interface OnStartDragListener {
void onStartDrag(RecyclerView.ViewHolder viewHolder);
}
3) SimpleItemTouchHelperCallback.java
public class SimpleItemTouchHelperCallback extends ItemTouchHelper.Callback {
private final ItemTouchHelperAdapter mAdapter;
public SimpleItemTouchHelperCallback(ItemTouchHelperAdapter adapter) {
mAdapter = adapter;
}
#Override
public boolean isLongPressDragEnabled() {
return true;
}
#Override
public boolean isItemViewSwipeEnabled() {
return false; // make this true to enable swipe to delete
}
#Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
int dragFlags = ItemTouchHelper.UP | ItemTouchHelper.DOWN;
int swipeFlags = ItemTouchHelper.START | ItemTouchHelper.END;
return makeMovementFlags(dragFlags, swipeFlags);
}
#Override
public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder,
RecyclerView.ViewHolder target) {
mAdapter.onItemMove(viewHolder.getAdapterPosition(), target.getAdapterPosition());
return true;
}
#Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
mAdapter.onItemDismiss(viewHolder.getAdapterPosition());
}
}
4) ItemTouchHelperAdapter.java
public interface ItemTouchHelperAdapter {
void onItemMove(int fromPosition, int toPosition);
void onItemDismiss(int position);
}
5) SeparationDecorator.java
public class SeparationDecorator extends RecyclerView.ItemDecoration {
private int textSize = 50;
private int groupSpacing = 100;
private Paint paint = new Paint();
{
paint.setTextSize(textSize);
}
#Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
for (int i = 0; i < parent.getChildCount(); i++) {
View view = parent.getChildAt(i);
int position = parent.getChildAdapterPosition(view);
if (position == 0) {
c.drawText("DEFAULT", view.getLeft(),
view.getTop() - groupSpacing / 2 + textSize / 3, paint);
} else if(position == 1) {
c.drawText("OTHER", view.getLeft(),
view.getTop() - groupSpacing / 2 + textSize / 3, paint);
}
}
}
#Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
if (parent.getChildAdapterPosition(view) == 0 || parent.getChildAdapterPosition(view) == 1) {
outRect.set(0, groupSpacing, 0, 0);
}
}
}
6) RecyclerViewAdapter.java
public class RecyclerViewAdapter extends RecyclerView.Adapter<RecyclerViewAdapter.MyViewHolder> implements ItemTouchHelperAdapter{
private List<Item> itemList;
private Context context;
#Override
public void onItemMove(int fromPosition, int toPosition) {
Item prev = itemList.remove(fromPosition);
itemList.add(toPosition > fromPosition ? toPosition - 1 : toPosition, prev);
notifyItemMoved(fromPosition, toPosition);
}
#Override
public void onItemDismiss(int position) {
itemList.remove(position);
notifyItemRemoved(position);
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView title;
public MyViewHolder(View view) {
super(view);
title = (TextView) view.findViewById(R.id.title);
}
}
public RecyclerViewAdapter(List<Item> itemList, Context context) {
this.itemList = itemList;
this.context = context;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.view_item, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
Item movie = itemList.get(position);
holder.title.setText(movie.getTitle());
}
#Override
public int getItemCount() {
return itemList.size();
}
}
7) Item.java
public class Item {
private String title;
public Item(String title) {
this.title = title;
}
public void setTitle(String title) {
this.title = title;
}
public String getTitle() {
return title;
}
}
This is it. This was able to solve your problem.
I am not able to explain you the complete code, I will take some time in future definitely and explain it.
public class MyAdapter extends RecyclerView.Adapter<MyViewHolder> {
// other methods..
#Override
public void onBindViewHolder(MyViewHolder holder, int position) {
// initialize your other views
if (your condition){
// display header
}else{
// hide header
}
}
}
You can do some thing like this by adding header view to the item and displaying for the required set and making it gone for un necessary items.
Simply coming towards what you need, just add an empty view with layout_height="1dp" and background="#bcbcbc" like:
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#bcbcbc"/>
it'll get a line drawn for you, use it as a divider, while for making format difference just use a change text size for texts.
Hope it'll help you.
I'm trying to get chatting data from the server and show it. I've created two xml, one for receiver and other for sender. I also tried to implement the logic in adapter class but when I call the API I got a blank screen.
Please help me to figure out the problem.
I want to make the output like this image
Here is my Adapter Class
public class ChatConversationAdapter extends
RecyclerView.Adapter<ChatConversationAdapter.ChatConversationViewHolder> {
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private List<Datum> data;
private Context mContext;
// constructor
public ChatConversationAdapter(List<Datum> data, Context mContext) {
this.data = data;
this.mContext = mContext;
}
#Override
public int getItemCount() {
return data.size();
}
#Override
public int getItemViewType(int position) {
Datum dataItem = data.get(position);
if (dataItem.getOriginatorId()=="8") return VIEW_TYPE_MESSAGE_SENT;
else return VIEW_TYPE_MESSAGE_RECEIVED;
}
#Override
public ChatConversationViewHolder onCreateViewHolder(ViewGroup parent,int viewType){
if(viewType==VIEW_TYPE_MESSAGE_SENT){
return new ChatConversationViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_message_sent,parent,false));
}
else{
return new ChatConversationViewHolder(LayoutInflater.from(mContext).inflate(R.layout.item_message_received,parent,false));
}
}
#Override
public void onBindViewHolder(ChatConversationViewHolder holder, int
position) {
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_SENT:
holder.messageText.setText(data.get(position).getMsg());
holder.timeText.setText(data.get(position).getCreatedAt().getFormatTime());
break;
case VIEW_TYPE_MESSAGE_RECEIVED:
holder.nameText.setText(data.get(position).getOriginator().getFullName());
holder.profileImage.setTag(data.get(position).getOriginator().getAvatar());
holder.messageText.setText(data.get(position).getMsg());
holder.timeText.setText(data.get(position).getCreatedAt().getFormatTime());
}
}
public class ChatConversationViewHolder extends RecyclerView.ViewHolder {
TextView messageText, timeText, nameText;
ImageView profileImage;
public ChatConversationViewHolder(View itemView) {
super(itemView);
messageText = itemView.findViewById(R.id.text_message_body);
timeText = itemView.findViewById(R.id.text_message_time);
nameText = itemView.findViewById(R.id.text_message_name);
profileImage = itemView.findViewById(R.id.image_message_profile);
}
}
}
Here is my main Activity
public class MsgChatActivity extends AppCompatActivity {
MsgHistoryAPIService msgHistoryAPIService;
RecyclerView recyclerView;
ChatConversationAdapter chatAdapter;
List<Datum> data = new ArrayList<>();
String frId_TV, owner_type_TV, subject_TV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_msg_chat);
msgHistoryAPIService =
RestClient.getClient().create(MsgHistoryAPIService.class);
recyclerView = (RecyclerView)
findViewById(R.id.reyclerview_message_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
chatAdapter = new ChatConversationAdapter(new ArrayList<Datum>(),this);
recyclerView.setAdapter(chatAdapter);
frId_TV = "1";
owner_type_TV = "1";
subject_TV = "Message";
chatHistoryData();
}
private void chatHistoryData() {
final MsgHistoryRequest msgHistoryRequest = new MsgHistoryRequest(
frId_TV,
owner_type_TV,
subject_TV
);
Call<MsgHistoryResponse> call =
msgHistoryAPIService.chatHistory(token_key,
msgHistoryRequest);
call.enqueue(new Callback<MsgHistoryResponse>() {
#Override
public void onResponse(Call<MsgHistoryResponse> call, Response<MsgHistoryResponse> response) {
Toast.makeText(MsgChatActivity.this, "" +response.body().getStatus() , Toast.LENGTH_LONG).show();
data.addAll(response.body().getData());
Toast.makeText(MsgChatActivity.this, "" + data.size(), Toast.LENGTH_LONG).show();
chatAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<MsgHistoryResponse> call, Throwable t) {
Toast.makeText(MsgChatActivity.this, "please try again" , Toast.LENGTH_LONG).show();
}
});
}
}
Updated Main activity
public class MsgChatActivity extends AppCompatActivity {
MsgHistoryAPIService msgHistoryAPIService;
RecyclerView recyclerView;
ChatConversationAdapter chatAdapter;
List<Datum> data = new ArrayList<>();
String frId_TV, owner_type_TV, subject_TV;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_msg_chat);
msgHistoryAPIService = RestClient.getClient()
.create(MsgHistoryAPIService.class);
recyclerView = (RecyclerView)
findViewById(R.id.reyclerview_message_list);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
chatAdapter = new ChatConversationAdapter(data, this);
recyclerView.setAdapter(chatAdapter);
frId_TV = "1";
owner_type_TV = "1";
subject_TV = "Message";
chatHistoryData();
}
private void chatHistoryData() {
final MsgHistoryRequest msgHistoryRequest = new
MsgHistoryRequest(
frId_TV,
owner_type_TV,
subject_TV
);
Call<MsgHistoryResponse> call = msgHistoryAPIService
.chatHistory( token_key,
msgHistoryRequest);
call.enqueue(new Callback<MsgHistoryResponse>() {
#Override
public void onResponse
(Call<MsgHistoryResponse> call,
Response<MsgHistoryResponse> response) {
Toast.makeText(MsgChatActivity.this, ""
+response.body().getStatus() , Toast.LENGTH_LONG).show();
data.addAll(response.body().getData());
Toast.makeText(MsgChatActivity.this, ""
+ data.size(), Toast.LENGTH_LONG).show();
chatAdapter.notifyDataSetChanged();
}
#Override
public void onFailure(Call<MsgHistoryResponse> call,
Throwable t) {
Toast.makeText(MsgChatActivity.this,
"please try again" , Toast.LENGTH_LONG).show();
}
});
}
}
Updated Adapter Class
public class ChatConversationAdapter extends
RecyclerView.Adapter<ChatConversationAdapter
.ChatConversationViewHolder> {
private static final int VIEW_TYPE_MESSAGE_SENT = 1;
private static final int VIEW_TYPE_MESSAGE_RECEIVED = 2;
private List<Datum> data;
private Context mContext;
// constructor
public ChatConversationAdapter(List<Datum> data, Context mContext) {
this.data = data;
this.mContext = mContext;
}
// item count
#Override
public int getItemCount() {
return data.size();
}
//Determines the appropriate ViewType according to the sender
of the message
#Override
public int getItemViewType(int position) {
Datum dataItem = data.get(position);
if (dataItem.getOriginatorId()=="8")
return VIEW_TYPE_MESSAGE_SENT;
else
return VIEW_TYPE_MESSAGE_RECEIVED;
}
// Inflates the appropriate layout according to the ViewType.
//create view holder
#Override
public ChatConversationViewHolder onCreateViewHolder
(ViewGroup parent, int viewType) {
View v;
if(viewType==VIEW_TYPE_MESSAGE_SENT){
v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_sent, parent, false);
}
else{
v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_message_received, parent, false);
}
return new ChatConversationViewHolder(v, mContext, data);
}
// bind view holder
#Override
public void onBindViewHolder(ChatConversationViewHolder holder,
int position) {
switch (holder.getItemViewType()) {
case VIEW_TYPE_MESSAGE_SENT:
holder.messageText.setText(data.get(position).getMsg());
holder.timeText.setText(data.get(position)
.getCreatedAt().getFormatTime());
break;
case VIEW_TYPE_MESSAGE_RECEIVED:
holder.nameText.setText(data.get(position)
.getOriginator().getFullName());
holder.profileImage.setTag(data.get(position)
.getOriginator().getAvatar());
holder.messageText.setText(data.get(position).getMsg());
holder.timeText.setText(data.get(position)
.getCreatedAt().getFormatTime());
}
}
// VIEW HOLDER
public class ChatConversationViewHolder extends
RecyclerView.ViewHolder
{
TextView messageText, timeText, nameText;
ImageView profileImage;
public ChatConversationViewHolder(View itemView, Context mContext,
List<Datum> data) {
super(itemView);
messageText = itemView.findViewById(R.id.text_message_body);
timeText = itemView.findViewById(R.id.text_message_time);
nameText = itemView.findViewById(R.id.text_message_name);
profileImage =
itemView.findViewById(R.id.image_message_profile);
}
}
}
try this
#Override
public ChatConversationViewHolder onCreateViewHolder(ViewGroup
parent,int viewType){
if(viewType==VIEW_TYPE_MESSAGE_SENT){
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.item_message_sent, parent, false);
}
else{
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.item_message_received, parent, false);
}
return new ChatConversationViewHolder(v, mContext, data);
}
public void onBindViewHolder(ChatConversationViewHolder holder, int
position){
if(data.get(position).getOriginatorId()=="8")
{
holder.messageText.setText(data.get(position).getMsg());
holder.timeText.setText(data.get(position).getCreatedAt().getFormatTime());
}
else
{
holder.nameText.setText(data.get(position).getOriginator().getFullName());
holder.profileImage.setTag(data.get(position).getOriginator().getAvatar());
holder.messageText.setText(data.get(position).getMsg());
holder.timeText.setText(data.get(position).getCreatedAt().getFormatTime());
}
}
I am implementing sticky header with RecyclerView. I have three sections (i.e 3 sticky headers) and they are working fine.Now I have taken three arraylists inside each section, I have initialized these list in my adapter and I am trying to get data of these lists on basis of header id inside onBindViewHolder. But it is not giving me the full list,just one string from each list (i.e under first section--data on first position of mylist,,,under second section-- data on second position of mylist1 ---under third section-- data on third position of mylist2)
Please Help !!
Code in Context:
StickyTestAdapter
public class StickyTestAdapter extends RecyclerView.Adapter<StickyTestAdapter.ViewHolder> implements
StickyHeaderAdapter<StickyTestAdapter.HeaderHolder> {
private Context mContext;
private ArrayList<String> mylist;
private ArrayList<String> mylist1;
private ArrayList<String> mylist2;
private static int countposition;
private String HEADER_FIRIST="HEADER_FIRIST";
private String HEADER_SECOND="HEADER_SECOND";
private String HEADER_THIRD="HEADER_THIRD";
public StickyTestAdapter(Context context) {
prepareData();
prepareData1();
prepareData2();
this.mContext=context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.item_test, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
long rowType= getHeaderId(position);
Log.e("getHeaderId----",""+rowType);
if (rowType==0){
if(!mylist.equals(""))
{
Log.e("list_data----", "" + mylist.get(position));
viewHolder.item.setText(mylist.get(position));
}
else
{
Log.e("Error--0--", "" + "error");
}
} else if (rowType==1){
if(!mylist1.equals(""))
{
Log.e("list_data1----", "" + mylist1.get(position));
viewHolder.item.setText(mylist1.get(position));
}
else
{
Log.e("Error---1-", "" + "error");
}
} else if (rowType==2){
if(!mylist2.equals(""))
{
Log.e("list_data2----", "" + mylist2.get(position));
viewHolder.item.setText(mylist2.get(position));
}
else
{
Log.e("Error----2", "" + "error");
}
}
}
#Override
public int getItemCount() {
if (getHeaderId(countposition)==0){
Log.e("mylist",""+mylist.size());
return mylist.size();
}else if (getHeaderId(countposition)==1){
Log.e("mylist1",""+mylist1.size());
return mylist1.size();
}else if (getHeaderId(countposition)==2){
Log.e("mylist2",""+mylist2.size());
return mylist2.size();
}
return 0;
}
#Override
public long getHeaderId(int pos) {
return pos;
}
#Override
public HeaderHolder onCreateHeaderViewHolder(ViewGroup parent) {
final View view = LayoutInflater.from(mContext).inflate(R.layout.header_test, parent, false);
return new HeaderHolder(view);
}
#Override
public void onBindHeaderViewHolder(HeaderHolder viewholder, int count) {
countposition=count;
if (getItemViewType(count)==0){
viewholder.headertext.setText(HEADER_FIRIST);
}else if (getItemViewType(count)==1){
viewholder.headertext.setText(HEADER_SECOND);
}else if (getItemViewType(count)==2){
viewholder.headertext.setText(HEADER_THIRD);
}
}
static class ViewHolder extends RecyclerView.ViewHolder {
public TextView item;
public ViewHolder(View itemView) {
super(itemView);
item = (TextView)itemView.findViewById(R.id.text_item);
}
}
static class HeaderHolder extends RecyclerView.ViewHolder {
public TextView headertext;
public HeaderHolder(View itemView) {
super(itemView);
headertext = (TextView)itemView.findViewById(R.id.header_text);
}
}
#Override
public int getItemViewType(int position) {
return position;
}
public void prepareData()
{
mylist=new ArrayList<>();
mylist.add("rajendra");
mylist.add("rani");
mylist.add("rahul");
}
public void prepareData1()
{
mylist1=new ArrayList<>();
mylist1.add("ravi");
mylist1.add("vikram");
mylist1.add("rakesh");
}
public void prepareData2()
{
mylist2=new ArrayList<>();
mylist2.add("apple");
mylist2.add("ashok");
mylist2.add("vikash");
}
}
Question is quite old. But that code looks complicated to read, personally I try to not reinvent what others did quite well by creating libraries.
GitHub is full of source that you can import. Some examples: FlexibleAdapter, FastAdapter, Epoxy and others.
I have build the first one, but you can try the others as well.
With mine, having multiple views and headers with sections is quite easy, I point here the wiki page where I define the section and how to initialize it.
Along with this feature, you have a lot more functionalities that makes your life easier.
I divide arraylist into 3 section based on alphabet like contactlist.
For that i use SectionedRecyclerViewAdapter
MainActivity.java
public class MainActivity extends AppCompactActivity {
private SectionedRecyclerViewAdapter sectionAdapter;
#Override
public View onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
sectionAdapter = new SectionedRecyclerViewAdapter();
for(char alphabet = 'a'; alphabet <= 'z';alphabet++) {
List<String> contacts = getContactsWithLetter(alphabet);
if (contacts.size() > 0) {
sectionAdapter.addSection(new ContactsSection(String.valueOf(alphabet), contacts));
}
}
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
recyclerView.setAdapter(sectionAdapter);
return view;
}
#Override
public void onResume() {
super.onResume();
if (getActivity() instanceof AppCompatActivity) {
AppCompatActivity activity = ((AppCompatActivity) getActivity());
if (activity.getSupportActionBar() != null)
activity.getSupportActionBar().setTitle(R.string.nav_example1);
}
}
private List<String> getContactsWithLetter(char letter) {
List<String> contacts = new ArrayList<>();
for (String contact : getResources().getStringArray(R.array.names_)) {
if (contact.charAt(0) == letter) {
contacts.add(contact);
}
}
return contacts;
}
private class ContactsSection extends StatelessSection {
String title;
List<String> list;
ContactsSection(String title, List<String> list) {
super(new SectionParameters.Builder(R.layout.section_ex1_item)
.headerResourceId(R.layout.section_ex1_header)
.build());
this.title = title;
this.list = list;
}
#Override
public int getContentItemsTotal() {
return list.size();
}
#Override
public RecyclerView.ViewHolder getItemViewHolder(View view) {
return new ItemViewHolder(view);
}
#Override
public void onBindItemViewHolder(RecyclerView.ViewHolder holder, int position) {
final ItemViewHolder itemHolder = (ItemViewHolder) holder;
String name = list.get(position);
itemHolder.tvItem.setText(name);
itemHolder.imgItem.setImageResource(name.hashCode() % 2 == 0 ? R.drawable.ic_face_black_48dp : R.drawable.ic_tag_faces_black_48dp);
itemHolder.rootView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Toast.makeText(getContext(), String.format("Clicked on position #%s of Section %s", sectionAdapter.getPositionInSection(itemHolder.getAdapterPosition()), title), Toast.LENGTH_SHORT).show();
}
});
}
#Override
public RecyclerView.ViewHolder getHeaderViewHolder(View view) {
return new HeaderViewHolder(view);
}
#Override
public void onBindHeaderViewHolder(RecyclerView.ViewHolder holder) {
HeaderViewHolder headerHolder = (HeaderViewHolder) holder;
headerHolder.tvTitle.setText(title);
}
}
private class HeaderViewHolder extends RecyclerView.ViewHolder {
private final TextView tvTitle;
HeaderViewHolder(View view) {
super(view);
tvTitle = (TextView) view.findViewById(R.id.tvTitle);
}
}
private class ItemViewHolder extends RecyclerView.ViewHolder {
private final View rootView;
private final ImageView imgItem;
private final TextView tvItem;
ItemViewHolder(View view) {
super(view);
rootView = view;
imgItem = (ImageView) view.findViewById(R.id.imgItem);
tvItem = (TextView) view.findViewById(R.id.tvItem);
}
}
}
use structure similar to
public class MultiArray<T> {
List<ItemGroup> lists = new ArrayList<>();
public void addList(String headerText, List<T> list) {
lists.add(new ItemGroup(headerText, list));
}
public int itemCount() {
int count = 0;
for (ItemGroup group : lists) {
count += group.count();
}
return count;
}
public T getItem(int position) {
int count = 0;
for (ItemGroup group : lists) {
if (count + group.count() >= position) {
return group.item(position - count);
}
count += group.count();
}
return null;
}
public int getGroupIndex(int position) {
int count = 0;
int groupIndex = 0;
for (ItemGroup group : lists) {
if (count + group.count() >= position) {
return groupIndex;
}
count += group.count();
groupIndex++;
}
return -1;
}
public String getHeaderText(int position){
int count = 0;
for (ItemGroup group : lists) {
if (count + group.count() >= position) {
return group.headerText;
}
count += group.count();
}
return "";
}
class ItemGroup {
public final String headerText;
public final List<T> list;
public ItemGroup(String headerText, List<T> list) {
this.headerText = headerText;
this.list = list;
}
public int count() {
return list.size();
}
public T item(int position) {
return list.get(position);
}
}
}
you can optimize it for faster performance