-2

I am new to android and I have to create an android app for my final project.

I am making a swipe card app and I am using 'com.lorentzos.swipecards:library:1.0.9' library for the swiping engine.

It uses a custom adapter that extends a base adapter to inflate a layout file and populate certain ImageViews and TextViews with iformation coming from an ArrayList.

This is the code of the adapter

package com.botevplovdiv.foodmatch2;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;

import com.bumptech.glide.Glide;
import com.bumptech.glide.load.engine.DiskCacheStrategy;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Stelio on 13.5.2017 г..
 */



public class MyAppAdapter extends BaseAdapter {

    private static class ViewHolder {
        public FrameLayout background;
        public TextView DataText;
        public ImageView cardImage;
        public TextView shortDescriptionTextView;
        public TextView title;
    }
    ;
    public List<FoodDish> dishesList = new ArrayList<>();
    public Context mContext;

    public MyAppAdapter(Context context, List<FoodDish> foodDishes) {
        this.dishesList = foodDishes;
        this.mContext = context;
    }



    @Override
    public int getCount() {
        return dishesList.size();
    }

    @Override
    public Object getItem(int position) {
        return position;
    }

    @Override
    public long getItemId(int position) {
        return position;
    }

    public List<FoodDish> getDishesList(){
        return this.dishesList;
    }

    public void updateReceiptsList(List<FoodDish> newlist) {
        dishesList.clear();
        dishesList.addAll(newlist);
        this.notifyDataSetChanged();
    }


    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        FoodDish current = dishesList.get(position);

        ViewHolder viewHolder;


        if (convertView == null) {

            LayoutInflater inflater = LayoutInflater.from(mContext);
            convertView = inflater.inflate(R.layout.cards_layout, parent,false);
            // configure view holder
            viewHolder = new ViewHolder();
            viewHolder.DataText = (TextView) convertView.findViewById(R.id.priceText);
            viewHolder.background = (FrameLayout) convertView.findViewById(R.id.background);
            viewHolder.cardImage = (ImageView) convertView.findViewById(R.id.cardImage);
            viewHolder.shortDescriptionTextView = (TextView) convertView.findViewById(R.id.shortDescription);
            viewHolder.title = (TextView) convertView.findViewById(R.id.titleText);

            convertView.setTag(viewHolder);

        } else {
            viewHolder = (ViewHolder) convertView.getTag();
        }
        viewHolder.DataText.setText(current.getPrice());
        viewHolder.title.setText(current.getTitle());
        viewHolder.shortDescriptionTextView.setText(current.getDescription());
        Glide.with(mContext).load(current.getImagePath()).into(viewHolder.cardImage);



        return convertView;
    }
}

Everything is going fine till one point.

I have a Settings activity, which inflates a preferences.xml which has a bunch of switches. I could do it using MultiSelectListPreferences, but I want to be with switches for aesthetic reasons.

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

<PreferenceCategory
    android:selectable="true"
    android:title="@string/food_categories_name">

    <SwitchPreference
        android:defaultValue="true"
        android:key="fishSwitch"
        android:title="Fish" />
    <SwitchPreference
        android:defaultValue="true"
        android:key="meatSwitch"
        android:title="Meat" />
    <SwitchPreference
        android:defaultValue="true"
        android:key="vegSwitch"
        android:title="Vegeterian" />
    <SwitchPreference
        android:defaultValue="true"
        android:key="pizzaSwitch"
        android:title="Pizza" />
    <SwitchPreference
        android:defaultValue="true"
        android:key="pastaSwitch"
        android:title="Pasta" />
</PreferenceCategory>

<ListPreference
    android:defaultValue="@array/area_list"
    android:entries="@array/area_list"
    android:entryValues="@array/area_list"
    android:key="list_preference_1"
    android:title="@string/areas" />
<PreferenceCategory android:title="@string/venues_categories">

    <SwitchPreference
        android:defaultValue="true"
        android:key="restaurantSwitch"
        android:title="Restaurants" />
    <SwitchPreference
        android:defaultValue="true"
        android:key="takeAwaySwitch"
        android:title="Take Away" />
</PreferenceCategory>

In my MainActivity I have prefereceChangedListner which register changes and refine the searcCriteria and refineList Lists throught the respectful methods.

package com.botevplovdiv.foodmatch2;

import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.os.Bundle;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.SwitchPreference;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.View;
import android.view.Menu;
import android.view.MenuItem;

import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.Toast;

import com.bumptech.glide.Glide;
import com.lorentzos.flingswipe.SwipeFlingAdapterView;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class MainActivity extends AppCompatActivity {

    // keys for reading data from SharedPreferences
    public static final String FISH = "fishSwitch";
    public static final String MEAT = "meatSwitch";
    public static final String VEGETARIAN = "vegSwitch";
    public static final String PIZZA = "pizzaSwitch";
    public static final String PASTA = "pastaSwitch";
    public static final String RESTAURANTS = "restaurantSwitch";
    public static final String TAKEAWAY = "takeAwaySwitch";


    private MyAppAdapter myAppAdapter;
    private List<FoodDish> dishList;
    private List<FoodDish> refineList;
    private List<FoodDish> dumpList;
    private List<Venue> venues;
    private boolean[] booleans;
    private String[] booleansTags;
    private List<String> searchCriteria;
    private SwipeFlingAdapterView flingContainer;
    public static Map<String, Bitmap> bitmaps = new HashMap<>();
    boolean fishSwitch;
    boolean meatSwitch;
    boolean vegetarianSwitch;
    boolean pizzaSwitch;
    boolean pastaSwitch;
    boolean restaurantSwitch;
    boolean takeAwaySwitch;
    boolean preferenceChanged = true;
    String TAG = "FoodMatch";



    @Override
     protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        flingContainer = (SwipeFlingAdapterView) findViewById(R.id.frame);


        // set default values in the app's SharedPreferences
        PreferenceManager.setDefaultValues(this, R.xml.preferences, false);

        // register listener for SharedPreferences changes
        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPreferences.registerOnSharedPreferenceChangeListener(
                preferencesChangeListener);

        fishSwitch = sharedPreferences.getBoolean(FISH,false);
        meatSwitch =  sharedPreferences.getBoolean(MEAT,false);
        vegetarianSwitch =  sharedPreferences.getBoolean(VEGETARIAN,false);
        pizzaSwitch =  sharedPreferences.getBoolean(PIZZA,false);
        pastaSwitch =  sharedPreferences.getBoolean(PASTA,false);
        restaurantSwitch =  sharedPreferences.getBoolean(RESTAURANTS,false);
        takeAwaySwitch =  sharedPreferences.getBoolean(TAKEAWAY,false);

        booleansTags = new String[] {"FISH","MEAT","VEGETARIAN","PIZZA","PASTA","RESTAURANT","TAKE AWAY"};

        dishList = new ArrayList<>();
        searchCriteria = new ArrayList<>();
        refineList = new ArrayList<>();
        dumpList = new ArrayList<>();


        // load initial data
        loadDishes();

        createSearchCriteria(searchCriteria);
        refineDishesList();

        //lock the device to portrait mode
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);

        myAppAdapter = new MyAppAdapter(this, refineList);
        flingContainer.setAdapter(myAppAdapter);
        flingContainer.setFlingListener(new SwipeFlingAdapterView.onFlingListener() {
            @Override
            public void removeFirstObjectInAdapter()
            {

            }

            @Override
            public void onLeftCardExit(Object dataObject)
            {
                FoodDish current = refineList.get(0);
                refineList.remove(0);
                myAppAdapter.notifyDataSetChanged();
                }
            }

            @Override
            public void onRightCardExit(Object dataObject)
            {
                FoodDish current = refineList.get(0);
                Intent intent = new Intent(MainActivity.this,LikedProduct.class).putExtra("current",current);
                startActivity(intent);
                refineList.remove(0);
                myAppAdapter.notifyDataSetChanged();

            }

            @Override
            public void onAdapterAboutToEmpty(int itemsInAdapter)
            {

            }

            @Override
            public void onScroll(float scrollProgressPercent) {
                View view = flingContainer.getSelectedView();
                view.findViewById(R.id.background).setAlpha(0);
                view.findViewById(R.id.item_swipe_left_indicator).setAlpha(scrollProgressPercent < 0 ? -scrollProgressPercent : 0);
                view.findViewById(R.id.item_swipe_right_indicator).setAlpha(scrollProgressPercent > 0 ? scrollProgressPercent : 0);
            }
        });


        // Listener for touching events
        flingContainer.setOnItemClickListener(new SwipeFlingAdapterView.OnItemClickListener()
        {
            @Override
            public void onItemClicked(int itemPosition, Object dataObject) {

                View view = flingContainer.getSelectedView();
                view.findViewById(R.id.background).setAlpha(0);
                myAppAdapter.notifyDataSetChanged();
            }
        });

        //floating buttons for remote flipping the cards

        FloatingActionButton yesFAB =
                (FloatingActionButton) findViewById(R.id.acceptButton);
        yesFAB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!refineList.isEmpty())
                    flingContainer.getTopCardListener().selectRight();

            }
        });

        FloatingActionButton noFAB =
                (FloatingActionButton) findViewById(R.id.rejectButton);
        noFAB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!refineList.isEmpty())
                    flingContainer.getTopCardListener().selectLeft();

            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(TAG,"Entered onStart() method in MainActivity");

        if (preferenceChanged){
            myAppAdapter.notifyDataSetChanged();
            preferenceChanged = false;
        }
    }

    private void refineDishesList() {
        if (this.refineList.size() > 0)
        {
            this.refineList.clear();
        }
        for (FoodDish dish : this.dishList){
            if (this.searchCriteria.contains(dish.getCategory().toUpperCase()) && this.searchCriteria.contains(dish.getVenueType().toUpperCase())){
                this.refineList.add(dish);
            }
        }
    }

    private void createSearchCriteria(List<String> searchCriteria){
        booleans = new boolean[]{fishSwitch,meatSwitch,vegetarianSwitch,pizzaSwitch,pastaSwitch,restaurantSwitch,takeAwaySwitch};
        if (searchCriteria.size() >0){
            searchCriteria.clear();
        }
        for (int i = 0;i < booleansTags.length;i++){
            boolean temp = booleans[i];
            if (temp){
                searchCriteria.add(booleansTags[i]);
            }
        }
    }


    @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) {
        Intent preferencesIntent = new Intent(this, Settings.class);
        startActivity(preferencesIntent);
        return super.onOptionsItemSelected(item);
    }

    public void loadDishes(){
        dishList.add(new FoodDish("Shrimp dish","https://cdn.pixabay.com/photo/2015/04/10/00/41/food-715539_960_720.jpg",getString(R.string.test),"Price : 2,14", "FISH","Restaurant"));
        dishList.add(new FoodDish("Pizza ultra mega qkata rabota","http://www.seattleorganicrestaurants.com/vegan-whole-foods/images/Food-Guidelines.jpg","Test description.This a very tasty dish and you should definitely order it.I don`t know what are you waiting for", "Price: 3,87", "PIZZA","Take Away"));
        dishList.add(new FoodDish("Pasta","http://assets.simplyrecipes.com/wp-content/uploads/2008/03/pasta-tuna-arugula-horiz-a-1600.jpg",getString(R.string.test), "Price: 4,87","PASTA","Restaurant"));
        dishList.add(new FoodDish("Chicken wings","http://cf.yellowblissroad.com/wp-content/uploads/2015/02/Baked-Chicken-Wings.jpg",getString(R.string.test),"Price: 1,23","MEAT","Take Away"));
        dishList.add(new FoodDish("Fish","http://cdn.skim.gs/image/upload/v1456339187/msi/grilled-catfish_izglgf.jpg",getString(R.string.test), "Price: 5,87", "FISH","Take Away"));
        dishList.add(new FoodDish("Spaghetti","http://food.fnr.sndimg.com/content/dam/images/food/fullset/2009/6/12/2/FO1D41_23785_s4x3.jpg.rend.hgtvcom.616.462.jpeg",getString(R.string.test), "Price: 9,23", "PASTA","Restaurant"));
        dishList.add(new FoodDish("Ceasar salad","http://entomofarms.com/wp-content/uploads/2016/04/EF-caesar-salad-cricket-powder.jpg",getString(R.string.test), "Price: 3,45", "VEGETARIAN","Restaurant"));
        dishList.add(new FoodDish("Steak sandwich","http://s3.amazonaws.com/finecooking.s3.tauntonclud.com/app/uploads/2017/04/18125307/051120015-01-steak-sandwich-recipe-main.jpg",getString(R.string.test), "Price: 3,45","MEAT","Take Away"));
        dishList.add(new FoodDish("Lasagna","http://www.weightlossresources.co.uk/img/recipes/vegetarian-dishes.jpg",getString(R.string.test), "Price: 11,45","VEGETERIAN","Restaurant"));
        dishList.add(new FoodDish("Sea Food Risotto","http://www.dvo.com/recipe_pages/healthy/Lemony_Seafood_Risotto.jpg",getString(R.string.test), "Price: 8,45","VEGETERIAN","Take Away"));
    }


    private SharedPreferences.OnSharedPreferenceChangeListener preferencesChangeListener =
            new SharedPreferences.OnSharedPreferenceChangeListener() {
                @Override
                public void onSharedPreferenceChanged(
                        SharedPreferences sharedPreferences, String key) {
                    switch (key){
                        case FISH:
                            fishSwitch = sharedPreferences.getBoolean(FISH,false);
                            createSearchCriteria(searchCriteria);
                            refineDishesList();
                            myAppAdapter.notifyDataSetChanged();
                            preferenceChanged = true;
                            break;
                        case MEAT:
                            meatSwitch = sharedPreferences.getBoolean(MEAT,false);
                            createSearchCriteria(searchCriteria);
                            refineDishesList();
                            myAppAdapter.notifyDataSetChanged();
                            preferenceChanged = true;
                            break;
                        case VEGETARIAN:
                            vegetarianSwitch = sharedPreferences.getBoolean(VEGETARIAN,false);
                            createSearchCriteria(searchCriteria);
                            refineDishesList();
                            myAppAdapter.notifyDataSetChanged();
                            preferenceChanged = true;
                            break;
                        case PIZZA:
                            pizzaSwitch = sharedPreferences.getBoolean(PIZZA,false);
                            createSearchCriteria(searchCriteria);
                            refineDishesList();
                            myAppAdapter.notifyDataSetChanged();
                            preferenceChanged = true;
                            break;
                        case PASTA:
                            pastaSwitch = sharedPreferences.getBoolean(PASTA,false);
                            createSearchCriteria(searchCriteria);
                            refineDishesList();
                            myAppAdapter.notifyDataSetChanged();
                            preferenceChanged = true;
                            break;
                        case RESTAURANTS:
                            restaurantSwitch = sharedPreferences.getBoolean(RESTAURANTS,false);
                            createSearchCriteria(searchCriteria);
                            refineDishesList();
                            myAppAdapter.notifyDataSetChanged();
                            preferenceChanged = true;
                            break;
                        case TAKEAWAY:
                            takeAwaySwitch = sharedPreferences.getBoolean(TAKEAWAY,false);
                            createSearchCriteria(searchCriteria);
                            refineDishesList();
                            myAppAdapter.notifyDataSetChanged();
                            preferenceChanged = true;
                            break;

                    } //end of switch statement
        }
    };

}

The problem is after I change some of the switches, the adapter doesn`t update properly and still shows the last loaded "card".

If the refineList is empty however(e.g. there are mo object to show ), then everything works fine.

I read a lot of posts about my issue, but everywhere they say that the notifyDataSetChanged() should update the view.

I wrote a method in the adapter that updates the list that is assosiated with the adapter , but even if I use it , nothing happens.

Any suggestion what I am doing wrong?

If you need , I can post the code of SwipeFlingAdapterView class of the library I am using.

UPDATE

I forgot to mention that I tried returning to MainActivity from SetingsActivity both ways -> with the Up button of the SettingsActivity ( which parent is MainActivity) and with the hardware back button of the Android device.

1.If I use the UP button, everything works perfect and how I want it, but the Logcat is showing me that on return it destroys the current MainActivity and creates a new one and therefore my Adapter is restarted and I don`t think that this is very efficient.

2.If I use the back button on the device, when I am back to MainActivity it calls the onRestart() method and the top view is not updated. After I swipe it makes some update but it is definitely not what I want and I am completely stuck.

It turns out that there is a bug in the library and when you call notifyDataSetChanged() the control doesn`t go to getView() when you are using SwipeFlingAdapterView.If you use a normal ListView it works fine. So I just call flingContainer.removeAllViewsInLayout(); before calling notifyDataSetChanged() and works good.

1 Answers1

0

just quick review on the code, is this part of code correct?

@Override
public Object getItem(int position) {
    return position;
}

why don't change it to

@Override
public Object getItem(int position) {
    return dishesList.get(position);
}

will check it out sometime later

  • I didn`t even use that method, so this is why I didn`t changed it. I manage to find a solution to my problem.Obviously there is a bug in the library and when you call notifyDataSetChanged() the control doesn`go to getView() when you are using SwipeFlingAdapterView.If you use a normal ListView it works fine. So I just call flingContainer.removeAllViewsInLayout(); before calling and works good. – Kristiyan Kyosev May 19 '17 at 00:26