There is a situation, I have an activity having recycler view and I have its adapter, there is a model class for three Text Views of a recycler view location,latitude,longitude that comes from database. Now I want the fourth field of recycler view the distance. distance is calculated by another class and return distance in a callback function. where do I initialize the object of that class in recyclerview so that it updates the distance continuously against the lat and long of each item.
Code that return distance for single lat,long
compassManager = new CompassManager(getApplicationContext(), this);
if (isLocationServiceEnabled()) {
Log.i("FloatingViewServie","Location Service Enabled");
// i want to pass latitude and longitude of UserLocations below to
// get distance on each row
compassManager.startNavigating(33.69206669, 73.03208828);
compassManager.getLocation().getLatitude();
compassManager.getLocation().getLongitude();
}
callback method that return continusly updated distance
#Override
public void onDistanceUpdate(float distance) {
//this distance need to be on recyclerview for each row
}
Recyclerview Adapter
public class ActiveLocationsAdapter extends RecyclerView.Adapter<ActiveLocationsAdapter.MyViewHolder> {
public interface OverflowOptions
{
public void edit(int position,UserLocations userLocations);
public void delete();
}
private List<UserLocations> userLocationsList;
FirebaseDatabase database;
DatabaseReference rootRef;
private FirebaseAuth mAuth;
FirebaseUser user;
Context context;
OverflowOptions overflowOptionsCallback;
public ActiveLocationsAdapter(Context context,List<UserLocations> locationsList,OverflowOptions callback) {
this.userLocationsList = locationsList;
database = FirebaseDatabase.getInstance();
rootRef = database.getReference();
mAuth = FirebaseAuth.getInstance();
user = mAuth.getCurrentUser();
this.context=context;
overflowOptionsCallback=callback;
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.row_active_locations, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, int position) {
// model class that have latitude and longitude for each row
final UserLocations userLocations = userLocationsList.get(position);
Log.i("aaposition",String.valueOf(holder.getAdapterPosition()));
holder.name.setText(userLocations.getName());
// holder.distance.setText(String.valueOf(userLocations.getLatitude()));
// holder.direction.setText(String.valueOf(userLocations.getLongitude()));
holder.overflow.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//creating a popup menu
PopupMenu popup = new PopupMenu(context, holder.overflow);
//inflating menu from xml resource
popup.inflate(R.menu.locations_overflow_menu);
//adding click listener
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
#Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_edit:
overflowOptionsCallback.edit(holder.getAdapterPosition(), userLocations);
break;
case R.id.action_delete:
break;
}
return false;
}
});
//displaying the popup
popup.show();
}
});
}
#Override
public int getItemCount() {
return userLocationsList.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
public TextView name, distance, direction;
public ImageView overflow;
public MyViewHolder(View view) {
super(view);
name = (TextView) view.findViewById(R.id.name);
distance = (TextView) view.findViewById(R.id.distance);
direction = (TextView) view.findViewById(R.id.direction);
overflow = (ImageView) view.findViewById(R.id.overflow);
}
}
}
Model Class
public class UserLocations {
String id;
String name;
double latitude;
double longitude;
String status;
public UserLocations() {
}
public UserLocations(String id, String name, double latitude, double longitude, String status) {
this.id=id;
this.name = name;
this.latitude = latitude;
this.longitude = longitude;
this.status = status;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
public String getStatus() {return status;}
public void setStatus(String status) {this.status = status;}
}
Row of Recyclerview
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:focusable="true"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:paddingTop="10dp"
android:paddingBottom="10dp"
android:clickable="true"
android:background="?android:attr/selectableItemBackground"
android:orientation="vertical">
<TextView
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:textColor="#color/heading"
android:textSize="16dp"
android:textStyle="bold" />
<TextView
android:id="#+id/distance_lable"
android:layout_below="#id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/subheading"
android:text="Distance : "/>
<!-- To display distance-->
<TextView
android:id="#+id/distance"
android:layout_below="#id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/subheading"
android:layout_toRightOf="#+id/distance_lable"
/>
<TextView
android:layout_below="#id/name"
android:id="#+id/direction_lable"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#id/distance"
android:textColor="#color/subheading"
android:text=" Direction : "/>
<!-- To display direction-->
<TextView
android:id="#+id/direction"
android:layout_below="#id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textColor="#color/subheading"
android:layout_toEndOf="#+id/direction_lable"/>
<ImageButton
android:id="#+id/overflow"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_marginRight="5dp"
android:background="#drawable/ic_more_vert_black_24dp"
/>
</RelativeLayout>
Main Activity that have recyclerview
public class MainActivity extends AppCompatActivity
implements CurrentLocationManager.ResultSupplier,NavigationView.OnNavigationItemSelectedListener,ActiveLocationsAdapter.OverflowOptions{
private static final int CODE_DRAW_OVER_OTHER_APP_PERMISSION = 2084;
public static final int REQUEST_FINE_LOCATION = 1;
public static final String TAG= MainActivity.class.getSimpleName();
private PrefManager prefManager;
CurrentLocationManager currentLocationManager;;
private List<UserLocations> userLocationsList = new ArrayList<>();
private RecyclerView recyclerView;
private ActiveLocationsAdapter mAdapter;
FirebaseDatabase database;
DatabaseReference rootRef;
private FirebaseAuth mAuth;
FirebaseUser user;
ProgressDialog progressDoalog;
Context context,interfaceContext;
ImageButton imgBtnSaveLocation;
private double lattitude,longitude;
Switch toggle;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkPermissions(this);
permissionCheck();
context=getApplicationContext();
imgBtnSaveLocation=(ImageButton)findViewById(R.id.main_activity_save_btn) ;
progressDoalog = new ProgressDialog(MainActivity.this);
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
toggle=(Switch)findViewById(R.id.active_locations_switch);
mAdapter = new ActiveLocationsAdapter(getApplicationContext(),userLocationsList,this);
prefManager = new PrefManager(this);
prefManager.setFirstTimeLaunch(false);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
//database reference pointing to root of database
database = FirebaseDatabase.getInstance();
rootRef = database.getReference();
// gives current authenticated user
mAuth = FirebaseAuth.getInstance();
user = mAuth.getCurrentUser();
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
recyclerView.setAdapter(mAdapter);
progressDoalog.setMessage("Fetching Data. . .");
progressDoalog.show();
// get and update data on View on any change in database
rootRef.child(user.getDisplayName()).child("active_locations").addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot noteDataSnapshot : dataSnapshot.getChildren()) {
UserLocations locations = noteDataSnapshot.getValue(UserLocations.class);
if(locations.getStatus().equals("active")) {
if (!contains((ArrayList<UserLocations>) userLocationsList, locations)) {
userLocationsList.add(locations);
}
}
}
mAdapter.notifyDataSetChanged();
progressDoalog.dismiss();
}
#Override
public void onCancelled(DatabaseError error) {
// Failed to read value
}
});
// button click that get current location and save to database
imgBtnSaveLocation.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.i(TAG,"onclick");
getLocation();
}
});
// turn the tracking on and off
toggle.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if(isChecked)
Toast.makeText(context, "Toggle on", Toast.LENGTH_SHORT).show();
else
Toast.makeText(context, "Toggle off", Toast.LENGTH_SHORT).show();
}
});
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}
public void permissionCheck()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(getApplicationContext())) {
//If the draw over permission is not available open the settings screen
//to grant the permission.
Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, CODE_DRAW_OVER_OTHER_APP_PERMISSION);
} else {
}
}
private void requestPermissions(Context context) {
ActivityCompat.requestPermissions((Activity) context,
new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION,android.Manifest.permission.ACCESS_COARSE_LOCATION},
REQUEST_FINE_LOCATION);
}
private boolean checkPermissions(Context context) {
if (ContextCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(context, android.Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
return true;
} else {
requestPermissions(context);
return false;
}
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_active_locations) {
startActivity(new Intent(getApplicationContext(),ActiveLocationsActivity.class));
} else if (id == R.id.nav_tracked_locations) {
startActivity(new Intent(getApplicationContext(),TrackedLocationsActivity.class));
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
AuthUI.getInstance()
.signOut(this)
.addOnCompleteListener(new OnCompleteListener<Void>() {
public void onComplete(#NonNull Task<Void> task) {
// user is now signed out
startActivity(new Intent(getApplicationContext(), SignUpActivity.class));
finish(); }
});
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
public void getLocation()
{
currentLocationManager = new CurrentLocationManager(context,this);
currentLocationManager.getUpdatedLocation();
}
/**
* Compares two array list
* #param list
* #param locations
* #return
*/
boolean contains(ArrayList<UserLocations> list, UserLocations locations) {
for (UserLocations item : list) {
if (item.getId().equals(locations.getId())&&item.getName().equals(locations.getName())&&item.getLatitude()==locations.getLatitude()&&item.getLongitude()==locations.getLongitude()&&item.getStatus().equals(locations.getStatus())) {
return true;
}
}
return false;
}
#Override
public void result(double lat, double longi) {
lattitude=lat;
longitude=longi;
Log.i("callback result",String.valueOf(lat)+","+String.valueOf(longi));
}
#Override
public void edit(final int position, final UserLocations userLocations) {
AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(this);
LayoutInflater inflater = this.getLayoutInflater();
final View dialogView = inflater.inflate(R.layout.dialog_edit_location_name, null);
dialogBuilder.setView(dialogView);
final EditText rename = (EditText) dialogView.findViewById(R.id.name);
dialogBuilder.setTitle("Rename Location");
//dialogBuilder.setMessage("hello");
dialogBuilder.setPositiveButton("Done", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
renameLocation(userLocations.getName(),rename.getText().toString());
userLocations.setName(rename.getText().toString());
userLocationsList.set(position, userLocations);
}
});
dialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
//pass
}
});
AlertDialog b = dialogBuilder.create();
b.show();
}
#Override
public void delete() {
}
public void renameLocation(final String name, final String renameLocation) {
Log.i("Interface","renameLocation");
Query renameQuery= rootRef.child(user.getDisplayName()).child("active_locations").orderByChild("name").equalTo(name);
renameQuery.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
for (DataSnapshot child : dataSnapshot.getChildren()) {
String child_name = (String) child.child("name").getValue();
if (child_name.equals(name)){
child.getRef().child("name").setValue(renameLocation);
Log.i("Rename Location","child renamed");
}
}
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
Related
I'm using the library Material Search Bar to search my Firebase Database, but it doesn't work.
Right here is the layout and it is assumed that when I click on the search bar should give me some suggestions and also to look for products but it is not
View
My Firebase Database
Firebase DataBase
Here is my Home.java where i put the searchBar
public class Home extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
FirebaseDatabase database;
DatabaseReference product;
TextView userName;
RecyclerView recycler_prod;
RecyclerView.LayoutManager layoutManager;
FirebaseRecyclerAdapter<Product,ProductViewHolder> adapter;
FirebaseRecyclerAdapter<Product, ProductViewHolder> searchadapter;
MaterialSearchBar searchBar;
String ProductId = "";
List<String> suggestList = new ArrayList<>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
database=FirebaseDatabase.getInstance();
product=database.getReference("Product");
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
View headerView = navigationView.getHeaderView(0);
userName= headerView.findViewById(R.id.idUserName);
userName.setText(Common.currentuser.getName());
recycler_prod = findViewById(R.id.recycler_card);
recycler_prod.setHasFixedSize(true);
layoutManager = new LinearLayoutManager(this);
recycler_prod.setLayoutManager(layoutManager);
loadProducts();
searchBar = findViewById(R.id.searchBar);
searchBar.setPlaceHolder("Productos");
loadSuggest();
searchBar.setLastSuggestions(suggestList);
searchBar.setCardViewElevation(10);
searchBar.addTextChangeListener(new TextWatcher() {
#Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
#Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
List<String> suggest = new ArrayList<String>();
for (String search : suggestList) {
if (search.toLowerCase().contains(searchBar.getText().toLowerCase()))
suggest.add(search);
}
searchBar.setLastSuggestions(suggest);
}
#Override
public void afterTextChanged(Editable s) {
}
});
searchBar.setOnSearchActionListener(new MaterialSearchBar.OnSearchActionListener() {
#Override
public void onSearchStateChanged(boolean enabled) {
if (!enabled)
recycler_prod.setAdapter(adapter);
}
#Override
public void onSearchConfirmed(CharSequence text) {
startSearch(text);
}
#Override
public void onButtonClicked(int buttonCode) {
}
});
}
private void startSearch(CharSequence text) {
searchadapter = new FirebaseRecyclerAdapter<Product, ProductViewHolder>(
Product.class,
R.layout.card_item,
ProductViewHolder.class,
product.orderByChild("Name").equalTo(text.toString())
) {
#Override
protected void populateViewHolder(ProductViewHolder viewHolder, Product model, int position) {
viewHolder.txtProductName.setText(model.getName());
Picasso.get().load(model.getImage())
.into(viewHolder.imageProductView);
final Product local = model;
viewHolder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
Intent details = new Intent(Home.this, ProductDetail.class);
details.putExtra("ProductId", searchadapter.getRef(position).getKey());
startActivity(details);
}
});
}
};
recycler_prod.setAdapter(searchadapter);
}
private void loadSuggest() {
product.orderByChild("ProductId").equalTo(ProductId)
.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for(DataSnapshot postSnapshot:dataSnapshot.getChildren()){
Product item = postSnapshot.getValue(Product.class);
suggestList.add(item.getName());
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
private void loadProducts() {
adapter = new FirebaseRecyclerAdapter<Product, ProductViewHolder>(Product.class,
R.layout.card_item,
ProductViewHolder.class,
product) {
#Override
protected void populateViewHolder(ProductViewHolder holder, Product model, int position) {
holder.txtProductName.setText(model.getName());
holder.txtProductDesc.setText(model.getDescription());
holder.txtProductPrice.setText("$" + model.getPrice());
Picasso.get().load(model.getImage())
.into(holder.imageProductView);
final Product clickItem = model;
holder.setItemClickListener(new ItemClickListener() {
#Override
public void onClick(View view, int position, boolean isLongClick) {
Intent details = new Intent(Home.this, ProductDetail.class);
details.putExtra("ProductId", adapter.getRef(position).getKey());
startActivity(details);
}
});
}
};
recycler_prod.setAdapter(adapter);
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.home, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_search) {
// Handle the camera action
} else if (id == R.id.nav_map) {
Intent mapa = new Intent(Home.this,Maps.class);
startActivity(mapa);
} else if (id == R.id.nav_log_out) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
}
My Product.java Model
public class Product {
private String Description, Name, Image,Price,Link;
public Product() {
}
public Product(String description, String name, String image, String price, String link) {
Description = description;
Name = name;
Image = image;
Price = price;
Link = link;
}
public String getLink() {
return Link;
}
public void setLink(String link) {
Link = link;
}
public String getDescription() {
return Description;
}
public void setDescription(String description) {
Description = description;
}
public String getName() {
return Name;
}
public void setName(String name) {
Name = name;
}
public String getImage() {
return Image;
}
public void setImage(String image) {
Image = image;
}
public String getPrice() {
return Price;
}
public void setPrice(String price) {
Price = price;
}
}
My ProductViewHolder.java
public class ProductViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
public TextView txtProductName,txtProductDesc,txtProductPrice;
public ImageView imageProductView;
private ItemClickListener itemClickListener;
public ProductViewHolder(#NonNull View itemView) {
super(itemView);
txtProductName = itemView.findViewById(R.id.name);
txtProductDesc = itemView.findViewById(R.id.description);
txtProductPrice = itemView.findViewById(R.id.price);
imageProductView = itemView.findViewById(R.id.thumbnail);
itemView.setOnClickListener(this);
}
public void setItemClickListener(ItemClickListener itemClickListener) {
this.itemClickListener = itemClickListener;
}
#Override
public void onClick(View v) {
itemClickListener.onClick(v,getAdapterPosition(),false);
}
}
Thank you for your attention
In your startSearch method, replace your .equalto with .startAt. See if it works
I have a navigation activity. In the file content.xml I have a recyclerview. If I put an EditText in the content.xml the recylerview is displayed, however if I do not put it it is not displayed.
I do not need the EditText field
Here are my code.
content_navegador.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:focusable="true"
tools:context="com.example.pablo.pruebasauthproyecto.Activities.Navegador"
app:layout_behavior="#string/appbar_scrolling_view_behavior"
tools:showIn="#layout/app_bar_navegador">
<EditText
android:id="#+id/search_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:hint="Buscar Proyectos..."
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<android.support.v7.widget.RecyclerView
android:focusable="true"
android:id="#+id/reciclador"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#+id/search_text" />
</android.support.constraint.ConstraintLayout>
Navegador.java
public class Navegador extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener {
public final static String PROYECTO = "proyecto";
private RecyclerView recycler;
private FirebaseUser fUsr;
private String intereses;
private String claveProy;
private ArrayList<Proyecto> proyectos = new ArrayList<>();
private ArrayList<String> listaIntereses = new ArrayList<>();
final DatabaseReference ref = FirebaseDatabase.getInstance().getReference();
Recursos r;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_navegador);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
recuperarProyectos ();
}
private void recuperarInteresesUsuario() {
fUsr = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference interesesRef = ref.child("intereses").child(fUsr.getUid());
interesesRef.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
intereses = dataSnapshot.getValue().toString();
listaIntereses.add(intereses);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void verProyecto(Proyecto proyecto) {
// Log.d("DEPURACIÓN", proyecto.toString());
Intent intent = new Intent(this, FichaProyecto.class);
intent.putExtra(this.PROYECTO, proyecto);
startActivity(intent);
}
private void cargarRecycler() {
// Obtener el Recycler
recycler = (RecyclerView) findViewById(R.id.reciclador);
recycler.setHasFixedSize(true);
ProyectosAdapter adapter = new ProyectosAdapter(proyectos);
adapter.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
// Log.d("DEPURACIÓN" , "Item Pulsado : " + proyectos.get(recycler.getChildAdapterPosition(view)).getNombre());
Proyecto prosel = proyectos.get(recycler.getChildAdapterPosition(view));
verProyecto(prosel);
}
});
recycler.setAdapter(adapter);
// Usar un administrador para LinearLayout
LinearLayoutManager lManager = new LinearLayoutManager(this);
recycler.setLayoutManager(lManager);
}
private void recuperarProyectos () {
DatabaseReference proyectosRef = ref.child("proyectos");
Query consProy = proyectosRef.orderByChild("genero");
consProy.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
claveProy = dataSnapshot.getKey();
final Proyecto p = dataSnapshot.getValue(Proyecto.class);
for (String inter : listaIntereses) {
// Log.d("DEPURACIÓN", inter);
if(p.getGenero().equalsIgnoreCase(inter)) {
// Log.d("DEPURACIÓN", p.toString());
DatabaseReference recursosRef = ref.child("recursos");
Query consRecursos = recursosRef.orderByChild("idProyecto").equalTo(claveProy);
consRecursos.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(DataSnapshot dataSnapshot, String s) {
r = dataSnapshot.getValue(Recursos.class);
// Log.d("DEPURACIÓN","PROYECTO -> " + p.toString());
p.addRecurso(r);
// Log.d("DEPURACIÓN", "RECURSOS PROYECTO -> " + p.getRecursos().toString());
proyectos.add(p);
// eliminamos elementos repetidos del ArrayList
HashSet<Proyecto> hs = new HashSet<>();
hs.addAll(proyectos);
proyectos.clear();
proyectos.addAll(hs);
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
}
}
#Override
public void onChildChanged(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onChildRemoved(DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(DataSnapshot dataSnapshot, String s) {
}
#Override
public void onCancelled(DatabaseError databaseError) {
}
});
recuperarInteresesUsuario();
cargarRecycler();
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.navegador, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.crear_proyect) {
startActivity(new Intent(Navegador.this, CrearProyecto.class));
} else if (id == R.id.nav_gallery) {
} else if (id == R.id.nav_slideshow) {
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
} else if (id == R.id.nav_send) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
} }
ProyectosAdapter.java
public class ProyectosAdapter extends
RecyclerView.Adapter implements
View.OnClickListener {
private List<Proyecto> items;
private View.OnClickListener listener;
public class ProyectosViewHolder extends RecyclerView.ViewHolder {
public ImageView imagen;
public TextView nombre;
public TextView autor;
public TextView genero;
public ProyectosViewHolder(View v) {
super(v);
imagen = (ImageView) v.findViewById(R.id.imagen);
nombre = (TextView) v.findViewById(R.id.nombre);
autor = (TextView) v.findViewById(R.id.autor);
genero = (TextView) v.findViewById(R.id.genero);
}
}
public ProyectosAdapter(List<Proyecto> items) {
this.items = items;
}
#Override
public int getItemCount() {
return items.size();
}
#Override
public ProyectosViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View v = LayoutInflater.from(viewGroup.getContext())
.inflate(R.layout.proyectos_card, viewGroup, false);
v.setOnClickListener(this);
return new ProyectosViewHolder(v);
}
#Override
public void onBindViewHolder(final ProyectosViewHolder viewHolder, int i) {
viewHolder.nombre.setText(items.get(i).getNombre());
viewHolder.autor.setText(items.get(i).getAutor());
viewHolder.genero.setText(items.get(i).getGenero());
Context context = viewHolder.imagen.getContext();
Uri uri = Uri.parse(items.get(i).getRecursos().get(0).getRuta());
Picasso.with(context)
.load(uri)
.resize(355,225)
.centerCrop()
.into(viewHolder.imagen);
}
#Override
public void onClick(View view) {
if(listener != null)
listener.onClick(view);
}
public void setOnClickListener(View.OnClickListener listener) {
this.listener = listener;
} }
Sounds like your constraints are messed up. For example your RecyclerView have toBottomOf="#+id/search_text", so it expects that edit text to present.
Try to remove EditText, and instead of that last line add app:layout_constraintTop_toTopOf="parent".
Your RecyclerView width and height is 0dp.
Try this:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="#+id/reciclador"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
Remove this line from recyclerview
app:layout_constraintTop_toBottomOf="#+id/search_text"
This is beacuse you have given top to bottom of edittext..
Change it like this:
<android.support.v7.widget.RecyclerView
android:focusable="true"
android:id="#+id/reciclador"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp" android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
Put setAdapter after setLayoutManager
I have an app that displays my e-mail via microsoft graph api.
Everything but 1 things i working fine so far. When the list first loads in, all info is correctly displayed, but when i scroll down, then back up. The imageview of the attachement sits on the wrong rows. It just displays on rows without attachement. In the adapter i have an if clausule which says to only show the image in the row if the hasAttachement value is "true".. I really don't get why it is redrawin the image in the wrongs rows..
The method where i set the attachement is called:
setBijlage() in MessagesAdapter
EDIT: If i click the row in my app, that row displays correctly again (gains an icon if it has attachement, and deletes it if it doesn't)
MailActivity.java
public class MailActivity extends AppCompatActivityRest implements SwipeRefreshLayout.OnRefreshListener, MessagesAdapter.MessageAdapterListener {
private String currentFolder;
private String currentUser;
private List<Message> messages = new ArrayList<>();
private RecyclerView recyclerView;
private MessagesAdapter mAdapter;
private SwipeRefreshLayout swipeRefreshLayout;
private ActionModeCallback actionModeCallback;
private ActionMode actionMode;
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_mail);
super.onCreate(savedInstanceState);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
currentFolder = getString(R.string.inbox);
currentUser = getIntent().getStringExtra("USER_EMAIL");
setActionBarMail(currentFolder, currentUser);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh_layout);
swipeRefreshLayout.setOnRefreshListener(this);
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(mLayoutManager);
recyclerView.setItemAnimator(new DefaultItemAnimator());
recyclerView.addItemDecoration(new DividerItemDecoration(this, LinearLayoutManager.VERTICAL));
actionModeCallback = new ActionModeCallback();
// show loader and fetch messages
swipeRefreshLayout.post(
new Runnable() {
#Override
public void run() {
getAllMails(15);
}
}
);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_search) {
Toast.makeText(getApplicationContext(), "Search...", Toast.LENGTH_SHORT).show();
return true;
}
return super.onOptionsItemSelected(item);
}
#Override
public void processResponse(OutlookObjectCall outlookObjectCall, JSONObject response) {
switch (outlookObjectCall) {
case READUSER: {
System.out.println("reading user");
} break;
case READMAIL: {
messages.clear();
JSONObject list = response;
try {
JSONArray mails = list.getJSONArray("value");
Type listType = new TypeToken<List<Message>>() {
}.getType();
messages = new Gson().fromJson(String.valueOf(mails), listType);
for (Message message : messages) {
message.setColor(getRandomMaterialColor("400"));
}
System.out.println(messages.get(2).getFrom().getEmailAddress().getName());
mAdapter = new MessagesAdapter(this, messages, this);
recyclerView.setAdapter(mAdapter);
} catch (JSONException e) {
e.printStackTrace();
}
mAdapter.notifyDataSetChanged();
swipeRefreshLayout.setRefreshing(false);
}
break;
case SENDMAIL: {
System.out.println("Just send a mail." );
}
}
}
#Override
public void onRefresh() {
// swipe refresh is performed, fetch the messages again
getAllMails(15);
}
#Override
public void onIconClicked(int position) {
if (actionMode == null) {
actionMode = startSupportActionMode(actionModeCallback);
}
toggleSelection(position);
}
#Override
public void onIconImportantClicked(int position) {
// Star icon is clicked,
// mark the message as important
Message message = messages.get(position);
message.setImportance("normal");
messages.set(position, message);
mAdapter.notifyDataSetChanged();
}
#Override
public void onMessageRowClicked(int position) {
// verify whether action mode is enabled or not
// if enabled, change the row state to activated
if (mAdapter.getSelectedItemCount() > 0) {
enableActionMode(position);
} else {
// read the message which removes bold from the row
Message message = messages.get(position);
message.setIsRead("true");
messages.set(position, message);
mAdapter.notifyDataSetChanged();
Toast.makeText(getApplicationContext(), "Read: " + message.getBodyPreview(), Toast.LENGTH_SHORT).show();
}
}
#Override
public void onRowLongClicked(int position) {
// long press is performed, enable action mode
enableActionMode(position);
}
private void enableActionMode(int position) {
if (actionMode == null) {
actionMode = startSupportActionMode(actionModeCallback);
}
toggleSelection(position);
}
private void toggleSelection(int position) {
mAdapter.toggleSelection(position);
int count = mAdapter.getSelectedItemCount();
if (count == 0) {
actionMode.finish();
} else {
actionMode.setTitle(String.valueOf(count));
actionMode.invalidate();
}
}
private class ActionModeCallback implements ActionMode.Callback {
#Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mode.getMenuInflater().inflate(R.menu.menu_action_mode, menu);
// disable swipe refresh if action mode is enabled
swipeRefreshLayout.setEnabled(false);
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
return false;
}
#Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
switch (item.getItemId()) {
case R.id.action_delete:
// delete all the selected messages
deleteMessages();
mode.finish();
return true;
default:
return false;
}
}
#Override
public void onDestroyActionMode(ActionMode mode) {
mAdapter.clearSelections();
swipeRefreshLayout.setEnabled(true);
actionMode = null;
recyclerView.post(new Runnable() {
#Override
public void run() {
mAdapter.resetAnimationIndex();
// mAdapter.notifyDataSetChanged();
}
});
}
}
// deleting the messages from recycler view
private void deleteMessages() {
mAdapter.resetAnimationIndex();
List<Integer> selectedItemPositions =
mAdapter.getSelectedItems();
for (int i = selectedItemPositions.size() - 1; i >= 0; i--) {
mAdapter.removeData(selectedItemPositions.get(i));
}
mAdapter.notifyDataSetChanged();
}
private void setActionBarMail(String title, String subtitle) {
getSupportActionBar().setTitle(title);
getSupportActionBar().setSubtitle(subtitle);
}
private void getAllMails(int aantalMails) {
swipeRefreshLayout.setRefreshing(true);
try {
new GraphAPI().getRequest(OutlookObjectCall.READMAIL, this, "/inbox/messages?$top=" + aantalMails);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
private int getRandomMaterialColor(String typeColor) {
int returnColor = Color.GRAY;
int arrayId = getResources().getIdentifier("mdcolor_" + typeColor, "array", getPackageName());
if (arrayId != 0) {
TypedArray colors = getResources().obtainTypedArray(arrayId);
int index = (int) (Math.random() * colors.length());
returnColor = colors.getColor(index, Color.GRAY);
colors.recycle();
}
return returnColor;
}
MessagesAdapter.java
public class MessagesAdapter extends RecyclerView.Adapter<MessagesAdapter.MyViewHolder> {
private Context mContext;
private List<Message> messages;
private MessageAdapterListener listener;
private SparseBooleanArray selectedItems;
// array used to perform multiple animation at once
private SparseBooleanArray animationItemsIndex;
private boolean reverseAllAnimations = false;
// index is used to animate only the selected row
// dirty fix, find a better solution
private static int currentSelectedIndex = -1;
public class MyViewHolder extends RecyclerView.ViewHolder implements View.OnLongClickListener {
public TextView from, subject, message, iconText, timestamp;
public ImageView iconImp, imgProfile, imgBijlage;
public LinearLayout messageContainer;
public RelativeLayout iconContainer, iconBack, iconFront;
public MyViewHolder(View view) {
super(view);
from = (TextView) view.findViewById(R.id.from);
subject = (TextView) view.findViewById(R.id.txt_primary);
message = (TextView) view.findViewById(R.id.txt_secondary);
iconText = (TextView) view.findViewById(R.id.icon_text);
timestamp = (TextView) view.findViewById(R.id.timestamp);
iconBack = (RelativeLayout) view.findViewById(R.id.icon_back);
iconFront = (RelativeLayout) view.findViewById(R.id.icon_front);
iconImp = (ImageView) view.findViewById(R.id.icon_star);
imgProfile = (ImageView) view.findViewById(R.id.icon_profile);
messageContainer = (LinearLayout) view.findViewById(R.id.message_container);
iconContainer = (RelativeLayout) view.findViewById(R.id.icon_container);
imgBijlage = (ImageView) view.findViewById(R.id.icon_attachement);
view.setOnLongClickListener(this);
}
#Override
public boolean onLongClick(View view) {
listener.onRowLongClicked(getAdapterPosition());
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
}
}
public MessagesAdapter(Context mContext, List<Message> messages, MessageAdapterListener listener) {
this.mContext = mContext;
this.messages = messages;
this.listener = listener;
selectedItems = new SparseBooleanArray();
animationItemsIndex = new SparseBooleanArray();
}
#Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.message_list_row, parent, false);
return new MyViewHolder(itemView);
}
#Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
Message message = messages.get(position);
// displaying text view data
holder.from.setText(message.getFrom().getEmailAddress().getName());
holder.subject.setText(message.getSubject());
holder.message.setText(message.getBodyPreview());
System.out.println("EMAIL: " + position + " HAS ATTACHEMENT: " + message.getHasAttachments());
setBijlage(message, holder);
try {
setDate(message, holder);
} catch (ParseException e) {
e.printStackTrace();
}
// displaying the first letter of From in icon text
holder.iconText.setText(message.getFrom().getEmailAddress().getName().substring(0, 1));
// change the row state to activated
holder.itemView.setActivated(selectedItems.get(position, false));
// change the font style depending on message read status
applyReadStatus(holder, message);
// handle message star
applyImportant(holder, message);
// handle icon animation
applyIconAnimation(holder, position);
// display profile image
applyProfilePicture(holder, message);
// apply click events
applyClickEvents(holder, position);
}
private void setDate(Message message, MyViewHolder holder) throws ParseException {
String stringDate = message.getReceivedDateTime();
String COMPARE_FORMAT = "yyyy/MM/dd";
String OUTPUT_FORMAT_NOT_TODAY = "dd MMM";
String JSON_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
SimpleDateFormat dateFormat = new SimpleDateFormat(COMPARE_FORMAT);
SimpleDateFormat formatter = new SimpleDateFormat(JSON_FORMAT);
SimpleDateFormat defaultFormat = new SimpleDateFormat(OUTPUT_FORMAT_NOT_TODAY);
//today date (check if today)
Date today = new Date();
String currentDate = dateFormat.format(today);
//hours (if today
Date date = formatter.parse(stringDate);
formatter.applyPattern(COMPARE_FORMAT);
String mailDate = formatter.format(date);
//dd/month (if not today)
boolean is24 = DateFormat.is24HourFormat(mContext);
if (mailDate.equals(currentDate)) {
if (is24) {
SimpleDateFormat outputFormat = new SimpleDateFormat("HH:mm");
holder.timestamp.setText(outputFormat.format(date));
} else {
SimpleDateFormat outputFormat = new SimpleDateFormat("hh:mm a");
holder.timestamp.setText(outputFormat.format(date));
}
} else {
holder.timestamp.setText(defaultFormat.format(date));
}
}
private void setBijlage(Message message, MyViewHolder holder){
//set bijlage
if (message.getHasAttachments().toLowerCase().equals("true")){
holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
}
}
private void applyClickEvents(MyViewHolder holder, final int position) {
holder.iconContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.onIconClicked(position);
}
});
holder.iconImp.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.onIconImportantClicked(position);
}
});
holder.messageContainer.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
listener.onMessageRowClicked(position);
}
});
holder.messageContainer.setOnLongClickListener(new View.OnLongClickListener() {
#Override
public boolean onLongClick(View view) {
listener.onRowLongClicked(position);
view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
return true;
}
});
}
private void applyProfilePicture(MyViewHolder holder, Message message) {
holder.imgProfile.setImageResource(R.drawable.bg_circle);
holder.imgProfile.setColorFilter(message.getColor());
holder.iconText.setVisibility(View.VISIBLE);
}
private void applyIconAnimation(MyViewHolder holder, int position) {
if (selectedItems.get(position, false)) {
holder.iconFront.setVisibility(View.GONE);
resetIconYAxis(holder.iconBack);
holder.iconBack.setVisibility(View.VISIBLE);
holder.iconBack.setAlpha(1);
if (currentSelectedIndex == position) {
FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, true);
resetCurrentIndex();
}
} else {
holder.iconBack.setVisibility(View.GONE);
resetIconYAxis(holder.iconFront);
holder.iconFront.setVisibility(View.VISIBLE);
holder.iconFront.setAlpha(1);
if ((reverseAllAnimations && animationItemsIndex.get(position, false)) || currentSelectedIndex == position) {
FlipAnimator.flipView(mContext, holder.iconBack, holder.iconFront, false);
resetCurrentIndex();
}
}
}
// As the views will be reused, sometimes the icon appears as
// flipped because older view is reused. Reset the Y-axis to 0
private void resetIconYAxis(View view) {
if (view.getRotationY() != 0) {
view.setRotationY(0);
}
}
public void resetAnimationIndex() {
reverseAllAnimations = false;
animationItemsIndex.clear();
}
#Override
public long getItemId(int position) {
return messages.get(position).getAutoId();
}
private void applyImportant(MyViewHolder holder, Message message) {
if (message.getImportance().toLowerCase().equals("high")) {
holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_black_24dp));
holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_selected));
} else {
holder.iconImp.setImageDrawable(ContextCompat.getDrawable(mContext, R.drawable.ic_star_border_black_24dp));
holder.iconImp.setColorFilter(ContextCompat.getColor(mContext, R.color.icon_tint_normal));
}
}
private void applyReadStatus(MyViewHolder holder, Message message) {
if (message.getIsRead().toLowerCase().equals("true")) {
holder.from.setTypeface(null, Typeface.NORMAL);
holder.subject.setTypeface(null, Typeface.NORMAL);
holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.message));
} else {
holder.from.setTypeface(null, Typeface.BOLD);
holder.subject.setTypeface(null, Typeface.BOLD);
holder.from.setTextColor(ContextCompat.getColor(mContext, R.color.from));
holder.subject.setTextColor(ContextCompat.getColor(mContext, R.color.subject));
}
}
#Override
public int getItemCount() {
return messages.size();
}
public void toggleSelection(int pos) {
currentSelectedIndex = pos;
if (selectedItems.get(pos, false)) {
selectedItems.delete(pos);
animationItemsIndex.delete(pos);
} else {
selectedItems.put(pos, true);
animationItemsIndex.put(pos, true);
}
notifyItemChanged(pos);
}
public void clearSelections() {
reverseAllAnimations = true;
selectedItems.clear();
notifyDataSetChanged();
}
public int getSelectedItemCount() {
return selectedItems.size();
}
public List<Integer> getSelectedItems() {
List<Integer> items =
new ArrayList<>(selectedItems.size());
for (int i = 0; i < selectedItems.size(); i++) {
items.add(selectedItems.keyAt(i));
}
return items;
}
public void removeData(int position) {
messages.remove(position);
resetCurrentIndex();
}
private void resetCurrentIndex() {
currentSelectedIndex = -1;
}
public interface MessageAdapterListener {
void onIconClicked(int position);
void onIconImportantClicked(int position);
void onMessageRowClicked(int position);
void onRowLongClicked(int position);
}
}
Change setBijlage to this..
private void setBijlage(Message message, MyViewHolder holder){
//set bijlage
if (message.getHasAttachments().toLowerCase().equals("true")){
holder.imgBijlage.setVisibility(View.VISIBLE);
holder.imgBijlage.setImageResource(R.drawable.ic_bijlage);
}else{
holder.imgBijlage.setVisibility(View.GONE);
}
}
That's occours because the recyclerView reuses the references of the rows and in your case, some rows doesnt have any reference in holder.imgBijlage, causing missbehavior.
To solve this, put holder.imgBijlage.setImageResource(R.drawable.ic_bijlage); inside onBindViewHolder and change setBijlage to:
if (message.getHasAttachments().toLowerCase().equals("true")){
holder.imgBijlage.setVisibility(View.VISIBLE);
}else {
holder.imgBijlage.setVisibility(View.INVISIBLE);
}
Your icon will be hidden when there is no attachement
i am building a simple recycle view with a custom adapter, i already set the position of all of my elements, but somehow the image of my row the main one is not showing up and i don't know why.
Before i changed the xml it was showing up, so basicly i have my main activity:
public class PlantFeed extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener,PlantFeedAdapter.OnItemClickListener {
//initialize fields
String token;
ArrayList<PlantPhotoUser> photos = new ArrayList<>();
VolleyService mVolleyService;
IResult mResultCallback = null;
final String GETREQUEST = "GETCALL";
String connectionTxt;
String URL;
String date;
String lat;
String lon;
String alt;
PlantFeedAdapter plantFeedAdapter;
RecyclerView recyclerView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_plant_feed);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
connectionString connection = ((connectionString) getApplicationContext());
connectionTxt = connection.getGlobalVarValue();
URL = connectionTxt + "/fotos";
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent i = new Intent(PlantFeed.this,CameraCapture.class);
startActivity(i);
}
});
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
recyclerView = (RecyclerView)findViewById(R.id.recycleView2);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
plantFeedAdapter = new PlantFeedAdapter(getApplicationContext(), photos,PlantFeed.this);
recyclerView.setAdapter(plantFeedAdapter);
token = checkForToken();
initVolleyCallback();
mVolleyService = new VolleyService(mResultCallback,this);
mVolleyService.getDataVolley(GETREQUEST,URL,token);
}
void initVolleyCallback(){
mResultCallback = new IResult() {
#Override
public void notifySuccess(String requestType,JSONObject response) {
Log.d("HELLL","hi1");
}
#Override
public void notifySuccess(String requestType, JSONArray response) {
PlantPhotoUser plantPhotoUser;
Log.d("HELLLL","hi");
for (int i=0; i < response.length(); i++) {
try {
JSONObject object = response.getJSONObject(i);
Log.d("objeto",object.toString());
int userId = object.getInt("userId");
Log.d("objeto",String.valueOf(userId));
String username = object.getJSONObject("user").getString("username");
Log.d("objeto",String.valueOf(username));
int plantId = object.getInt("plantId");
Log.d("objeto",String.valueOf(plantId));
String specie = object.getJSONObject("plant").getString("specie");
Log.d("objeto",String.valueOf(specie));
String path = object.getString("image");
Log.d("objeto",String.valueOf(path));
int fotoId = object.getInt("id");
if(object.getString("date") != null){
date = object.getString("date");
}
if(object.getString("lat") != null){
lat = object.getString("lat");
}
if(object.getString("lon") != null){
lon = object.getString("lon");
}
if(object.getString("altitude") != null){
alt = object.getString("altitude");
}
plantPhotoUser = new PlantPhotoUser(fotoId,plantId,userId,path,specie,date,lat,lon,alt,username);
photos.add(plantPhotoUser);
} catch (JSONException e) {
e.printStackTrace();
}
}
plantFeedAdapter.notifyDataSetChanged();
}
#Override
public void notifyError(String requestType,VolleyError error) {
Log.d("FAIL",error.toString());
}
};
}
public String checkForToken() {
SharedPreferences sharedPref = getSharedPreferences("user", MODE_PRIVATE);
String tokenKey = getResources().getString(R.string.token);
String token = sharedPref.getString(getString(R.string.token), tokenKey); // take the token
return token;
}
#Override
public void onBackPressed() {
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.plant_feed, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.Perfil) {
return true;
}
return super.onOptionsItemSelected(item);
}
#SuppressWarnings("StatementWithEmptyBody")
#Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();
if (id == R.id.nav_camera) {
Intent i = new Intent(PlantFeed.this,CameraCapture.class);
startActivity(i);
} else if (id == R.id.nav_gallery) {
Intent i = new Intent(PlantFeed.this,PlantFeed.class);
startActivity(i);
} else if (id == R.id.nav_slideshow) {
Intent i = new Intent(PlantFeed.this,FamilyLibrary.class);
startActivity(i);
} else if (id == R.id.nav_manage) {
} else if (id == R.id.nav_share) {
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
#Override
public void onRowClick(int position, String name, int id, View view) {
}
#Override
public void onTitleClicked(int position, int id, View clickedview) {
Intent i = new Intent(this,PhotosForPlant.class);
i.putExtra("plantId",String.valueOf(id));
startActivity(i);
}
#Override
public void onImageClicked(int position, int id, View clickedview) {
Intent i = new Intent(this,PhotosForPlant.class);
i.putExtra("plantId",String.valueOf(id));
startActivity(i);
}
#Override
public void onReportClicked(int position, int id, String name, View clickedview) {
Log.d("HELLLO","HELLOO");
showDialogReport(id,name);
}
#Override
public void onUserIconClicked(int position, int id, View clickedview) {
Intent i = new Intent(this,UserProfile.class);
i.putExtra("userId",id);
startActivity(i);
}
#Override
public void onUsernameClicked(int position, int id, View clickedview) {
Intent i = new Intent(this,UserProfile.class);
i.putExtra("userId",id);
startActivity(i);
}
#Override
public void onAvaliationClicked(int position, int id, String name, View clickedview) {
}
private void showDialogReport(int id, String name) {
Log.d("HELLLO","HELLOO");
AlertDialog.Builder builder = new AlertDialog.Builder(PlantFeed.this);
builder.setTitle(name);
builder.setMessage("Tem a certeza que pretende reportar a fotografia?");
builder.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
//TODO reportar base de dados
}
});
builder.setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
AlertDialog dialog = builder.create();
dialog.show();
}
}
and then i have my customer adapter like this:
public class PlantFeedAdapter extends RecyclerView.Adapter<PlantFeedAdapter.ViewHolder> {
private OnItemClickListener listener;
public interface OnItemClickListener {
void onRowClick(int position, String name, int id, View view);
void onTitleClicked(int position, int id, View clickedview);
void onImageClicked(int position,int id, View clickedview);
void onReportClicked(int position, int id,String name, View clickedview);
void onUserIconClicked(int position, int id, View clickedview);
void onUsernameClicked(int position, int id, View clickedview);
void onAvaliationClicked(int position, int id,String name, View clickedview);
}
private ArrayList<PlantPhotoUser> photos;
private Context context;
public PlantFeedAdapter(Context context, ArrayList<PlantPhotoUser> photos, OnItemClickListener listener) {
this.photos = photos;
this.context = context;
this.listener = listener;
}
#Override
public PlantFeedAdapter.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
View view = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.plant_feed_row, viewGroup, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(final PlantFeedAdapter.ViewHolder viewHolder, final int i) {
viewHolder.name.setText(photos.get(i).getSpecie());
viewHolder.username.setText(photos.get(i).getUsernName());
viewHolder.data.setText(photos.get(i).getDate().split("T")[0]);
Log.d("data123",(photos.get(i).getDate().toString()));
String urlFoto = "http://fe1b7efd.ngrok.io/" + photos.get(i).getPath();
if(urlFoto.toLowerCase().contains("public/")){
urlFoto = urlFoto.replace("public/","");
}
viewHolder.userIcon.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
listener.onUserIconClicked(viewHolder.getAdapterPosition(), photos.get(i).getUserId(), view);
}
}
});
viewHolder.username.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
listener.onUsernameClicked(viewHolder.getAdapterPosition(),photos.get(i).getUserId(), view);
}
}
});
viewHolder.plantImg.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
if (listener != null) {
listener.onImageClicked(viewHolder.getAdapterPosition(), photos.get(i).getIdPlant(), view);
}
}
});
viewHolder.name.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null){
listener.onTitleClicked(viewHolder.getAdapterPosition(),photos.get(i).getIdPlant(),v);
}
}
});
viewHolder.reportImage.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null){
listener.onReportClicked(viewHolder.getAdapterPosition(),photos.get(i).getIdPlant(),photos.get(i).getSpecie(),v);
}
}
});
/*viewHolder.avaliationFoto.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
if(listener != null){
listener.onAvaliationClicked(viewHolder.getAdapterPosition(),photos.get(i).getIdPlant(),photos.get(i).getSpecie(),v);
}
}
});*/
Picasso.with(context)
.load(urlFoto)
.resize(300, 300)
.into(viewHolder.plantImg);
}
#Override
public int getItemCount() {
return photos.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
private TextView name;
private ImageView userIcon;
private TextView avaliationFoto;
private ImageView plantImg;
private ImageView foto;
private TextView username;
private ImageView reportImage;
private TextView data;
public ViewHolder(View view) {
super(view);
data = (TextView)view.findViewById(R.id.data);
name = (TextView) view.findViewById(R.id.plantName);
userIcon = (ImageView)view.findViewById(R.id.userIcon);
plantImg = (ImageView)view.findViewById(R.id.plantPhoto);;
username = (TextView)view.findViewById(R.id.password);
reportImage = (ImageView)view.findViewById(R.id.cameraForbiden);
}
}
}
finally my row xml, wher i think there is the problem
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="#cfcfcf">
<LinearLayout
android:layout_margin="10dp"
android:background="#ffffff"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.android.volley.toolbox.NetworkImageView
android:layout_weight="1"
android:layout_width="120dp"
android:layout_height="100dp"
android:padding="0dp"
app:srcCompat="#mipmap/ic_launcher"
android:id="#+id/plantPhoto"
android:background="#c7c7c7"
/>
<LinearLayout
android:layout_weight="20"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/plantName"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="right"
android:padding="15dp"
android:text="TextView"
android:textColor="#000"
android:textSize="20dp" />
<ImageView
android:id="#+id/starIcon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="15dp"
android:gravity="right"
android:src="#drawable/ic_star" />
</RelativeLayout>
<RelativeLayout
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:padding="15dp">
<com.example.afcosta.inesctec.pt.android.Helpers.NexusBoldTextView
android:id="#+id/data"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toStartOf="#+id/cameraForbiden"
android:text="TextView"
android:textColor="#color/base" />
<ImageView
android:id="#+id/cameraForbiden"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_alignParentEnd="true"
android:src="#drawable/ic_no_photos" />
<ImageView
android:id="#+id/userIcon"
android:layout_width="15dp"
android:layout_height="15dp"
android:gravity="left"
android:layout_alignParentBottom="true"
android:src="#drawable/ic_user" />
<com.example.afcosta.inesctec.pt.android.Helpers.NexusBoldTextView
android:id="#+id/password"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="#+id/userIcon"
android:text="Filipe"
android:textColor="#color/base" />
</RelativeLayout>
</LinearLayout>
</LinearLayout>
the problem is on this element:
<com.android.volley.toolbox.NetworkImageView
android:layout_weight="1"
android:layout_width="120dp"
android:layout_height="100dp"
android:padding="0dp"
app:srcCompat="#mipmap/ic_launcher"
android:id="#+id/plantPhoto"
android:background="#c7c7c7"
/>
Add centerCrop() with Picasso
Picasso.with(context)
.load(url)
.resize(50, 50)
.centerCrop()
.into(imageView)
Change this lines in Your Adapter and in ViewHolder because type cast is wrong. :
private ImageView plantImg;
plantImg = (ImageView)view.findViewById(R.id.plantPhoto);;
to
private NetworkImageView plantImg;
plantImg= (NetworkImageView) findViewById(R.id
.plantPhoto); then set image .
Edit
`private ImageLoader mImageLoader;
mImageLoader = CustomVolleyRequestQueue.getInstance(this.getApplicationContext())
.getImageLoader();
mImageLoader.get(url, ImageLoader.getImageListener(mNetworkImageView,
R.mipmap.truiton_short, android.R.drawable
.ic_dialog_alert));
mNetworkImageView.setImageUrl(url, mImageLoader);`
use this link http://www.truiton.com/2015/03/android-volley-imageloader-networkimageview-example/ for further guide.
I'm trying to change the icon of a button in my recycler view every time the activity starts based off a boolean value in my custom object. I assume this has to be done within the adapter since not every groups button will have the same background.
Below is the code for my recycler view adapter:
public class RecipeListAdapter extends RecyclerView.Adapter<RecipeListAdapter.ViewHolder>{
private List<Recipe> mRecipeSet;
private Button mAddToGroceriesButton;
public RecipeListAdapter(List<Recipe> recipes){
mRecipeSet = recipes;
}
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
//This is what will handle what happens when you click a recipe in the recycler view
private TextView mRecipeName;
private TextView mPrepTime;
private TextView mCookTime;
private TextView mServingSize;
private RelativeLayout mRecipeTextSection;
public ViewHolder(View v) {
super(v);
mRecipeName = (TextView) v.findViewById(R.id.recipe_list_recycler_view_recipe_name);
mServingSize = (TextView) v.findViewById(R.id.recipe_list_recycler_view_serving_size);
mPrepTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_prep_time);
mCookTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_cook_time);
mRecipeTextSection = (RelativeLayout) v.findViewById(R.id.recycled_item_section_view);
mRecipeTextSection.setOnClickListener(this);
mAddToGroceriesButton = (Button) v.findViewById(R.id.add_to_grocery_list);
mAddToGroceriesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Recipe recipeToGrocery = mRecipeSet.get(position);
//RecipeDB dbHelper = new RecipeDB(v.getContext());
//dbHelper.addGroceryItem(recipeToGrocery);
if(!recipeToGrocery.isInList()) {
RecipeDB dbHelper = new RecipeDB(v.getContext());
dbHelper.addGroceryItem(recipeToGrocery);
recipeToGrocery.setInList(true);
dbHelper.updateRecipe(recipeToGrocery);
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
Toast.makeText(v.getContext(), recipeToGrocery.getRecipeName() + " added to grocery list.", Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(v.getContext(), "That recipe is already in the list.", Toast.LENGTH_SHORT).show();
}
}
});
}
#Override
public void onClick(View v){
int position = getAdapterPosition();
Intent i = new Intent(v.getContext(), RecipeTextView.class);
Recipe selectedRecipe = mRecipeSet.get(position);
i.putExtra("view_recipe_key", selectedRecipe);
v.getContext().startActivity(i);
}
}
public void add(int position, Recipe item) {
mRecipeSet.add(position, item);
notifyItemInserted(position);
}
public void remove(Recipe item) {
int position = mRecipeSet.indexOf(item);
mRecipeSet.remove(position);
notifyItemRemoved(position);
}
public RecipeListAdapter(ArrayList<Recipe> myRecipeset) {
mRecipeSet = myRecipeset;
}
// Create new views (invoked by the layout manager)
#Override
public RecipeListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recipe_item_recycled, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Recipe recipe = mRecipeSet.get(position);
String recipeName = recipe.getRecipeName();
String prepTime = "Prep Time: " + String.valueOf(recipe.getPrepTime()) + " minutes";
String cookTime = "Cook Time: " + String.valueOf(recipe.getCookTime()) + " minutes";
String servingSize = "Servings: " + String.valueOf(recipe.getServings());
holder.mRecipeName.setText(recipeName);
//Only display values if they are not null
if(recipe.getServings() != null) {
holder.mServingSize.setText(servingSize);
}
if (recipe.getPrepTime() != null) {
holder.mPrepTime.setText(prepTime);
}
if(recipe.getCookTime() != null) {
holder.mCookTime.setText(cookTime);
}
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
if(mRecipeSet != null) {
return mRecipeSet.size();
}
return 0;
}
}
I know how to change the background of the button when it's clicked with
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
but it's obviously not going to save the state of that button when the activity restarts. I'm just not sure of how to check the boolean value for each group upon activity start up and change the button background accordingly.
I tried using
if(recipe.isInList()){
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
}
in the onBindViewHolder method but it didn't do anything, and I'm pretty sure that wouldn't be the correct place for it anyways. I know the boolean is working properly since I use it in other places and it works fine.
Here's the relevant XML code:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/apk/res/android"
android:layout_margin="7dp"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="10dp"
android:id="#+id/recycled_item_section_view"
android:elevation="30dp"
android:background="#drawable/background_border"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:text="Recipe name"
android:textSize="24dp"
android:textColor="#color/black"
android:id="#+id/recipe_list_recycler_view_recipe_name"
android:paddingBottom="3dp"
android:maxWidth="275dip"
android:singleLine="false"/>
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="18dp"
android:textColor="#color/black"
android:layout_below="#id/recipe_list_recycler_view_recipe_name"
android:id="#+id/recipe_list_recycler_view_serving_size"
android:paddingBottom="3dp"/>
<Button
android:layout_width="35dp"
android:layout_height="35dp"
android:background="#mipmap/ic_playlist_add_black_24dp"
android:height="36dp"
android:padding="8dp"
android:layout_alignParentRight="true"
android:id="#+id/add_to_grocery_list"
android:layout_alignParentTop="true"
android:layout_alignParentEnd="true"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/recipe_list_recycler_view_serving_size"
android:layout_alignParentLeft="true"
android:textSize="18dp"
android:textColor="#color/black"
android:id="#+id/recipe_list_recycler_view_prep_time"
android:paddingBottom="3dp"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/recipe_list_recycler_view_prep_time"
android:textSize="18dp"
android:textColor="#color/black"
android:layout_alignParentLeft="true"
android:id="#+id/recipe_list_recycler_view_cook_time"/>
</RelativeLayout>
Recipe class:
public class Recipe implements Parcelable {
//These are all of the qualities a recipe contains, we will create an arraylist of this in the activity
private String mRecipeName;
private int mID;
private String mServings;
private String mPrepTime;
private String mCookTime;
private boolean isInList;
private List<String> mIngredients;
private List<String> mDirections;
public Recipe(){
}
public Recipe(int id, String name, String serving, String prep, String cook, List<String>
ingredientsList, List<String> directionsList, boolean inList){
this.mID = id;
this.mRecipeName = name;
this.mServings = serving;
this.mPrepTime = prep;
this.mCookTime = cook;
this.mIngredients = ingredientsList;
this.mDirections = directionsList;
this.isInList = inList;
}
public Recipe(String name, String serving, String prep, String cook, List<String>
ingredientsList, List<String> directionsList, boolean inList){
this.mRecipeName = name;
this.mServings = serving;
this.mPrepTime = prep;
this.mCookTime = cook;
this.mIngredients = ingredientsList;
this.mDirections = directionsList;
this.isInList = inList;
}
public String getRecipeName() {
return mRecipeName;
}
public int getID() {
return mID;
}
public void setID(int id){
mID = id;
}
public String getServings() {
return mServings;
}
public String getPrepTime() {
return mPrepTime;
}
public void setRecipeName(String recipeName) {
mRecipeName = recipeName;
}
public void setServingSize(String servings) {
mServings = servings;
}
public void setPrepTime(String prepTime) {
mPrepTime = prepTime;
}
public void setServings(String servings) {
mServings = servings;
}
public List<String> getIngredients() {
return mIngredients;
}
public List<String> getDirections() {
return mDirections;
}
public String getCookTime() {
return mCookTime;
}
public void setCookTime(String cookTime) {
mCookTime = cookTime;
}
public void setIngredients(List<String> ingredients) {
mIngredients = ingredients;
}
public void setDirections(List<String> directions) {
mDirections = directions;
}
public boolean isInList() {
return isInList;
}
public void setInList(boolean inList) {
isInList = inList;
}
#Override
public int describeContents() {
return 0;
}
#Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.mRecipeName);
dest.writeInt(this.mID);
dest.writeString(this.mServings);
dest.writeString(this.mPrepTime);
dest.writeString(this.mCookTime);
dest.writeByte(this.isInList ? (byte) 1 : (byte) 0);
dest.writeStringList(this.mIngredients);
dest.writeStringList(this.mDirections);
}
protected Recipe(Parcel in) {
this.mRecipeName = in.readString();
this.mID = in.readInt();
this.mServings = in.readString();
this.mPrepTime = in.readString();
this.mCookTime = in.readString();
this.isInList = in.readByte() != 0;
this.mIngredients = in.createStringArrayList();
this.mDirections = in.createStringArrayList();
}
public static final Creator<Recipe> CREATOR = new Creator<Recipe>() {
#Override
public Recipe createFromParcel(Parcel source) {
return new Recipe(source);
}
#Override
public Recipe[] newArray(int size) {
return new Recipe[size];
}
};
}
And main activity class that uses the adapter:
public class RecipeList extends AppCompatActivity{
private RecyclerView mRecyclerView;
private RecyclerView.Adapter mAdapter;
private RecyclerView.LayoutManager mLayoutManager;
private int REQUEST_CODE=1;
private Button mNavigateGroceryButton;
RecipeDB dbHelper = new RecipeDB(this);
List<Recipe> recipes;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
recipes = dbHelper.getAllRecipes();
setContentView(R.layout.activity_recipe_list);
mRecyclerView = (RecyclerView) findViewById(R.id.list_recycler_view);
mLayoutManager = new LinearLayoutManager(this);
mRecyclerView.setLayoutManager(mLayoutManager);
mAdapter = new RecipeListAdapter(recipes);
mRecyclerView.setAdapter(mAdapter);
mNavigateGroceryButton = (Button) findViewById(R.id.navigate_to_groceries_button_list_view);
mNavigateGroceryButton.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View v){
Intent i = new Intent(RecipeList.this, ExpandableListViewActivity.class);
//Log.d("Navigate", "navigate pressed" );
startActivity(i);
}
});
}
#Override
public void onBackPressed() {
}
public boolean onOptionsItemSelected(MenuItem item){
//Handles menu buttons
switch (item.getItemId()){
case R.id.recipe_list_add_recipe_actionbar_button:
//This button creates a new empty Recipe object and passes it to the EditRecipe class
//The Recipe object is passed as a parcelable
Recipe passedRecipe = new Recipe();
Intent i = new Intent(RecipeList.this, EditRecipe.class);
i.putExtra("passed_recipe_key", (Parcelable) passedRecipe);
startActivityForResult(i, REQUEST_CODE);
return true;
default:
Log.d("Name,", "default called");
return super.onOptionsItemSelected(item);
}
}
public void addNewReRecipe(Recipe recipe){
dbHelper.addRecipe(recipe);
recipes = dbHelper.getAllRecipes();
mAdapter = new RecipeListAdapter(recipes);
mRecyclerView.setAdapter(mAdapter);
}
//Makes the menu bar appear as it is in the action_bar_recipe_list_buttons menu layout file
#Override
public boolean onCreateOptionsMenu(Menu menu){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.action_bar_recipe_list_buttons, menu);
return true;
}
//This code is called after creating a new recipe. This is only for creating, and not editing.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data){
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE){
if(resultCode == Activity.RESULT_OK) {
Recipe createdRecipe = data.getExtras().getParcelable("recipe_key");
addNewReRecipe(createdRecipe);
}
}
}
}
Looks like you need to declare your button at the top of your ViewHolder with your other views. So move the declaration from the top of your adapter:
private Button mAddToGroceriesButton;
Then in your onBindViewHolder method you can get a reference to your button through the holder and set the background:
if(recipe.isInList()) {
holder.mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
}
Try this,
public class RecipeListAdapter extends RecyclerView.Adapter<RecipeListAdapter.ViewHolder>{
private List<Recipe> mRecipeSet;
private Button mAddToGroceriesButton;
public RecipeListAdapter(List<Recipe> recipes){
mRecipeSet = recipes;
}
// Provide a reference to the views for each data item
// Complex data items may need more than one view per item, and
// you provide access to all the views for a data item in a view holder
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
//This is what will handle what happens when you click a recipe in the recycler view
private TextView mRecipeName;
private TextView mPrepTime;
private TextView mCookTime;
private TextView mServingSize;
private RelativeLayout mRecipeTextSection;
public ViewHolder(View v) {
super(v);
mRecipeName = (TextView) v.findViewById(R.id.recipe_list_recycler_view_recipe_name);
mServingSize = (TextView) v.findViewById(R.id.recipe_list_recycler_view_serving_size);
mPrepTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_prep_time);
mCookTime = (TextView) v.findViewById(R.id.recipe_list_recycler_view_cook_time);
mRecipeTextSection = (RelativeLayout) v.findViewById(R.id.recycled_item_section_view);
mAddToGroceriesButton = (Button) v.findViewById(R.id.add_to_grocery_list);
}
}
public void add(int position, Recipe item) {
mRecipeSet.add(position, item);
notifyItemInserted(position);
}
public void remove(Recipe item) {
int position = mRecipeSet.indexOf(item);
mRecipeSet.remove(position);
notifyItemRemoved(position);
}
public RecipeListAdapter(ArrayList<Recipe> myRecipeset) {
mRecipeSet = myRecipeset;
}
// Create new views (invoked by the layout manager)
#Override
public RecipeListAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// create a new view
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.recipe_item_recycled, parent, false);
ViewHolder vh = new ViewHolder(v);
return vh;
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
Recipe recipe = mRecipeSet.get(position);
String recipeName = recipe.getRecipeName();
String prepTime = "Prep Time: " + String.valueOf(recipe.getPrepTime()) + " minutes";
String cookTime = "Cook Time: " + String.valueOf(recipe.getCookTime()) + " minutes";
String servingSize = "Servings: " + String.valueOf(recipe.getServings());
holder.mRecipeName.setText(recipeName);
//Only display values if they are not null
if(recipe.getServings() != null) {
holder.mServingSize.setText(servingSize);
}
if (recipe.getPrepTime() != null) {
holder.mPrepTime.setText(prepTime);
}
if(recipe.getCookTime() != null) {
holder.mCookTime.setText(cookTime);
}
mRecipeTextSection.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Intent i = new Intent(v.getContext(), RecipeTextView.class);
Recipe selectedRecipe = mRecipeSet.get(position);
i.putExtra("view_recipe_key", selectedRecipe);
v.getContext().startActivity(i);
});
Recipe recipeToGrocery = mRecipeSet.get(position);
if(!recipeToGrocery.isInList()) {
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_24dp);
}
else{
mAddToGroceriesButton.setBackgroundResource(R.mipmap.ic_playlist_add_check_black_26dp);//set another image
}
mAddToGroceriesButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
int position = getAdapterPosition();
Recipe recipeToGrocery = mRecipeSet.get(position);
//RecipeDB dbHelper = new RecipeDB(v.getContext());
//dbHelper.addGroceryItem(recipeToGrocery);
if(!recipeToGrocery.isInList()) {
RecipeDB dbHelper = new RecipeDB(v.getContext());
dbHelper.addGroceryItem(recipeToGrocery);
recipeToGrocery.setInList(true);
dbHelper.updateRecipe(recipeToGrocery);
notifyDataSetChanged();
}
else {
Toast.makeText(v.getContext(), "That recipe is already in the list.", Toast.LENGTH_SHORT).show();
}
}
});
}
// Return the size of your dataset (invoked by the layout manager)
#Override
public int getItemCount() {
if(mRecipeSet != null) {
return mRecipeSet.size();
}
return 0;
}
}