i am having spinner with country name and below i am showing flags according to country spinner.here i want to show flag according to spinner selection and not all..how can i show that in gridView?
HERE IS MY CODE:
public class FanciersFragment extends Fragment {
private View rootView;
private Spinner spFindCountry;
private RecyclerView rvFanciers;
private ArrayList<CountryDetail> countryDetailArray;
private LinearLayout llContainer;
private String countryCode;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.fragment_fanciers, container, false);
iitializeView();
return rootView;
}
private void iitializeView() {
spFindCountry = (Spinner) rootView.findViewById(R.id.sp_country_find);
rvFanciers = (RecyclerView) rootView.findViewById(R.id.rv_fanc_items);
llContainer = (LinearLayout) rootView.findViewById(R.id.ll_fanciers_container);
GridLayoutManager gridLayoutManager = new GridLayoutManager(getActivity() , 3);
rvFanciers.setHasFixedSize(true);
rvFanciers.setLayoutManager(gridLayoutManager);
getCounties();
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
getActivity().setTitle("FanciersResponse");
}
private void getCounties() {
if(Utility.isNetworkConnected(getActivity())) {
final Call<Countries> resp = Utility.getApiService().getContries();
resp.enqueue(new Callback<Countries>() {
#Override
public void onResponse(Call<Countries> call, Response<Countries> response) {
if (response.code() == 200) {
Countries countries = (Countries) response.body();
if (countries != null)
if (countries.getStatus() != null)
if (countries.getStatus().equals("OK")) {
countryDetailArray = (ArrayList<CountryDetail>) countries.getCountryDetails();
if(countryDetailArray != null)
populateCountrySpinner(countryDetailArray);
pupulateFanciers();
} else {
Utility.ShowSnackBar(countries.getStatusMessage() , llContainer);
}
} else {
Utility.ShowSnackBar("Network Error" , llContainer);
}
}
#Override
public void onFailure(Call<Countries> call, Throwable t) {
Utility.ShowSnackBar("No Response" , llContainer);
}
});
}
else {
Utility.ShowSnackBar(getResources().getString(R.string.no_internet), llContainer);
}
}
private void pupulateFanciers() {
Fanciers rcAdapter = new Fanciers(getActivity(), countryDetailArray , new Fanciers.OnItemClickListener() {
#Override
public void onItemClick(CountryDetail item) {
if(item != null){
Bundle b = new Bundle();
b.putSerializable(Constants.COUNTRY_DETAILS , item);
Intent intent = new Intent(getActivity() , CountryBaseFanciers.class);
intent.putExtra(Constants.BUNDLE , b);
startActivity(intent);
}
}
});
rvFanciers.setAdapter(rcAdapter);
}
private void populateCountrySpinner(final ArrayList<CountryDetail> countryDetailList) {
ArrayList<String> countryList = new ArrayList<>();
if(countryDetailList != null){
for(CountryDetail countryDetail: countryDetailList ){
countryList.add(countryDetail.getCountryName());
}
}
/*adapterCountry = new ArrayAdapter<String>(getActivity(), R.layout.spinner_layout, R.id.tv_country_name, countryList);
spCountry.setAdapter(adapterCountry);*/
HintSpinner<String> hintSpinner = new HintSpinner<>(
spFindCountry,
// Default layout - You don't need to pass in any layout id, just your hint text and
// your list data
new HintAdapter<>(getActivity(), getResources().getString(R.string.find_country), countryList),
new HintSpinner.Callback<String>() {
#Override
public void onItemSelected(int position, String itemAtPosition) {
// Here you handle the on item selected event (this skips the hint selected event)
countryCode = countryDetailList.get(position).getCountryCode();
}
});
hintSpinner.init();
}
}
I am getting all flags in gridview but i want on selection of spinner..kindly help
Instead of using GridView, try extending an ArrayAdapter class to use images, setting it in a ListView and implementing a filter based on country name. This should be fine if you want only one flag to be displayed at a time.
Related
The title might be a little confusing so I hope that I can express my problem correctly. So I'm working on a simple workout log app. I have fragment ActiveWorkout as in Image 1. When I press the pink add button I am directed to another fragment, which contains different exercises as a List, which is shown in Image 2. Then I am to select an exercise(with the onItemClickListener) and the title of that exercise should be sent back to the ActiveWorkoutFragment and added to the Active Workout, so it should be like Image 3. So the problem here is, I don't exactly know how to keep my Active Workout 'alive', it should be updated if I want to add another exercise and not be blank when I press the pink add button again, so in the end it should be something like in Image 4. I was thinking about sending data with a Bundle, which I also tried in the code but the more difficult part is updating the Workout list without deleting the previous added exercises. Btw the reason I am trying to do something like this is because the data is actually in Firebase Database, so in a sense I'm trying to retrieve data from the Workout database.
Images:
Image 1 Image 2 Image 3 Image 4
This is the Exercise List or the Catalog:
public class ExercisesFragment extends Fragment {
private ListView lv;
private FirebaseListAdapter adapter;
private ArrayList<Exercise> exerciseList;
private ArrayList<String> nameList;
//private Adapter adapter;
public ExercisesFragment() {
// Required empty public constructor
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_exercises, container, false);
lv = v.findViewById(R.id.lv);
Query query = FirebaseDatabase.getInstance().getReference().child("exerciseList");
FirebaseListOptions<ExerciseElement> options = new FirebaseListOptions.Builder<ExerciseElement>()
.setLayout(R.layout.exercise)
.setQuery(query, ExerciseElement.class)
.build();
adapter = new FirebaseListAdapter(options) {
#Override
protected void populateView(#NonNull View v, #NonNull Object model, int position) {
TextView bodypart = v.findViewById(R.id.bodypart);
TextView title = v.findViewById(R.id.title);
ExerciseElement el = (ExerciseElement) model;
bodypart.setText(el.getBodypart().toString());
title.setText(el.getTitle().toString());
}
};
lv.setAdapter(adapter);
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
ExerciseElement el = (ExerciseElement) lv.getItemAtPosition(position);
String item = el.getTitle();
ActiveWorkoutFragment awf = new ActiveWorkoutFragment();
Bundle args = new Bundle();
args.putString("ExerciseTitle", item);
awf.setArguments(args);
getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, awf).commit();
//Navigation.findNavController(v).navigate(R.id.activeWorkoutFragment);
}
});
return v;
}
#Override
public void onStart() {
super.onStart();
adapter.startListening();
}
#Override
public void onStop() {
super.onStop();
adapter.stopListening();
}
}
Then there is the ActiveWorkoutFragment, which is a little longer but the upper part is not the concern. The addNewExercise() method is being called when I click on the pink add button, so I was trying to retrieve the data somehow there.
public class ActiveWorkoutFragment extends Fragment {
private Workout workout;
private TextView emptyRecyclerView;
private RecyclerView exerciseRecyclerView;
private ExerciseRecyclerViewAdapter adapter;
private WorkoutHistory workoutHistory;
private FloatingActionButton fab;
private FirebaseAuth mAuth;
private DatabaseReference databaseWorkouts;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_active_workout, container, false);
fab = v.findViewById(R.id.fab);
fab.setOnClickListener(this::addNewExercise);
setHasOptionsMenu(true);
workout = new Workout("WORKOUT");
if(savedInstanceState != null) {
workout = savedInstanceState.getParcelable("key");
}
emptyRecyclerView = v.findViewById(R.id.empty_recycler_view);
//buildRecyclerView(workout);
exerciseRecyclerView = v.findViewById(R.id.recycler_view_exercise);
// improves performance if size of RecyclerView content is fixed
// taken from developer.android.com
exerciseRecyclerView.setHasFixedSize(true);
// use a linear layout manager for RecyclerView
LinearLayoutManager layoutManager = new LinearLayoutManager(this.getContext());
exerciseRecyclerView.setLayoutManager(layoutManager);
// add divider
RecyclerView.ItemDecoration itemDecoration = new
DividerItemDecoration(this.getContext(), DividerItemDecoration.VERTICAL);
exerciseRecyclerView.addItemDecoration(itemDecoration);
// Create adapter and set its data set to workout
adapter = new ExerciseRecyclerViewAdapter(workout, this);
// Set up swipe to dismiss and ability to move RecyclerView items around
// Create callback object for ItemTouchHelper
ItemTouchHelper.Callback callback = new CustomItemTouchHelperCallback(adapter);
// Implement object created above
ItemTouchHelper touchHelper = new ItemTouchHelper(callback);
touchHelper.attachToRecyclerView(exerciseRecyclerView);
if (adapter.getItemCount() == 0)
{
showEmptyRecyclerViewText();
}
else
{
exerciseRecyclerView.setAdapter(adapter);
}
return v;
}
// Adds save button (check mark) to action bar
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.active_workout_action_bar, menu);
super.onCreateOptionsMenu(menu, inflater);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_save: {
List<Exercise> exercises = workout.getExercises();
mAuth = FirebaseAuth.getInstance();
String user_id = mAuth.getCurrentUser().getUid();
databaseWorkouts = FirebaseDatabase.getInstance().getReference("Workouts").child(user_id);
String id = databaseWorkouts.push().getKey();
workout = new Workout("abc", user_id, exercises);
databaseWorkouts.child(id).setValue(workout);
Toast.makeText(getContext(), "Workout saved", Toast.LENGTH_SHORT).show();
return true;
}
case R.id.action_delete: {
exerciseRecyclerView.requestFocus();
AlertDialog.Builder builder = new AlertDialog.Builder(getContext());
builder.setTitle("Confirm deletion").setMessage("Are you sure you want to delete" +
" this workout?");
builder.setPositiveButton(android.R.string.yes, (dialog, which) -> {
try {
workoutHistory.removeWorkout(workout);
} catch (IOException e) {
e.printStackTrace();
}
Toast.makeText(getContext(), "Workout deleted", Toast.LENGTH_SHORT).show();
});
builder.setNegativeButton(android.R.string.no, (dialog, which) -> {
dialog.dismiss();
});
builder.show();
return true;
}
default:
// unrecognized button pressed
return super.onOptionsItemSelected(item);
}
}
public void showEmptyRecyclerViewText()
{
emptyRecyclerView.setVisibility(View.VISIBLE);
}
public void addNewExercise(View view) {
Bundle bundle = getArguments();
String value = "";
if(bundle != null) {
value = bundle.getString("ExerciseTitle");
}
System.out.println("lala");
System.out.println(value);
Exercise newExercise = new Exercise(value, -1, -1);
if (exerciseRecyclerView.getAdapter() == null) {
exerciseRecyclerView.setAdapter(adapter);
}
emptyRecyclerView.setVisibility(View.INVISIBLE);
workout.addExercise(newExercise);
adapter.notifyItemInserted(workout.getExercises().size() - 1);
}
private void hideKeyboard(Context context, View view) {
InputMethodManager imm = (InputMethodManager) context.getSystemService
(Activity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
#Override
public void onSaveInstanceState(#NonNull Bundle outState) {
super.onSaveInstanceState(outState);
outState.putParcelable("key", workout);
}
}
Try this as a base for your project. add views to it and other necessary methods however it will provide you with the flow of module
//contract to update Framgents
public interface FragUpdater {
public void updateExerciseFrag(Exercise exercise);
}
public class ExerciseActiity extends AppCompatActivity implements FragUpdater {
FragmentManager fm;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_exercise_actiity);
fab.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
gotoActiveWorkoutFragment();
}
});
fm = getSupportFragmentManager();
gotoExercisesFragment();
}
private void gotoActiveWorkoutFragment() {
ActiveWorkoutFragment activeWorkoutFragment = new ActiveWorkoutFragment();
Bundle bundle = new Bundle();
activeWorkoutFragment.setArguments(bundle);
fm.beginTransaction().add(R.id.content_frame, activeWorkoutFragment, "ExerciseSelectionFrag").addToBackStack(null).commit();
}
private void gotoExercisesFragment() {
ExercisesFragment exercisesFragment = new ExercisesFragment();
Bundle bundle = new Bundle();
exercisesFragment.setArguments(bundle);
fm.beginTransaction().replace(R.id.content_frame, exercisesFragment, "ExerciseDisplayFrag").commit();
}
#Override
public void updateExerciseFrag(Exercise exercise) {
// Get Fragment ExercisesFragment
ExercisesFragment frag = (ExercisesFragment)
fm.findFragmentByTag("ExerciseDisplayFrag");
if (frag == null) {
return;
}
frag.updateList(exercise);
}
}
public class ExercisesFragment extends Fragment {
//here update your list in ExerciseFragment
public void updateList(Exercise exercise) {}
}
public class ActiveWorkoutFragment extends Fragment {
FragUpdater fragUpdater;
#Override
public void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fragUpdater = (ExerciseActiity) getActivity();
}
private void selectListItem(Exercise exercise) {
fragUpdater.updateExerciseFrag(exercise);
getActivity().getSupportFragmentManager().popBackStack();
}
}
I am using a recyclerView to show a grid of movie posters. The posters are contained in a List<> along with their respective title and so on.
I implemented a searchView widget and I can successuflly get a List of matching results. But I can't hide the other ones.
As you understand I don't want to delete the irrelevant movies from the adapter or the user would not be able to see them again.
This is the code:
public class SearchUtils {
public static List<String> search(List<Show> list, String keyword){
List<String> results = new ArrayList<>();
for (Show curVal : list){
String curTitle = curVal.getTitle().toLowerCase().trim();
if (curTitle.contains(keyword)){
results.add(curTitle);
}else{
results = new ArrayList<>();
}
}
return results;
}
}
ListFragment.java
public class ListFragment extends Fragment implements LoaderManager.LoaderCallbacks<List<Show>> {
private static final String LOG_TAG = "ListFragment";
private static final String ARG_SCOPE = "com.dcs.shows.activity_to_launch";
private static final String BASE_URL = "http://api.themoviedb.org/3";
private TextView tv;
private ProgressBar pb;
private int scope;
private RecyclerView mRecyclerView;
private ShowAdapter mShowAdapter;
private SearchView mSearchView;
public static ListFragment newInstance(int target) {
Bundle args = new Bundle();
args.putInt(ARG_SCOPE, target);
ListFragment fragment = new ListFragment();
fragment.setArguments(args);
return fragment;
}
public ListFragment() {
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
scope = getArguments().getInt(ARG_SCOPE);
setHasOptionsMenu(true);
Log.i(LOG_TAG, "onCreate#Scope is: " + scope);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_list, container, false);
mShowAdapter = new ShowAdapter(new ArrayList<Show>());
mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recyclerView);
GridLayoutManager glm = new GridLayoutManager(getActivity(), 4);
mRecyclerView.setLayoutManager(glm);
mRecyclerView.addItemDecoration(new SpacesItemDecoration(8, getActivity()));
mRecyclerView.setAdapter(mShowAdapter);
mRecyclerView.addOnScrollListener(new EndlessRecyclerViewScrollListener(glm) {
#Override
public void onLoadMore(int page, int totalItemsCount) {
// Triggered only when new data needs to be appended to the list
// Add whatever code is needed to append new items to the bottom of the list
}
});
pb = (ProgressBar)rootView.findViewById(R.id.progress_view);
ConnectivityManager connMgr = (ConnectivityManager) getActivity().getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = connMgr.getActiveNetworkInfo();
if (networkInfo != null && networkInfo.isConnected()) {
// fetch data
getLoaderManager().initLoader(1, null, this);
} else {
// display error
pb.setVisibility(View.GONE);
}
return rootView;
}
List<Show> searchList;
#Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
getActivity().getMenuInflater().inflate(R.menu.main, menu);
final MenuItem myActionMenuItem = menu.findItem( R.id.action_search);
mSearchView = (SearchView) myActionMenuItem.getActionView();
mSearchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
#Override
public boolean onQueryTextSubmit(String s) {
if(!mSearchView.isIconified()) {
mSearchView.setIconified(true);
}
myActionMenuItem.collapseActionView();
return false;
}
#Override
public boolean onQueryTextChange(String s) {
if(s != null || !s.isEmpty()) {
for(Show movie : mShowAdapter.getList()) {
if(movie.getTitle().toLowerCase().contains(s.toLowerCase())){
mShowAdapter.add(movie);
}
mShowAdapter.notifyDataSetChanged();
}
} else {
mShowAdapter.addItemsToList(searchList, false);
}
return false;
}
});
mSearchView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
#Override
public void onViewDetachedFromWindow(View arg0) {
// search was detached/closed
Log.v(LOG_TAG, "Restoring list: " + searchList + " size: " + searchList.size());
mShowAdapter.addItemsToList(searchList, false);
}
#Override
public void onViewAttachedToWindow(View arg0) {
// search was opened
searchList = mShowAdapter.getList();
}
});
}
private class ShowHolder extends RecyclerView.ViewHolder {
public ImageView mImageView;
public TextView mTextView;
public ShowHolder(View itemView) {
super(itemView);
mImageView = (ImageView) itemView.findViewById(R.id.grid_item_image);
mTextView = (TextView) itemView.findViewById(R.id.grid_item_title);
}
}
private class ShowAdapter extends RecyclerView.Adapter<ShowHolder> {
private List<Show> mShows;
public ShowAdapter(List<Show> shows) {
mShows = shows;
}
public void add(Show show){
mShows.add(show);
notifyDataSetChanged();
}
public void addItemsToList(List<Show> newShows, boolean append){
if(append){
mShows.addAll(newShows);
}else {
mShows = newShows;
}
notifyDataSetChanged();
}
public void removeItemsFromList(int index){
mShows.remove(index);
notifyItemRemoved(index);
}
public List<Show> getList(){
return mShows;
}
#Override
public ShowHolder onCreateViewHolder(ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(getActivity());
View rootView = inflater.inflate(R.layout.list_item_row, parent, false);
return new ShowHolder(rootView);
}
#Override
public void onBindViewHolder(ShowHolder holder, int position) {
Show currentShow = mShows.get(position);
holder.mTextView.setText(currentShow.getTitle());
Glide.with(getActivity()).load(currentShow.getImage()).into(holder.mImageView);
}
#Override
public int getItemCount() {
return mShows.size();
}
}
#Override
public Loader<List<Show>> onCreateLoader(int i, Bundle bundle) {
//start the loader with the appropriate uri
//for now it only supports movies+popular
//it will support movies+top, tv+popular, tv+top.
Uri baseUri = Uri.parse(BASE_URL);
Uri.Builder uriBuilder = baseUri.buildUpon();
uriBuilder.appendPath("movie");
uriBuilder.appendPath("popular");
uriBuilder.appendQueryParameter("api_key", QueryUtils.API_KEY);
uriBuilder.appendQueryParameter("page", Integer.valueOf(1).toString());
Log.v(LOG_TAG, "onCreateLoader#URL built: " + uriBuilder.toString());
return new ShowLoader(getActivity(), uriBuilder.toString());
}
#Override
public void onLoadFinished(Loader<List<Show>> loader, List<Show> shows) {
// Clear the adapter of previous earthquake data
clearAdapter();
// If there is a valid list of Shows, then add them to the adapter's
// data set. This will trigger the ListView to update.
if (shows != null && !shows.isEmpty()) {
mShowAdapter.addItemsToList(shows, false);
mShowAdapter.notifyDataSetChanged();
}
pb.setVisibility(View.GONE);
}
#Override
public void onLoaderReset(Loader<List<Show>> loader) {
// Loader reset, so we can clear out our existing data.
clearAdapter();
}
private void clearAdapter(){
List<Show> empty = new ArrayList<>();
mShowAdapter.addItemsToList(empty, false);
mShowAdapter.notifyDataSetChanged();
}
Thanks
You can use two lists, one with all the elements (original), and one with just queried elements (this one should use recyclerview adapter). When querying, just select from original list and add them to adapter list, then notify changes. Don't forget to clear adapter list before adding new entries.
Edit: you can try something like this on onQueryTextChange method. Adapt for your own wish.
if(s != null && !s.isEmpty()) {
for(String movie : originalList) {
if(movie.toLowerCase().contains(s.toLowerCase()){
adapter.add(movie);
}
notifyChanges();
}
}
} else { adapter.addAll(originalList); }
Hello am trying to delete an item from my listview am able to delete item from my db but my adapter is not getting updated I have attached the code below`
public class SavedPolygonFragment extends android.support.v4.app.Fragment implements RefreshListener {
private static String LOG_TAG = SavedPolygonFragment.class.getName();
private String message = "No message";
private ListView shapeList;
private TextView textView;
private Button startMainBtn;
private SavedShapeAdapter savedShapeAdapter;
private long shapeId;
private float scaleFactor;
private List<Shape> savedShapes = new ArrayList<>();
private StartDrawingListener startListener;
private DeleteShapesDialog deleteDialog;
public SavedPolygonFragment() {
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
startListener = (StartDrawingListener) activity;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_one, container, false);
savedShapes = getArguments().getParcelableArrayList("shapes");
AssetLog.verbose(LOG_TAG, "savedshapes.size " + savedShapes.size());
shapeList = (ListView) view.findViewById(R.id.shapeList);
textView = (TextView) view.findViewById(R.id.polygonTitle);
startMainBtn = (Button) view.findViewById(R.id.gotoMain);
startMainBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
startListener.startMainReceived();
}
});
if (!savedShapes.isEmpty() && !savedShapes.equals(null) && savedShapes.size() != 0) {
textView.setText("Polygons");
shapeList.setVisibility(View.VISIBLE);
startMainBtn.setVisibility(View.GONE);
if (savedShapeAdapter != null) {
savedShapeAdapter.notifyDataSetChanged();
} else {
savedShapeAdapter = new SavedShapeAdapter(savedShapes, getActivity());
shapeList.setAdapter(savedShapeAdapter);
shapeList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
MainActivity_.intent(getActivity())
.savedProjectId(ProjectShapesActivity.projId)
.scaleFactor(ProjectShapesActivity.scaleFactor)
.shapeId(((Shape) view.getTag()).getShapeId())
.lineId(-1)
.pointId(-1)
.start();
}
});
}
}
else{
shapeList.setVisibility(View.GONE);
startMainBtn.setVisibility(View.VISIBLE);
textView.setText("Sorry no shapes are saved");
}
return view;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
registerForContextMenu(shapeList);
}
#Override
public void onRefreshPressed() {
}
#Override
public void onCreateContextMenu(ContextMenu menu, View view, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, view, menuInfo);
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo)menuInfo;
shapeId = info.id;
menu.add(Menu.NONE, R.id.deleteShapes, Menu.NONE, "Delete");
menu.add(Menu.NONE, R.id.editShapes, Menu.NONE, "Edit");
}
#Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()){
case R.id.refresh:
return false;
case R.id.deleteShapes:
if(deleteDialog == null){
Bundle bundle = new Bundle();
bundle.putString("SHAPE", "SHAPE");
bundle.putLong("shapeId", shapeId);
deleteDialog = new DeleteShapesDialog();
deleteDialog.setArguments(bundle);
deleteDialog.show(getActivity().getFragmentManager().beginTransaction(), "showDeleteDialog");
}
return true;
case R.id.editShapes:
return true;
}
return super.onContextItemSelected(item);
}
public void onDataChanged(long shapeid) {
Shape shape;
for (int i = 0; i <savedShapes.size() ; i++) {
shape = savedShapes.get(i);
if(shape.getShapeId() == shapeid){
savedShapes.remove(i);
shapeList.removeViewAt(i);
shapeList.invalidate();
savedShapeAdapter.notifyDataSetChanged();
break;
}
}
}
}
`
Now when user selects yes from deleteDialog i wrote a callback to my activity and in the corresponding methods this is what I do
SavedPolygonFragment polygonFragment = new SavedPolygonFragment();
polygonFragment.onDataChanged(shapeId);
Can somebody show me whats wrong
/////EDIT 1
public void onDataChanged(long shapeid) {
savedShapeAdapter.removeItemById(shapeid);
}
and my adapter
public void removeItemById(long itemId){
for(int i =0; i< shapeList.size() ; i++){
if(shapeList.get(i).getShapeId() == itemId){
shapeList.remove(i);
}
}
notifyDataSetChanged();
}
am able to delete item from my db but my adapter is not getting
updated
Problem is caused by :
savedShapes.remove(i);
line.
Currently removing item from ArrayList which is in SavedPolygonFragment class, not from ArrayList which is used by Adapter to fill ListView.
Using current approach try this way will work by setting new Adapter every time:
if(shape.getShapeId() == shapeid){
savedShapes.remove(i);
savedShapeAdapter = new SavedShapeAdapter(savedShapes, getActivity());
shapeList.setAdapter(savedShapeAdapter);
savedShapeAdapter.notifyDataSetChanged();
break;
}
But this is not optimize solution to create and set new object of Adapter every-time when want to update ListView.
Right approach is create a method in SavedShapeAdapter class for removing item for ArrayList which is used by Adapter and then call it inside onDataChanged method:
public void deleteRowItem(int index){
this.savedShapes.remove(index);
this..notifyDataSetChanged();
}
Now call deleteRowItem when want to delete row item from ListView :
if(shape.getShapeId() == shapeid){
savedShapeAdapter.deleteRowItem(i);
break;
}
I cant figure out whats the problem here. Im trying to add an Object "idea" from type Idea to the list ideaList. And then it throws this exception. Anyone knows?
java.lang.UnsupportedOperationException
at java.util.AbstractList.add(AbstractList.java:404)
at java.util.AbstractList.add(AbstractList.java:425)
at smoca.ch.kreagen.Fragments.VotingFragment.(VotingFragment.java:50)
at smoca.ch.kreagen.FragmentStateHandler.chooseAndShowForVoting(FragmentStateHandler.java:69)
at smoca.ch.kreagen.Adapters.ArchiveAdapter$1.onClick(ArchiveAdapter.java:50)
at android.view.View.performClick(View.java:5155)
I want to add it after the list has been created and filled by realm-data.
right in the first constructor with Idea as param.
Class-Code:
public class VotingFragment extends Fragment implements VotingAdapter.ClickListener{
private RecyclerView recyclerView;
private VotingAdapter votingAdapter;
private Realm realm;
private List<Idea> ideaList;
private List<Vote> voteList;
private List<Owner> ownerList;
private FragmentStateHandler fragmentStateHandler;
private TextView status;
private Button startVoting;
private Button stopVoting;
public VotingFragment(Idea idea) {
getData();
ideaList.add(idea);
setStatus(true);
}
public VotingFragment() {
getData();
setStatus(false);
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public void onAttach(Activity activity) {
super.onAttach(activity);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
super.onCreateView(inflater, container, savedInstanceState);
View layout = inflater.inflate(R.layout.voting_fragment_layout, container, false);
recyclerView = (RecyclerView) layout.findViewById(R.id.votingDrawerList);
realm = Realm.getInstance(getActivity());
fragmentStateHandler = FragmentStateHandler.getInstance();
// get buttons and views
status = (TextView) layout.findViewById(R.id.statusTextView);
startVoting = (Button) layout.findViewById(R.id.startButton);
stopVoting = (Button) layout.findViewById(R.id.stopButton);
// clicklisteners for start/stop
startVoting.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setStatus(true);
// put ideas in List
// put votes in List
// put Owners in List
// sort Voting
// set timestamp (24h)
}
});
stopVoting.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
setStatus(false);
// clear ideas from List
// put voting in History
}
});
votingAdapter = new VotingAdapter(getActivity(), ideaList, voteList, ownerList); // params: context, idealist, votelist, ownerlist
votingAdapter.setClickListener(this); // set clicklistener on this
recyclerView.setAdapter(votingAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
return layout;
}
public void getData() {
ideaList = Collections.emptyList();
voteList = Collections.emptyList();
ownerList = Collections.emptyList();
try {
RealmQuery<Idea> ideaQuery = realm.where(Idea.class);
RealmResults<Idea> ideaQueryResult = ideaQuery.findAll();
RealmQuery<Vote> voteQuery = realm.where(Vote.class);
RealmResults<Vote> voteQueryResult = voteQuery.findAll();
RealmQuery<Owner> ownerQuery = realm.where(Owner.class);
RealmResults<Owner> ownerQueryResult = ownerQuery.findAll();
ideaList = ideaQueryResult;
voteList = voteQueryResult;
ownerList = ownerQueryResult;
} catch (Exception e) { e.printStackTrace();}
Log.d("joris", "" + ideaList);
Log.d("joris", "" + voteList);
Log.d("joris", "" + ownerList);
}
// items clicked in recyclerview
#Override
public void itemClicked(View view, int position) {
Idea current = ideaList.get(position);
fragmentStateHandler.showIdeaFrag(current);
}
public void setStatus(boolean val) {
if(val) {
status.setText("OPEN");
status.setTextColor(getResources().getColor(R.color.Green));
} else {
status.setText("CLOSED");
status.setTextColor(getResources().getColor(R.color.Red));
}
}
}
You can't modify the Lists you get back as RealmResult
Instead you probably want to copy the results of your queries to get mutable lists.
Something like
ideaList = new ArrayList<>();
voteList = Collections.emptyList();
ownerList = Collections.emptyList();
try {
RealmQuery<Idea> ideaQuery = realm.where(Idea.class);
RealmResults<Idea> ideaQueryResult = ideaQuery.findAll();
RealmQuery<Vote> voteQuery = realm.where(Vote.class);
RealmResults<Vote> voteQueryResult = voteQuery.findAll();
RealmQuery<Owner> ownerQuery = realm.where(Owner.class);
RealmResults<Owner> ownerQueryResult = ownerQuery.findAll();
ideaList.addAll(ideaQueryResult);
voteList = voteQueryResult;
ownerList = ownerQueryResult;
} catch (Exception e) { e.printStackTrace();}
As you see you can no longer use the Collections.emptyList as default value as it is immutable, and instead of using the ideaQueryResult directly we copy all the elements from the list to our own mutable ArrayList.
I am attempting to enact the Parcelable pattern to save and restore my ListView data on orientation changes.
The problem is, the ListView will only update once I do an orientation change. It will not update otherwise. It used to work just fine, until I started implementing Parcelable.
All help is greatly appreciated!
My fragment class is copied below, but can also be accessed here on GitHub:
public class TrackActivityFragment extends Fragment {
private IconicAdapter trackResultListViewAdapter = null;
private String artistId = null;
private final String LOG_TAG = TrackActivityFragment.class.getSimpleName();
public TrackActivityFragment() {
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
ArrayList<TrackParcelable> trackParcelables = null;
View rootView = inflater.inflate(R.layout.fragment_track, container, false);
Intent intent = getActivity().getIntent();
if(intent != null && intent.hasExtra(Intent.EXTRA_SHORTCUT_NAME)) {
artistId = intent.getStringExtra(Intent.EXTRA_SHORTCUT_NAME);
}
if(savedInstanceState == null || !savedInstanceState.containsKey("tracks_key")) {
trackParcelables = new ArrayList<TrackParcelable>();
performSearch(artistId);
}
else {
trackParcelables = savedInstanceState.getParcelableArrayList("tracks_key");
}
ListView listView = (ListView) rootView.findViewById(R.id.listViewOfTopTracks);
trackResultListViewAdapter = new IconicAdapter(trackParcelables,
getTrackNamesFromParcelables(trackParcelables));
listView.setAdapter(trackResultListViewAdapter);
return rootView;
}
#Override
public void onResume() {
super.onResume();
}
#Override
public void onSaveInstanceState(Bundle outState) {
outState.putParcelableArrayList("tracks_key",
trackResultListViewAdapter.getTrackParcelables());
super.onSaveInstanceState(outState);
}
private ArrayList<String> getTrackNamesFromParcelables(ArrayList<TrackParcelable>
trackParcelables){
ArrayList<String> trackNames = new ArrayList<>();
for(TrackParcelable element : trackParcelables){
trackNames.add(element.name);
}
return trackNames;
}
private void performSearch(String artistId) {
SpotifyApi api = new SpotifyApi();
SpotifyService spotify = api.getService();
Map<String, Object> options = new HashMap<>();
options.put("country", "US");
spotify.getArtistTopTrack(artistId, options, new Callback<Tracks>() {
#Override
public void success(Tracks tracks, Response response) {
final ArrayList<TrackParcelable> trackParcelables =
new ArrayList<TrackParcelable>();
for (Track track : tracks.tracks) {
trackParcelables.add(new TrackParcelable(track.name,track.album.name,
track.album.images.get(0).url,track.preview_url));
}
trackResultListViewAdapter.swapItems(trackParcelables);
Log.d(LOG_TAG,trackParcelables.toString());
getActivity().runOnUiThread(new Runnable() {
#Override
public void run() {
if(trackParcelables.size()==0){
Toast.makeText(getActivity(),
getString(R.string.no_tracks_found_toast),
Toast.LENGTH_SHORT).show();
}
trackResultListViewAdapter.notifyDataSetChanged();
}
});
}
#Override
public void failure(RetrofitError error) {
}
});
}
//This ViewHolder Pattern is from Busy Android Coder's Guide page 274 of book version 6.7
class ViewHolder {
ImageView icon=null;
TextView trackName=null;
TextView trackAlbum=null;
ViewHolder(View row) {
this.icon = (ImageView)row.findViewById(R.id.imageViewAlbum);
this.trackName = (TextView)row.findViewById(R.id.textViewTrackTitle);
this.trackAlbum = (TextView)row.findViewById(R.id.textViewTrackAlbum);
}
}
//This IconicAdapter Pattern is from Busy Android Coder's Guide page 272 of book version 6.7
class IconicAdapter extends ArrayAdapter<String> {
private ArrayList<TrackParcelable> trackParcelables;
public IconicAdapter(ArrayList<TrackParcelable> trackParcelables,
ArrayList<String> trackNames) {
super(getActivity(), R.layout.list_item_top_tracks, R.id.textViewTrackTitle
, trackNames);
this.trackParcelables = trackParcelables;
}
public void swapItems(ArrayList<TrackParcelable> trackParcelables) {
this.trackParcelables = trackParcelables;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
View row = super.getView(position, convertView, parent);
ViewHolder holder = (ViewHolder)row.getTag();
if (holder==null) {
holder=new ViewHolder(row);
row.setTag(holder);
}
Picasso.with(getActivity()).load(trackParcelables.get(position).albumImageUrl)
.into(holder.icon);
TextView trackAlbumTextView = (TextView)row.findViewById(R.id.textViewTrackAlbum);
trackAlbumTextView.setText(trackParcelables.get(position).albumName);
return row;
}
public ArrayList<TrackParcelable> getTrackParcelables(){
return trackParcelables;
}
}
The issue is that IconicAdapter is only tracking changes in trackNames, not in ArrayList <TrackParcelable> trackParcelables.
To fix this, I added a a member variable in my IconicAdapter for the trackNames and set this in the constructor like so:
private ArrayList<TrackParcelable> trackParcelables;
private ArrayList <String> trackNames;
public IconicAdapter(ArrayList<TrackParcelable> trackParcelables,
ArrayList<String> trackNames) {
super(getActivity(), R.layout.list_item_top_tracks, R.id.textViewTrackTitle
, trackNames);
this.trackNames = trackNames;
this.trackParcelables = trackParcelables;
}
Then, I edited my swapItems to update my ListView data like so:
public void swapItems(ArrayList<TrackParcelable> trackParcelables) {
this.trackParcelables = trackParcelables;
trackNames.clear();
trackNames.addAll(getTrackNamesFromParcelables(trackParcelables));
}