trying to pass an int variable from Activity to Adapter - java

I'm trying to pass the int pub_or_priv from my Activity1 to Myadapter.
I've looked at posts here and I think I've followed them correctly but it's still not working. The value in my adapter is always 0 whereas it should be 0,1 or 2, as is the case with the value in my Activity1.
Here's what I've done.
In my Activity1 I get "publicorprivate" from my server and convert it to an int with:
//convert public_or_private to an integer
pub_or_priv = Integer.parseInt(obj.getString("publicorprivate"));
For different cells in my recyclerView it will be 0,1 or 2.
Now I want to pass this to my adapter so in my adapter contructor I have:
public MyAdapter(List<Review> reviewUsers, Activity activity, int pub_or_priv) {
this.activity = activity;
the_reviews = reviewUsers;
this.mPub_or_priv = pub_or_priv;
}
And in my Activity1:
pAdapter = new MyAdapter(reviewList, this, pub_or_priv);
Then in MyAdapter:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
Review r = the_reviews.get(position);
//shared_status will be Just U, Private or Public
String shared_status ="";
if(mPub_or_priv==0){
//change colour depending on value
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#DA850B"));
shared_status = "Just U";
}
if(mPub_or_priv==1){
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#0A7FDA"));
shared_status = "Private";
}
if(mPub_or_priv==2){
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#2AB40E"));
shared_status = "Public";
}
((ReviewHolder) viewHolder).phone_user_name.setText(shared_status);
etc..etc..
However in the recyclerView in all cells the phone_user_name textbox is always "Just U", in the #DA850B colour, whereas in fact it is supposed to be Private and Public in some cells, as per the pub_or_priv value in Activity1.
How can I get pub_or_priv correctly into my adapter?, thanks.

It looks like you're using one value in the activity/adapter, so of course all rows show the same value.
In the adapter, use the value in the Review instance that corresponds to the current cell:
#Override
public void onBindViewHolder(final RecyclerView.ViewHolder viewHolder, final int position) {
Review review = the_reviews.get(position);
int pubOrPriv = review.getPublicOrPrivate();
//shared_status will be Just U, Private or Public
String shared_status = "";
if (pubOrPriv == 0) {
//change colour depending on value
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#DA850B"));
shared_status = "Just U";
}
if (pubOrPriv == 1) {
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#0A7FDA"));
shared_status = "Private";
}
if (pubOrPriv == 2) {
((ReviewHolder) viewHolder).phone_user_name.setTextColor(Color.parseColor("#2AB40E"));
shared_status = "Public";
}
//.............
}

Related

Save data from fragments when switching tabs

I've written a game where the user inputs the number of player and every player gets an own tab with an empty table.
Therefore I used a PagerAdapterClass (extends FragmentStatePagerAdapter) and a viewpager.
So every player has the same fragmentView.
Now the user can put variables into the table, bu everytime I switch between the tabs, the input gets lost.
Well, i 'fixed' that problem by adding this to my pageradapter:
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
But it's more stopping the viewpager from destroying than actually saving the data.
My main goal is to really save that stuff in that table.
I already tried https://stackoverflow.com/a/17135346/11956040 but i cannot get mContent because i cannot get the reference of the fragment, because all fragments are not created on their own but all at the same time (or something like that).
I also don't know how to set a Tag.
This way: https://stackoverflow.com/a/18993042/11956040
doesn't work for me.
MainActivity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_game);
Toolbar toolbar = findViewById(R.id.toolbar2);
setSupportActionBar(toolbar);
...
//numPlayer = num of tabs
SectionsPagerAdapter adapter = new SectionsPagerAdapter(numPlayer, getSupportFragmentManager());
ViewPager viewPager = findViewById(R.id.view_pager);
viewPager.setAdapter(adapter);
TabLayout tabs = findViewById(R.id.tabs);
tabs.setupWithViewPager(viewPager);
if(numPlayer >= 5) {
tabs.setTabMode(TabLayout.MODE_SCROLLABLE);
}
}
PagerAdapter:
public class SectionsPagerAdapter extends FragmentStatePagerAdapter {
private int tabNum;
public SectionsPagerAdapter(int tabNum, FragmentManager fm) {
super(fm);
this.tabNum = tabNum;
}
#Override
public PlaceholderFragment getItem(int position) {
return PlaceholderFragment.newInstance(position);
}
#Nullable
#Override
public CharSequence getPageTitle(int position) {
int playerNum = position + 1;
return "Spieler " + playerNum;
}
#Override
public int getCount() {
// Show 2 total pages.
return tabNum;
}
#Override
public void destroyItem(ViewGroup container, int position, Object object) {
}
}
Fragment:
public static PlaceholderFragment newInstance(int index) {
PlaceholderFragment fragment = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt("player", index);
fragment.setArguments(bundle);
return fragment;
}
There must be a solution but I cannot find it or cannot implement it.
Pls help.
Solved my problem this way:
define 2 dimensional ArrayList for rows and columns and counter for columns:
private ArrayList<ArrayList<Integer>> columnArray;
private int column;
onCreateView (for fragments) set column = 0 and add one entry with an empty list to columnArray
and set the first rowList on column index of columnArray:
pointArray.add(column, new ArrayList<Integer>());
final ArrayList<Integer> rowList = pointArray.get(column);
fill the empty rowListwith 0 (maybe it also works in an other way, but I made it this way to have on empty EditTexts a 0 and can easily replace them)
define View.OnFocusChangeListener for all EditTexts like this:
/*I dont know if I could set column final in general,
but you need to set a final int because you call this value in an inner class*/
final int pos = column
for (int i = 0; i <= getEditTexts(pos).size() - 1; i++) {
EditText editTexts = getEditTexts(pos).get(i);
final String editTextsTag = editTexts.getTag().toString();
View.OnFocusChangeListener listener = new View.OnFocusChangeListener() {
#Override
public void onFocusChange(View view, final boolean b) {
if (view.getTag().toString().equals(editTextsTag) && !b) {
//fills rowList
addEntries(pos, rowList);
//adds rowList to columnArray
columnArray.set(pos, rowList);
//save the columnsArray or use it
saveData(columnArray);
}
}
};
editTexts.setOnFocusChangeListener(listener);
define method which collects data from each cell, depending on column position (pos), add it to rowList
for example:
private void addEntries(int pos, ArrayList<Integer> rowList) {
for(int i = 0; i <= 16; i++) {
//this requires EditText_label, i made them dynamically
String edit_label = "edit_" + pos + i;
EditText editText = table.findViewWithTag(edit_label);
String mEditTextString = editText.getText().toString();
try {
int thisValue = Integer.parseInt(mEditString);
rowList.set(j, thisValue);
} catch (NumberFormatException e) {
//maybe you do not need this, but I need it for something else
int thisValue = 0;
rowList.set(j, thisValue);
}
}
}
define a method for saving the columnArray. I used an interface to give it to parent Activity: Here you can find how I made it
Otherwise you can convert the columnArray to a String and save it in a database.
NOTE
I made it with column value set beacuse I increase the value for every column I add during runtime using a method. If you just have one column, you dont need to set it. Just use 0 instead of pos, column

How can I send text value from ViewHolder to ItemTouchHelper class?

I've been learning Java and Android Development for about a month. Maybe, I don't know some features... But I can't find any advise for a week.
I need to send value from one of my fields in ViewHolder (created by onBindViewHolder) to overrided method onChildDraw (in class, that extends ItemTouchHelper). But I can't understand, how can I do this.
I want to call new activity after swipe action and send value of field "name" to that activity. Can I do this with Intent? Or maybe have other way?
Creating ViewHolder (public class ModelsDataAdapter extends RecyclerView.Adapter):
#Override
public void onBindViewHolder(ModelsViewHolder holder, int position) {
ModelsData model = models.get(position);
holder.name.setText(model.getName()); // <-- I NEED THIS VALUE
holder.tags.setText(model.getTags());
holder.keywords.setText(model.getKeywords());
holder.cost.setText(model.getCost().toString());
//-- some code --//
}
My onChildDraw (public class SwipeControl extends ItemTouchHelper.Callback):
#Override
public void onChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
//-- some code --//
int x = 0;
if (dX < -200){ //
viewHolder.itemView.findViewById(R.id.card_foreground).setTranslationX(dX / 3);
} else if (dX > 200){
viewHolder.itemView.findViewById(R.id.card_foreground).setTranslationX(dX / 3);
openStatCard();
} else if (dX == 0){
checkActivity = false;
}
}
Opening new activity (inside SwipeControl.class):
private void openStatCard(){
if (!checkActivity) {
checkActivity = true;
Intent intent = new Intent(context, StatCards.class);
intent.putExtra("choosingModel", model); // <-- PUT "name" IN "model"
context.startActivity(intent);
}
}
Inside onChildDraw method use viewHolder.getAdapterPositon() method to get the position. And when you need the value just use that position to find Name from the models list
EDIT
Inside onChildDraw get the TextView using viewHolder.itemView.findViewById(R.id.name); and then use getText() method to get the Name.

How to change background colour to specific viewholder items in a RecycleView?

I am trying to change background color in specific item(s) in a RecycleView.
Because I need to set text too, I have the following code that works fine:
protected void populateViewHolder(RankingViewHolder viewHolder, final Ranking model, int position)
{
final Context mContext = getActivity().getApplicationContext();
viewHolder.txt_name.setText(model.getUserName());
viewHolder.txt_score.setText(String.valueOf(model.getScore()));
viewHolder.txt_class.setText(model.getUser_class());
Picasso.with(mContext).load(model.getAvatarUrl()).error(R.drawable.ic_people_black_24dp).into(viewHolder.personPhoto);
int totalRanking = adapter.getItemCount();
int realRank = totalRanking - viewHolder.getAdapterPosition();
viewHolder.ranknumber.setText("# "+String.valueOf(realRank));
}
This works as I want and realRanktakes the correct values, and the viewHolder.ranknumber.setText("# "+String.valueOf(realRank));
Sets the right text with no problem.
Now I am trying (as I got a number/text result correct, to make an if statement like this:
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 0)
{
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 1)
{
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
if(adapter.getItemCount() -viewHolder.getAdapterPosition() == 2)
{
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
(I tried with String.valueOf(realRank)equality, with realRankequality too)
In all cases I have the same result. The color changes as its should at positions 1,2,3 BUT it changes at positions 7,8,9 and 14,15,16 and 21,22,23 etc.
What am I missing here?
public class RankingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private ItemClickListener itemClickListener;
public TextView txt_name, txt_score, txt_class, ranknumber;
public ImageView personPhoto;
public RankingViewHolder(View itemView)
{
super(itemView);
txt_name = itemView.findViewById(R.id.txt_name);
txt_score = itemView.findViewById(R.id.txt_score);
personPhoto = itemView.findViewById(R.id.person_photo);
txt_class = itemView.findViewById(R.id.txt_class);
ranknumber = itemView.findViewById(R.id.ranknumber);
itemView.setOnClickListener(this);
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
#Override
public void onClick(View view) {
itemClickListener.onClick(view , getAdapterPosition(),false);
}
}
The adapter:
adapter = new FirebaseRecyclerAdapter<Ranking, RankingViewHolder>(
Ranking.class,
R.layout.layout_ranking,
RankingViewHolder.class,
rankingTbl.orderByChild("score").limitToFirst(100)
)
This line of code int realRank = totalRanking - viewHolder.getAdapterPosition();gives a number (1,2,3,4,5,6 etc.) Why i cannot use this number to check equality?
Notice
Keeping this code for NOT working solution, just for future reference:
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
else if(position == 1){
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
else if(position == 2){
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
else{
viewHolder.itemView.setBackgroundColor(Color.WHITE);
}
This changes the color BUT not for only 3 first items. As you scroll down, changes the color for every 3 first viewable items like before, meaning 1,2,3, 7,8,9, etc.
Update:
I dont use a custom adapter, i use FirebaseRecyclerAdapter.
Thanks to #Muhammad Haroon comment i checked that has getItemViewType. So now i m trying with it like
position =adapter.getItemViewType( 0);
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
Not working for now, but i think its the correct direction...
Update 2
With position its not possible as RecycleView recycles the views so i have the same result. The working code is
if (linearLayoutManager.findFirstVisibleItemPosition() > 0) {
viewHolder.itemView.setBackgroundResource(R.drawable.blackframe);
}
else{
viewHolder.itemView.setBackgroundResource(R.drawable.goldframe);
}
Works fine except that after scrolling loosing the change of background.
So as we want and need the perfection, any idea for keeping even after scroll?
hi try add this in your Adapater it may solve your problem.
#Override
public int getItemViewType(int position) {
return position;
}
Please give this a try
override in your custom adapter
#Override
public long getItemId(int position) {
return position;
}
and in in your adapter object:
myAdapter.setHasStableIds(true);
In populateViewHolder add these line of code
if(position == 0){
viewHolder.itemView.setBackgroundColor(Color.GREEN);
}
else if(position == 1){
viewHolder.itemView.setBackgroundColor(Color.YELLOW);
}
else if(position == 2){
viewHolder.itemView.setBackgroundColor(Color.BLUE);
}
else{
viewHolder.itemView.setBackgroundColor(Color.WHITE);
}
position is a parameter in populateViewHolder.

Get ImageView drawable ID and change it with AsyncTask

What I want to do: get the id of the src of an ImageView, compare it to the ids of two drawables, and swap them, using AsyncTask (just because I want to understand how it works).
I've read similar questions here, and so far this is what I've got:
public class Main extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ImageView image = (ImageView) findViewById(R.id.img);
Integer integer = (Integer) image.getTag();
}
private class cambiarImagen extends AsyncTask<Integer, Integer, Integer> {
protected void onPreExecute() {
ImageView image = (ImageView) findViewById(R.id.img);
Integer integer = (Integer) image.getTag();
int img1 = R.drawable.zapato;
int img2 = R.drawable.zapatod;
}
#Override
protected Integer doInBackground(Integer... values) {
// parte logica
int num = values[0];
int zapato = values[1];
int zapatod = values[2];
if (num == zapato) {
num = zapatod;
} else if (num == zapatod) {
num = zapato;
}
return num;
}
protected Void onPostExecute(Integer... values) {
int num = values[0];
ImageView image = (ImageView) findViewById(R.id.img);
image.setTag(num);
return null;
}
}
Of course this doesn't work.
1. I don't understand how to get the id of the drawable that ImageView has as its src.
2. I don't understand how the params are passed in AsyncTask; onPreExecute should receive the UI stuff, doInbackground should receive it to compare it and return the drawable int that should be set to the ImageView, and onPreExecute should set it to the ImageView.
I don't understand how to get the id of the drawable that ImageView has as its src.
I haven't had to do this so may not work but you should be able to use
imageView.getDrawable().getId();
I don't understand how the params are passed in AsyncTask;
Whatever you pass in task.execute() is received by doInBackground(). If you call publishProgress() then whatever params are sent there are received by onProgressUpdate(). And the data returned in doInBackground() is received by onPostExecute().
AsyncTask, just so you know, shouldn't be needed for this but I know you said you wanted to learn how to use it. I was a little confused on exactly what specifically you were having trouble with besides these two things so please elaborate if I missed something.
ImageView Docs
AsyncTask Docs
AsyncTask Example (in case it can be helpful)
You should do other task if you like to get to learn ASyncTask.
I would have done a dialog with progress bar or something instead if i wanted to learn ASyncTask.
edit:
As Samus Arin comment on the main post about you should always have track on which image that you are showing. so instead use something like
if(currentImage == R.Drawable.image1){
image.setImageResource(R.Drawable.image2);
}else{
image.setImageResource(R.Drawable.image1);
}
For what it's worth, take a look at what I'm doing with an AsyncTask, maybe it'll give ya some ideas.
This is Monodroid/C# code, not raw Java/Android (but the syntax is extremely close). As such, inner-classes do not get an implicit reference to their containing object, and so I pass one in (called outer in the constructor). I chose to name it "_" as a lexicographical extension to .NET's _member naming convention for private data members.
public class MonthChangeTask : AsyncTask
{
private CalendarView _; // outer class
private DateTime _newMonth;
private bool _refreshInspectionRecordsRemote;
private bool _changingInspector;
private bool _todayButtonPressed;
private Android.App.ProgressDialog _progressDialog;
private IMXController _controller;
private Dictionary<string, string> _paramz;
private DateTime _newSelectedDate;
public MonthChangeTask( CalendarView outer, DateTime newMonth, bool changingInspector, bool refreshInspectionRecordsRemote, bool todayButtonPressed )
{
_ = outer;
_newMonth = newMonth;
_changingInspector = changingInspector;
_refreshInspectionRecordsRemote = refreshInspectionRecordsRemote;
_todayButtonPressed = todayButtonPressed;
}
protected override void OnPreExecute()
{
base.OnPreExecute();
_progressDialog = Android.App.ProgressDialog.Show( _ , "", "Loading Inspections...");
_newSelectedDate = _._calendar.SetMonth(new DateTime(_newMonth.Year, _newMonth.Month, 1));
AppSettingService.SetCalendarDate(_newMonth);
_paramz = new Dictionary<string, string>();
string target = MD.MxNAVIGATION.CONTROLLER.CALENDAR._name;
string action = MD.MxNAVIGATION.CONTROLLER.ACTION.GET;
string command = _refreshInspectionRecordsRemote
? ((int) MD.MxNAVIGATION.CONTROLLER.CALENDAR.Command.RefreshInspectionRecordsRemote).ToString()
: ((int) MD.MxNAVIGATION.CONTROLLER.CALENDAR.Command.RefreshInspectionRecordsLocal).ToString();
string url = target + "/" + action + "/" + command;
_controller = MXContainer.Instance.GetController(url, ref _paramz);
}
protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] #params)
{
if ( _paramz == null )
{
Log.Info(FIDB.TAG_APP, "MonthChangeTask.DoInBackground(): paramz = NULL");
}
else
{
_controller.Load( _paramz );
}
return true;
}
protected override void OnPostExecute(Java.Lang.Object result)
{
base.OnPostExecute(result);
_progressDialog.Dismiss();
_.Model = (CalendarVM)_controller.GetModel();
if (_changingInspector)
{
_._calendar.PermitSwitch = _.Model.Buttons.PermitsVisible;
_._calendar.ComplaintSwitch = _.Model.Buttons.ComplaintsVisible;
_._calendar.ProjectSwitch = _.Model.Buttons.ProjectsVisible;
_._calendar.PeriodicInspectionSwitch = _.Model.Buttons.PeriodicInspectionsVisible;
}
_.UpdateCalendar(_.Model.Inspections);
if( _todayButtonPressed )
{
_._calendar.SelectedDate = _._calendar.CurrentDate;
}
else
{
_._calendar.SelectedDate = _newSelectedDate;
}
_._calendar.Invalidate();
AppSettingService.SetCalendarDate( _._calendar.SelectedDate );
if ( _.Model.IsParcelCacheDownloading )
{
AnimationTask task = new AnimationTask( _ );
task.Execute( new Java.Lang.Object[1] );
}
}
}

ListView custom adapter for different rows

I am using a ListView to display some JSON data and want to display each result according to its type (Artist, Release, Label...).
I will be using an interface implemented by each type of result :
public interface Result {
public Int getId();
public String getThumb();
// ...
}
I would like to know which of these choices is the best solution (I am open to better things, that's just what I had on the top of my head):
creating an enum ResultType in the interace (so inherited class will have to return their own value like ResultType.ARTIST in a getType() method
checking the instance type using isInstance()
I would like to know what would be the best way to perform something equivalent to this C code (array of function pointer) as I would like to avoid using to many if/else statements.
typedef struct s_func {
const char *type_name;
void* (*func_pointer)(void *result_infos);
} t_func;
static t_func type_array[] = {
{"artist", artist_function},
{"label", label_function},
// ....
{NULL, NULL}
}
void check_type(const char *type_string)
{
int i, j = 0;
char *key_value;
// compare string and array key
while (type_array && type_array[i][0]) {
key_value = type_array[i][0];
// if key match
if (type_string && strncmp(type_string, key_value, strlen(type_string)) == 0) {
type_array[i][1](); // call appropriate function;
}
i++;
}
}
I guess it would be using a HashMap but (I might be wrong) it doesn't seem to have a litteral notation. Is there any easy way to build an HashMap of pairs ?
Thank you
I think you can use an ArrayAdapter.
Take a look at this tutorial to see what I mean.
It'll need some twiddling so that it can deal with the different kinds of items.
Make an interface MyListItem
public interface MyListItem {
public int getLayout();
public void bindToView(View v);
}
Make different layouts for the display of Artist, Release, Label.
Make classes Artist, Release, Label that implement MyListItem.
public class Artist implements MyListItem {
private String Name;
public Artist(String name){
this.name = name;
}
public int getLayout() {
return R.layout.artistlayout;
}
public void bindToView(View v) {
TextView textView = (TextView) rowView.findViewById(R.id.artistLabel);
textView.setText(name);
}
}
Now the adapter only has to call the right methods to fill the view for the selected item.
public class MySimpleArrayAdapter extends ArrayAdapter<MyListItem> {
private final Context context;
private final MyListItem[] values;
public MySimpleArrayAdapter(Context context, MyListItem[] values) {
super(context, android.R.layout.simple_list_item_1, values);
this.context = context;
this.values = values;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
MyListItem item = values[position];
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(item.getLayout(), parent, false);
item.bindTo(view);
return view;
}
}

Categories