【发布时间】:2017-05-18 22:27:42
【问题描述】:
我是 android 新手,我必须为我的最终项目创建一个 android 应用程序。
我正在制作一个刷卡应用程序,我正在为刷卡引擎使用“com.lorentzos.swipecards:library:1.0.9”库。
它使用自定义适配器扩展基本适配器来扩展布局文件并使用来自 ArrayList 的信息填充某些 ImageView 和 TextView。
这是适配器的代码
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;
}
}
一切都很好,直到某一点。
我有一个设置活动,它膨胀了一个有一堆开关的preferences.xml。我可以使用 MultiSelectListPreferences 来做到这一点,但出于审美原因,我想使用开关。
<?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>
在我的 MainActivity 中,我有 prefereceChangedListner,它通过尊重的方法注册更改并优化 searcCriteria 和 refineList 列表。
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
}
};
}
问题是在我更改了一些开关后,适配器没有正确更新并且仍然显示最后加载的“卡”。
如果refineList是空的(例如有mo对象要显示),那么一切正常。
我阅读了很多关于我的问题的帖子,但他们到处都说 notifyDataSetChanged() 应该更新视图。
我在适配器中编写了一个方法来更新与适配器关联的列表,但即使我使用它,也没有任何反应。
有什么建议我做错了吗?
如果你需要,我可以发布我正在使用的库的 SwipeFlingAdapterView 类的代码。
更新
我忘了提到,我尝试通过 SettingsActivity 的向上按钮(父级是 MainActivity)和 Android 设备的硬件后退按钮两种方式从 SetingsActivity 返回 MainActivity。
1.如果我使用 UP 按钮,一切正常,并且我想要它,但是 Logcat 显示返回时它会破坏当前的 MainActivity 并创建一个新的,因此我的适配器重新启动,我不不认为这是非常有效的。
2.如果我使用设备上的后退按钮,当我回到 MainActivity 时,它会调用 onRestart() 方法并且顶视图不会更新。在我刷卡之后,它会进行一些更新,但这绝对不是我想要的,我完全被卡住了。
原来库中有一个错误,当您调用 notifyDataSetChanged() 时,当您使用 SwipeFlingAdapterView 时,控件不会转到 getView()。如果您使用普通的 ListView,它可以正常工作。所以我只是调用 flingContainer.removeAllViewsInLayout();在调用 notifyDataSetChanged() 之前效果很好。
【问题讨论】: