I am creating a document arrangement activity with RecyclerView. I want to arrange the document with drag and drop. It was done by using ItemTouchHelper.Callbackbut after that I can't set the page number after the OnItemMove callback. what should I do?
EDIT: added code snippet
package adapters;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.graphics.pdf.PdfRenderer;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
import com.mobilix.docscanner.R;
import java.util.ArrayList;
import java.util.Collections;
import helper.ItemTouchHelperAdapter;
import helper.ItemTouchHelperViewHolder;
import helper.OnStartDragListener;
import helper.SimpleItemTouchHelperCallback;
public class PageAjdustAdapter extends RecyclerView.Adapter<PageAjdustAdapter.PageAdjustHolder> implements ItemTouchHelperAdapter, OnStartDragListener {
private final String TAG = getClass().getName();
Context mContext;
ArrayList<PdfPage> pdfPages = new ArrayList<>();
private ItemTouchHelper itemTouchHelper;
public PageAjdustAdapter(Context context, ArrayList<PdfPage> pages) {
this.mContext = context;
pdfPages = pages;
ItemTouchHelper.Callback callback = new SimpleItemTouchHelperCallback(this);
itemTouchHelper = new ItemTouchHelper(callback);
itemTouchHelper.attachToRecyclerView(((Activity) context).findViewById(R.id.rcvPageArrange));
}
#NonNull
#Override
public PageAdjustHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(mContext).inflate(R.layout.item_page_adajustment, parent, false);
return new PageAdjustHolder(view);
}
#Override
public void onBindViewHolder(#NonNull PageAdjustHolder holder, int position) {
Log.d(TAG, "onBindViewHolder: ");
holder.ivPage.setImageBitmap(pdfPages.get(position).bitmap);
holder.cbPage.setChecked(pdfPages.get(position).isSelected);
holder.tvPageNo.setText(String.valueOf(position + 1));
holder.cbPage.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
pdfPages.get(holder.getAdapterPosition()).isSelected = isChecked;
}
});
holder.ivRotate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int pos = holder.getAdapterPosition();
pdfPages.get(pos).bitmap = Bitmap.createBitmap(//
pdfPages.get(pos).bitmap, 0, 0, pdfPages.get(pos).bitmap.getWidth(),//
pdfPages.get(pos).bitmap.getHeight(), pdfPages.get(pos).matrix, true);//
notifyItemChanged(pos);
}
});
}
#Override
public int getItemCount() {
return pdfPages.size();
}
#Override
public boolean onItemMove(int fromPosition, int toPosition) {
Log.d(TAG, "onItemMove: ->fp " + (fromPosition + 1) + " tp-> " + (toPosition + 1));
Collections.swap(pdfPages, fromPosition, toPosition);
notifyItemMoved(fromPosition, toPosition);
return false;
}
#Override
public void onItemDismiss(int position) {
pdfPages.remove(position);
notifyItemRemoved(position);
}
#Override
public void onStartDrag(RecyclerView.ViewHolder viewHolder) {
itemTouchHelper.startDrag(viewHolder);
}
public static class PageAdjustHolder extends RecyclerView.ViewHolder implements
ItemTouchHelperViewHolder {
ImageView ivPage, ivRotate;
CheckBox cbPage;
TextView tvPageNo;
public PageAdjustHolder(#NonNull View itemView) {
super(itemView);
ivPage = itemView.findViewById(R.id.ivPage);
ivRotate = itemView.findViewById(R.id.ivRotate);
cbPage = itemView.findViewById(R.id.cbPage);
tvPageNo = itemView.findViewById(R.id.tvPageNo);
}
#Override
public void onItemSelected() {
}
#Override
public void onItemClear() {
}
}
public static class PdfPage {
PdfRenderer.Page page;
Bitmap bitmap;
boolean isSelected;
Matrix matrix;
int rotate = 0;
public PdfPage(PdfRenderer.Page page, Bitmap bitmap) {
this.page = page;
this.bitmap = bitmap;
matrix = new Matrix();
rotate += 90;
matrix.postRotate(90);//martix work on +=90
}
}
}
You have to call notifyDataSetChanged() when an item position is changed. The easiest way it to used onItemClear(), it will be called when an item is de-selected. Add it like following.
#Override
public void onItemClear() {
notifyDataSetChanged();
}
One thing you have to add is check weather the position is actually changed after the drag operation or not other wise it will always update the whole dataset whenever an item is selected and than de-selected.
Edit
Create a local variable in view-holder class. Than you just have to set it in onItemSelected() and check it in onItemClear();
#Override
public void onItemSelected() {
lastpos = getAdapterPosition();
}
#Override
public void onItemClear() {
if(lastpos != getAdapterPosition())
notifyDataSetChanged();
}
Related
I've got the following classes:
MatchActivity.java:
public void setDart1(int playerIndex, int points) {
getDart1().set(playerIndex, points);
}
public ArrayList<Integer> getDart1() {
return dart1;
}
public void setDart2(int playerIndex, int points) {
getDart2().set(playerIndex, points);
}
public ArrayList<Integer> getDart2() {
return dart2;
}
public void setDart3(int playerIndex, int points) {
getDart3().set(playerIndex, points);
}
public ArrayList<Integer> getDart3() {
return dart3;
}
MatchActivityPlayerAdapter.java:
package de.tkirchmann.myaveragev3;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.constraintlayout.widget.ConstraintLayout;
import androidx.recyclerview.widget.RecyclerView;
import java.io.Serializable;
import java.util.List;
public class MatchActivityPlayerAdapter extends RecyclerView.Adapter<MatchActivityPlayerAdapter.MatchActivityPlayerRowViewHolder> {
private final List<Player> playerList;
private final Match match;
private Context context;
MatchActivityPlayerAdapter(List<Player> playerList, Match match) {
this.playerList = playerList;
this.match = match;
}
#NonNull
#Override
public MatchActivityPlayerAdapter.MatchActivityPlayerRowViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.match_activity_row_layout, parent, false);
return new MatchActivityPlayerRowViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull MatchActivityPlayerAdapter.MatchActivityPlayerRowViewHolder holder, int position) {
final Player player = playerList.get(position);
MatchActivity matchActivity = new MatchActivity();
holder.nameTextView.setText(player.getPlayerName());
holder.pointsTextView.setText(matchActivity.getRemainingPoints().get(position));
holder.dart1.setText(matchActivity.getDart1().get(position));
holder.dart2.setText(matchActivity.getDart2().get(position));
holder.dart3.setText(matchActivity.getDart3().get(position));
holder.dartsCombined.setText(matchActivity.getDartsCombined().get(position));
/*holder.averageTextView.setText(matchActivity.getAverage().get(position));*/
}
#Override
public int getItemCount() {
return playerList.size();
}
class MatchActivityPlayerRowViewHolder extends RecyclerView.ViewHolder {
public TextView nameTextView, pointsTextView, averageTextView, dart1, dart2, dart3, dartsCombined;
public MatchActivityPlayerRowViewHolder(View playerRowView) {
super(playerRowView);
final ConstraintLayout playerRowRootLayout = playerRowView.findViewById(R.id.match_player_row_root_layout);
nameTextView = playerRowView.findViewById(R.id.name);
pointsTextView = playerRowView.findViewById(R.id.points);
averageTextView = playerRowView.findViewById(R.id.average);
dart1 = playerRowView.findViewById(R.id.dart1);
dart2 = playerRowView.findViewById(R.id.dart2);
dart3 = playerRowView.findViewById(R.id.dart3);
dartsCombined = playerRowView.findViewById(R.id.last_darts_combined);
}
}
}
In the onBindViewHolder() method in the custom adapter I want to set the texts of my views by getting the values from the lists via getters from my activity. But I am getting a IndexOutOfBoundsException, so I propably don't have a correct reference/context when calling the getters.
How can I get the correct context/reference to my activity?
You can try this:
((YourActivityName) itemView.getContext()).getDart1();
and then so on for other getters. You can use any public method using this.
I'm having this issue where the old viewHolder of a position in the recyclerview isn't deleted or reset before recycling it. In my case this means that if I scroll and go back to the former position it now has two views stacked on top of each other. I tried solving this by setting the visiblity of the view to be inflated to gone but this is a solution for the short run and I want to understand how to really solve this. I also tried to setRecycble(false) but then my views take longer to inflate and recycling the views also makes more sense My Adapter code is below:
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.core.content.ContextCompat;
import androidx.recyclerview.widget.RecyclerView;
import com.chatr.app.android.Interfaces.MessageListParent;
import com.chatr.app.android.Models.ChatrInvitePending;
import com.chatr.app.android.Models.ChatrMessagingInfo;
import com.chatr.app.android.R;
import com.chatr.app.android.Repositories.MessageRepository;
import com.chatr.app.android.RoomDB.ChatDatabase.ChatEntity;
import com.chatr.app.android.RoomDB.MessagesDatabase.MessageEntity;
import com.chatr.app.android.Tools.ChatrApplication;
import com.chatr.app.android.Tools.ChatrErrorHandler;
import com.chatr.app.android.Views.MessageItemView;
import org.jetbrains.annotations.NotNull;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static com.chatr.app.android.Manager.MessageManager.CONSTANT_OTHER_TYPE;
import static com.chatr.app.android.Manager.MessageManager.CONSTANT_SELF_TYPE;
public class MessageListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
//Constants
private static final String TAG = "MessageListAdapter";
private static final int CONSTANT_MESSAGE_TYPE = 0;
private static final int CONSTANT_INFORMATION_TYPE = 1;
//Data list
private final ArrayList<MessageEntity> messageEntityList = new ArrayList<>();
private final ArrayList<Object> additionalInformationList = new ArrayList<>();
//Callback
private final MessageListParent parentCallback;
public MessageListAdapter(MessageListParent parent) {
this.parentCallback = parent;
}
#NonNull
#Override
public RecyclerView.ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
RecyclerView.ViewHolder viewHolder = null;
if (viewType == CONSTANT_MESSAGE_TYPE) {
MessageItemView messageItemView = new MessageItemView(parent.getContext());
messageItemView.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
viewHolder = new MessageViewHolder(messageItemView);
}
else if(viewType == CONSTANT_INFORMATION_TYPE){
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_chat_view_information_text,parent);
//v.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
viewHolder = new InformationTextViewHolder(v);
}
return viewHolder;
}
#Override
public int getItemViewType(int position) {
Object v = null;
for(Object obj : additionalInformationList){
if (additionalInformationList.get(position) instanceof ChatrInvitePending){
if (((ChatrInvitePending)
additionalInformationList.get(position)).getRecyclerViewPosition() == position){
v = obj;
break;
}
}
else if (additionalInformationList.get(position) instanceof ChatrMessagingInfo){
if (((ChatrMessagingInfo)
additionalInformationList.get(position)).getRecyclerViewPosition() == position){
v = obj;
break;
}
}
}
if (v == null){
return CONSTANT_MESSAGE_TYPE;
}
else{
return CONSTANT_INFORMATION_TYPE;
}
}
#Override
public void onBindViewHolder(#NonNull RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()){
case CONSTANT_MESSAGE_TYPE:
generateMessageTypeView((MessageViewHolder) holder, position);
case CONSTANT_INFORMATION_TYPE:
//generateInformationTypeView((InformationTextViewHolder) holder, position);
}
}
public void generateMessageTypeView(MessageViewHolder holder, int position) {
try{
holder.messageItemView.setFormerEntity(messageEntityList.get(position-1));
}catch (Exception e){
ChatrErrorHandler.handleException(e);
}
holder.messageItemView.setEntity(messageEntityList.get(position));
if(!messageEntityList.get(position).isRead()) {
parentCallback.viewIsRead(messageEntityList.get(position));
}
}
#Override
public int getItemCount() {
return messageEntityList.size();
}
public void updateMessageList(List<MessageEntity> messageEntitiesList) {
this.messageEntityList.clear();
this.messageEntityList.addAll(new ArrayList<>(messageEntitiesList));
notifyItemInserted(messageEntitiesList.size());
}
public void updateAdditionalInfoList(List<Object> additionalList) {
this.additionalInformationList.clear();
this.additionalInformationList.addAll(new ArrayList<>(additionalList));
notifyItemInserted(additionalList.size());
}
#Override
public void onViewRecycled(#NonNull #NotNull RecyclerView.ViewHolder holder) {
super.onViewRecycled(holder);
MessageViewHolder messageViewHolder = (MessageViewHolder) holder;
messageViewHolder.messageItemView.clear();
}
public static class MessageViewHolder extends RecyclerView.ViewHolder{
private final MessageItemView messageItemView;
public MessageViewHolder(#NonNull View itemView) {
super(itemView);
messageItemView = (MessageItemView) itemView;
}
}
public static class InformationTextViewHolder extends RecyclerView.ViewHolder{
private final TextView textView;
public InformationTextViewHolder(#NonNull View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.title_information_text_chat);
}
}
}
Here you can see the issue I have:
Here is my view that I inflate:
import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.ColorFilter;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.net.Uri;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.TextPaint;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.bumptech.glide.Glide;
import com.chatr.app.android.Manager.MediaManager;
import com.chatr.app.android.Manager.MessageManager;
import com.chatr.app.android.R;
import com.chatr.app.android.Repositories.ChatRepository;
import com.chatr.app.android.Repositories.MessageRepository;
import com.chatr.app.android.RoomDB.ChatDatabase.ChatEntity;
import com.chatr.app.android.RoomDB.MediaDatabase.MediaEntity;
import com.chatr.app.android.RoomDB.MessagesDatabase.MessageEntity;
import org.jetbrains.annotations.NotNull;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MessageItemView extends FrameLayout {
private static final long CONSTANT_TIME_5_MIN = 300000;
private int viewType = 1;
private MessageEntity messageEntity;
private TextView txtContent;
private TextView txtTime;
private ImageView imageView;
private AudioMessageView audioMessageView;
private ChatrGradientView chatrGradientView;
private final String regexEmoji = "([\\u20a0-\\u32ff\\ud83c\\udc00-\\ud83d\\udeff\\udbb9\\udce5-\\udbb9\\udcee])";
private static final String TAG = "MessageItemView";
private MessageEntity formerMessageEntity;
public MessageItemView(#NonNull Context context) {
super(context);
}
public MessageItemView(#NonNull Context context, #Nullable AttributeSet attrs) {
super(context, attrs);
}
public MessageItemView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
public MessageItemView(#NonNull Context context, #Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
}
private void init() {
Log.d(TAG, "init: " + viewType);
if (viewType == MessageManager.CONSTANT_OTHER_TYPE) {
Log.d(TAG, "init:3 ");
LayoutInflater.from(getContext()).inflate(R.layout.layout_chat_other_message_view_item, this);
}
if (viewType == MessageManager.CONSTANT_SELF_TYPE) {
Log.d(TAG, "ini2t: " + viewType);
LayoutInflater.from(getContext()).inflate(R.layout.layout_chat_self_message_view_item, this);
}
initViews();
}
#NotNull
public String convertMillisToTime(long millis) {
Log.d(TAG, "convertMillisToTime: " + millis);
DateFormat formatter = new SimpleDateFormat("HH:mm", Locale.GERMANY);
formatter.setTimeZone(TimeZone.getTimeZone("GMT+2" +
""));
return formatter.format(new Date(millis*1000));
}
private void initViews() {
Log.d(TAG, "initViews: ");
imageView = findViewById(R.id.img_content_message_item);
txtContent = findViewById(R.id.txt_content_message_item);
txtTime = findViewById(R.id.message_date_indicator_txt);
chatrGradientView = findViewById(R.id.img_message_item_profile_pic);
audioMessageView = findViewById(R.id.audio_message_view_in_message);
ChatRepository.get(getContext())
.getStartGradientChatEntity(messageEntity.getChatId(), new ChatRepository.GetGradient() {
#Override
public void getGradient(int color) {
chatrGradientView.setGradientStartColor(color);
}
});
ChatRepository.get(getContext())
.getEndGradientChatEntity(messageEntity.getChatId(), new ChatRepository.GetGradient() {
#Override
public void getGradient(int color) {
chatrGradientView.setGradientEndColor(color);
}
});
imageView.setVisibility(GONE);
txtContent.setVisibility(VISIBLE);
if (formerMessageEntity == null || formerMessageEntity.getDateSent() > CONSTANT_TIME_5_MIN ){
txtTime.setVisibility(VISIBLE);
txtTime.setText(convertMillisToTime(messageEntity.getDateSent()));
}
if (messageEntity != null) {
imageView.setVisibility(GONE);
txtContent.setVisibility(VISIBLE);
txtContent.setText(messageEntity.getContentText());
}
Log.d(TAG, "run-3: ");
if (messageEntity.getMediaId()!= -1){
txtContent.setVisibility(GONE);
Log.d(TAG, "run-2: " + messageEntity.getMediaId());
MessageRepository.get(getContext()).getMediaWithId(messageEntity.getMediaId(),
new MessageRepository.getMediaEntity() {
#Override
public void getMedia(MediaEntity mediaEntity) {
Log.d(TAG, "run-1: " + mediaEntity);
mediaAvailabilityWork(mediaEntity);
}
});
}
else{
Glide.with(MessageItemView.this).clear(imageView);
imageView.setImageDrawable(null);
imageView.setVisibility(GONE);
}
Matcher matchEmo = Pattern.compile(regexEmoji).matcher(txtContent.getText());
while(matchEmo.find()){
Log.d(TAG, "initViews: ");
Spannable spannable = new SpannableString(txtContent.getText());
spannable.setSpan(new ForegroundColorSpan(Color.WHITE), matchEmo.start(),
matchEmo.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
txtContent.setText(spannable, TextView.BufferType.SPANNABLE);
}
}
public void mediaAvailabilityWork(MediaEntity mediaEntity) {
Log.d(TAG, "run0: ");
if (mediaEntity != null) {
Log.d(TAG, "run1: " +mediaEntity.getTypeMedia());
if (mediaEntity.getTypeMedia().equals(MediaManager.CONSTANT_MEDIA_TYPE_AUDIO)){
audioMessageView.post(new Runnable(){
#Override
public void run() {
Log.d(TAG, "run2: ");
audioMessageView.setVisibility(VISIBLE);
imageView.setVisibility(GONE);
audioMessageView.setMediaEntity(mediaEntity);
}
});
}
else if (mediaEntity.getTypeMedia().equals(MediaManager.CONSTANT_MEDIA_TYPE_IMG)){
imageView.post(new Runnable() {
#Override
public void run() {
Log.d(TAG, "run3123123: ");
imageView.setVisibility(VISIBLE);
audioMessageView.setVisibility(GONE);
Glide.with(MessageItemView.this).
load(mediaEntity.getFileUrl()).centerCrop().into(imageView);
}
});
}
}
}
public void setEntity(MessageEntity messageEntity) {
this.viewType = messageEntity.getChatType();
this.messageEntity = messageEntity;
Log.d(TAG, "setEntity: " + messageEntity.getMediaId());
init();
}
public void setFormerEntity(MessageEntity formerMessageEntity) {
this.formerMessageEntity = formerMessageEntity;
}
public void clear() {
viewType = 1;
txtTime.setText("");
txtContent.setText("");
audioMessageView.setVisibility(GONE);
txtContent.setVisibility(GONE);
this.postInvalidate();
}
}
I have a problem with my android app.
I have a RecyclerView and a click handler for it. When you click on a list item, one of the class fields is displayed on the screen. Also inside there is a button, by clicking on which another class field should be displayed. But the program throws a NullPointerException. I understand why this is happening, but I cannot understand how to modify my code, please help.
here is my Adapeter
package com.skorbr.stock_yandextest;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class TickerAdapter extends RecyclerView.Adapter<TickerAdapter.TickerViewHolder> {
private List<Ticker> tickers;
private Context context;
// listener
private final Listener onTickerClickListener;
// constructor
public TickerAdapter(List<Ticker> tickers, Listener onTickerClickListener) {
this.tickers = tickers;
this.onTickerClickListener = onTickerClickListener;
}
#NonNull
#Override
public TickerViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
context = parent.getContext();
View view = LayoutInflater.from(context).inflate(R.layout.recycler_stock_item, parent, false);
// click on RecyclerView
view.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onTickerClickListener.onTickerClick((Ticker) v.getTag());
}
});
// click on button
view.findViewById(R.id.button_favourite).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
onTickerClickListener.onFavouriteClick((Ticker) v.getTag());
}
});
return new TickerViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull TickerViewHolder holder, int position) {
Ticker ticker = tickers.get(position);
holder.bind(ticker);
holder.itemView.setTag(ticker);
}
#Override
public int getItemCount() {
return tickers.size();
}
class TickerViewHolder extends RecyclerView.ViewHolder {
private TextView ticker;
private TextView tickerFull;
private TextView price;
private TextView priceChange;
private ImageView tickerLogo;
private Button favouriteButton;
public TickerViewHolder(#NonNull final View itemView) {
super(itemView);
ticker = itemView.findViewById(R.id.ticker);
tickerFull = itemView.findViewById(R.id.ticker_full);
price = itemView.findViewById(R.id.price);
priceChange = itemView.findViewById(R.id.price_change);
tickerLogo = itemView.findViewById(R.id.ticker_image);
favouriteButton = itemView.findViewById(R.id.button_favourite);
}
// заполнение элемента RecyclerView данными
void bind(Ticker ticker) {
double priceNow = ticker.getPrice();
double priceDayAgo = ticker.getPriceDayAgo();
String sign = "";
this.ticker.setText(ticker.getTicker());
this.tickerFull.setText(ticker.getTickerFull());
this.price.setText("$" + priceNow);
// check price
if (priceNow < priceDayAgo) {
sign = "-";
this.priceChange.setTextColor(context.getResources().getColor(R.color.colorRedDm));
} else if (priceNow > priceDayAgo) {
sign = "+";
this.priceChange.setTextColor(context.getResources().getColor(R.color.colorGreenDm));
}
// check favourites
if (ticker.isFavourite()) {
this.favouriteButton.setBackground(context.getDrawable(R.drawable.ic_favourite_on));
} else {
this.favouriteButton.setBackground(context.getDrawable(R.drawable.ic_favourite_off));
}
this.priceChange.setText(String.format("%s$%.2f (%.2f%%)", sign, Math.abs(priceNow-priceDayAgo), Math.abs(priceNow/priceDayAgo*100-100)));
this.tickerLogo.setImageResource(ticker.getTickerLogo());
}
}
interface Listener {
void onTickerClick(Ticker ticker);
void onFavouriteClick(Ticker ticker);
}
}
Here is my Main Activity
package com.skorbr.stock_yandextest;
import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import java.util.ArrayList;
import java.util.List;
public class ActivityMain extends Activity {
private RecyclerView tickerList;
private TickerAdapter tickerAdapter;
private List<Ticker> tickerListList;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tickerListList = tickerList();
tickerList = findViewById(R.id.tickers_list);
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
tickerList.setLayoutManager(layoutManager);
tickerAdapter = new TickerAdapter(tickerListList, new TickerAdapter.Listener() {
#Override
public void onTickerClick(Ticker ticker) {
Toast.makeText(ActivityMain.this, ticker.getTickerFull(), Toast.LENGTH_SHORT);
}
#Override
public void onFavouriteClick(Ticker ticker) {
Toast.makeText(ActivityMain.this, ticker.getTicker(), Toast.LENGTH_SHORT);
}
});
tickerList.setAdapter(tickerAdapter);
}
private List<Ticker> tickerList() {
List<Ticker> tickers = new ArrayList<>();
tickers.add(new Ticker("APPL", "Apple Inc.", 138.54, 150.22, R.drawable.apple_logo, false));
tickers.add(new Ticker("TSLA", "Tesla Motors", 904.37, 753.92, R.drawable.tesla_logo, true));
tickers.add(new Ticker("GOOGL", "Alphabel Class A", 1845.90, 1845.90, R.drawable.google_logo, false));
return tickers;
}
}
Here is my class for data
package com.skorbr.stock_yandextest;
public class Ticker {
private String ticker;
private String tickerFull;
private double price;
private double priceDayAgo;
private int tickerLogo;
private boolean isFavourite;
public Ticker(String ticker, String tickerFull, double price, double priceDayAgo, int tickerLogo, boolean isFavourite) {
this.ticker = ticker;
this.tickerFull = tickerFull;
this.price = price;
this.priceDayAgo = priceDayAgo;
this.tickerLogo = tickerLogo;
this.isFavourite = isFavourite;
}
public String getTicker() {
return ticker;
}
public String getTickerFull() {
return tickerFull;
}
public double getPrice() {
return price;
}
public double getPriceDayAgo() {
return priceDayAgo;
}
public int getTickerLogo() {
return tickerLogo;
}
public boolean isFavourite() {
return isFavourite;
}
public void setFavourite(boolean favourite) {
isFavourite = favourite;
}
}
#Override
public void onBindViewHolder(#NonNull TickerViewHolder holder, int position) {
Ticker ticker = tickers.get(position);
holder.bind(ticker);
holder.itemView.setTag(ticker);
// add this line
holder.favouriteButton.setTag(ticker);
}
Or you can modify the onCreateViewHolder()
view.findViewById(R.id.button_favourite).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// instead of
onTickerClickListener.onFavouriteClick((Ticker) v.getTag());
// use
onTickerClickListener.onFavouriteClick((Ticker) view.getTag());
}
});
I am currently working on a personal adapter.
I have some buttons in every one of them.
One to delete, one to edit and one to add to shared pref. list.
However, I do not know how to get the Id or a specific property from the element such as it's ID.
In other words, I try to get the ID (a property from my object) to display when I click one of the buttons, later on, I will implement the feature.
However, I don't really understand where to get the elements and what does every #Override do in the adapter, also, where to declare the onClick function?
Here is my adapter, for now (The Toastare for test purpose):
package a.bogin.revmidterm.Adapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import a.bogin.revmidterm.Models.StringInfos;
import a.bogin.revmidterm.R;
public class StringsAdapter extends RecyclerView.Adapter<StringsAdapter.ViewHolder> {
private List<StringInfos> allStrings;
public StringsAdapter(List<StringInfos> lst){
this.allStrings = lst;
}
public class ViewHolder extends RecyclerView.ViewHolder {
TextView string1;
TextView string2;
TextView string3;
Button delB;
Button editB;
Button addPrefB;
public ViewHolder(final View itemView) {
super(itemView);
string1 = itemView.findViewById(R.id.forS1);
string2 = itemView.findViewById(R.id.forS2);
string3 = itemView.findViewById(R.id.forS3);
delB = itemView.findViewById(R.id.delBtn);
delB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
}
});
editB = itemView.findViewById(R.id.editbtn);
editB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(itemView.getContext(), "TEST", Toast.LENGTH_SHORT).show();
}
});
addPrefB = itemView.findViewById(R.id.pref);
addPrefB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(itemView.getContext(), " C MON NOM", Toast.LENGTH_SHORT).show();
}
});
}
}
#Override
public void onBindViewHolder(final StringsAdapter.ViewHolder vh, final int position) {
StringInfos str = allStrings.get(position);
vh.string1.setText(str.getString1());
vh.string2.setText(str.getString2());
vh.string3.setText(str.getString3());
}
#Override
public int getItemCount() {
return allStrings.size();
}
#Override
public StringsAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
Context ctx = parent.getContext();
LayoutInflater inf = LayoutInflater.from(ctx);
View createdViewForAdapter = inf.inflate(R.layout.string_adapter_infos, parent, false);
ViewHolder vh = new ViewHolder(createdViewForAdapter);
vh.editB.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(view.getContext(), "TEEEEST", Toast.LENGTH_SHORT).show();
}
});
return vh;
}
}
Here is my object class:
package a.bogin.revmidterm.Models;
public class StringInfos {
private int id;
private String string1;
private String string2;
private String string3;
public StringInfos(String string1, String string2, String string3) {
this.string1 = string1;
this.string2 = string2;
this.string3 = string3;
}
public String getString1() {
return string1;
}
public void setString1(String string1) {
this.string1 = string1;
}
public String getString2() {
return string2;
}
public void setString2(String string2) {
this.string2 = string2;
}
public String getString3() {
return string3;
}
public void setString3(String string3) {
this.string3 = string3;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Also, here is my MainActivity:
package a.bogin.revmidterm;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import java.util.ArrayList;
import a.bogin.revmidterm.Adapter.StringsAdapter;
import a.bogin.revmidterm.DB.DBManager;
import a.bogin.revmidterm.Models.StringInfos;
public class MainActivity extends AppCompatActivity {
ArrayList<StringInfos> listOfAll;
StringsAdapter strAdapter;
RecyclerView.LayoutManager mLayoutManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLayoutManager = new LinearLayoutManager(this);
.setLayoutManager(mLayoutManager);
RecyclerView myOwnRc = findViewById(R.id.rc);
myOwnRc.addItemDecoration(new DividerItemDecoration(getApplicationContext(), DividerItemDecoration.VERTICAL));
mLayoutManager = new LinearLayoutManager(this);
myOwnRc.setLayoutManager(mLayoutManager);
listOfAll = DBManager.getAllItems();
strAdapter = new StringsAdapter(listOfAll);
myOwnRc.setAdapter(strAdapter);
myOwnRc.setLayoutManager(new LinearLayoutManager(this));
myOwnRc.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View v, int pos, long id){
}
});
}
public void addStuff(View v){
Intent addNew = new Intent(this, AddItem.class);
startActivity(addNew);
}
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inf = getMenuInflater();
inf.inflate(R.menu.itemsstuff, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item){
switch (item.getItemId()){
case R.id.ea:
deleteAll();
return true;
case R.id.pref:
seePrefs();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void seePrefs(){
}
public void deleteAll(){
listOfAll.clear();
finish();
startActivity(getIntent());
}
}
Feel free to suggest me links in order to know where to start or ask for any specification.
Thank you for your time.
Problem with setOnItemClickListner:
myOwnRc.setOnItemClickListener(new AdapterView.OnItemClickListener(){
#Override
public void onItemClick(AdapterView<?> parent, View v, int pos, long id){
}
});
after myOwnRc, it is red, however, the second one is accepted.
After using these lines to display your data in a activity:
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new MyAdapter(myDataset);
mRecyclerView.setAdapter(mAdapter);
You can set up setonItemClickListener:
mRecylerView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
//here you can use the id or position to make changes to your data
//Something like myDataset.add or myDataset.remove
String one = myDataset.get(position).getString1();
}
});
Edit: Updated Main Activity part:
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this);
myOwnRc.setLayoutManager(linearLayoutManager);
strAdapter = new StringsAdapter(listOfAll);
myOwnRc.setAdapter(strAdapter);
myOwnRc.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
}
});
Base on this instructions I've created RecyclerView filtering in my app. Almost everything works fine but there are 2 strange things.
When I input text into search view and there is only one item which meets requirements until I hide keyboard I can't see this item.
Second problem is more complicated because it occurs from time to time. My item in RecyclerView has an image in background and not always when filtering image is loaded properly.
Because I now my description might be unclear here is an gif which shows the problem:
Here is my adapter class:
package com.ostojan.x360.view;
import android.support.v7.util.SortedList;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.ostojan.x360.R;
import com.ostojan.x360.model.Game;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
public class GameAdapter extends RecyclerView.Adapter<GameViewHolder> {
private SortedList<Game> games;
private ArrayList<Game> allGames;
private View.OnClickListener onClickListener;
public GameAdapter(View.OnClickListener onClickListener, List<Game> games) {
this(onClickListener);
this.games.addAll(games);
this.allGames.addAll(games);
}
public GameAdapter(View.OnClickListener onClickListener) {
this.onClickListener = onClickListener;
this.games = new SortedList<Game>(Game.class, new GamesSortedListCallback(this));
this.allGames = new ArrayList<>();
}
#Override
public GameViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.item_game, parent, false);
view.setOnClickListener(onClickListener);
return new GameViewHolder(view);
}
#Override
public void onBindViewHolder(GameViewHolder holder, int position) {
Game game = games.get(position);
holder.title.setText(game.getTitle());
Picasso.with(holder.itemView.getContext())
.load(game.getCoverLink().toString())
.placeholder(R.drawable.ic_loading)
.fit()
.centerCrop()
.error(R.drawable.ic_error)
.into(holder.coverImage);
}
#Override
public int getItemCount() {
return games.size();
}
public void add(Game game) {
this.games.add(game);
this.allGames.add(game);
notifyDataSetChanged();
}
public void addAll(Collection<Game> games) {
this.games.addAll(games);
this.allGames.addAll(games);
notifyDataSetChanged();
}
public void remove(Game game) {
games.beginBatchedUpdates();
games.remove(game);
allGames.remove(game);
games.endBatchedUpdates();
}
public void replaceAll(Collection<Game> games) {
this.games.beginBatchedUpdates();
List<Game> gamesToRemove = new ArrayList<>();
for (int i = 0; i < this.games.size(); i++) {
Game game = this.games.get(i);
if (!games.contains(game)) {
gamesToRemove.add(game);
}
}
for (Game game : gamesToRemove) {
this.games.remove(game);
}
this.games.addAll(games);
this.games.endBatchedUpdates();
}
public Game get(int index) {
return this.games.get(index);
}
public Collection<Game> getGames() {
return allGames;
}
public void clear() {
this.games.clear();
notifyDataSetChanged();
}
public void search(String query) {
replaceAll(filterGames(query));
}
private Collection<Game> filterGames(String query) {
query = query.toLowerCase();
List<Game> filteredGames = new ArrayList<>();
for (Game game : allGames) {
String gameTitle = game.getTitle().toLowerCase();
if (gameTitle.contains(query)) {
filteredGames.add(game);
}
}
return filteredGames;
}
}
View holder:
package com.ostojan.x360.view;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.ImageView;
import android.widget.TextView;
import com.ostojan.x360.R;
import butterknife.BindView;
import butterknife.ButterKnife;
public class GameViewHolder extends RecyclerView.ViewHolder {
#BindView(R.id.text_title)
TextView title;
#BindView(R.id.image_cover)
ImageView coverImage;
public GameViewHolder(View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
}
SortedList callback:
package com.ostojan.x360.view;
import android.support.v7.util.SortedList;
import android.support.v7.widget.RecyclerView;
import com.ostojan.x360.model.Game;
import java.util.Comparator;
public class GamesSortedListCallback extends SortedList.Callback<Game> {
private static final Comparator<Game> GAMES_COMPARATOR = new Comparator<Game>() {
#Override
public int compare(Game o1, Game o2) {
return o1.getId().compareTo(o2.getId());
}
};
private RecyclerView.Adapter<GameViewHolder> adapter;
public GamesSortedListCallback(RecyclerView.Adapter<GameViewHolder> adapter) {
this.adapter = adapter;
}
#Override
public int compare(Game o1, Game o2) {
return GAMES_COMPARATOR.compare(o1, o2);
}
#Override
public void onChanged(int position, int count) {
adapter.notifyItemRangeChanged(position, count);
}
#Override
public boolean areContentsTheSame(Game oldItem, Game newItem) {
return oldItem.equals(newItem);
}
#Override
public boolean areItemsTheSame(Game item1, Game item2) {
return item1.getId() == item1.getId();
}
#Override
public void onInserted(int position, int count) {
adapter.notifyItemRangeInserted(position, count);
}
#Override
public void onRemoved(int position, int count) {
adapter.notifyItemRangeRemoved(position, count);
}
#Override
public void onMoved(int fromPosition, int toPosition) {
adapter.notifyItemMoved(fromPosition, toPosition);
}
}
And here how I call filtering from activity:
RecyclerView gamesList;
GameAdapter gamesAdapter;
#Override
public boolean onQueryTextSubmit(String query) {
onQueryTextChange(query);
return true;
}
#Override
public boolean onQueryTextChange(String newText) {
gamesAdapter.search(newText);
gamesList.scrollToPosition(0);
return true;
}