I have an image in feed_item.xml that is inflated in the custom adapter.I am able to handle click events for the image.
I Have a relative layout in my activity_main that is rendered player.setVisibility(View.GONE); when my Main Activity is launched.I would like to setVisibility(View.VISIBLE) of this layout when my image in the row is clicked.
I have trouble relating the two layouts with my Custom Adapter and Main Activity.Any suggestions will be appreciated!!
FeedListAdapter.java
public class FeedListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<FeedItem> feedItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public FeedListAdapter(Activity activity, List<FeedItem> feedItems) {
this.activity = activity;
this.feedItems = feedItems;
}
#Override
public int getCount() {
return feedItems.size();
}
#Override
public Object getItem(int location) {
return feedItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.feed_item, null);
TextView name = (TextView) convertView.findViewById(R.id.name);
FeedItem item = feedItems.get(position);
name.setText(item.getName());
String fontPath = "fonts/Lato-Light.ttf";
// Loading Font Face
Typeface tf = Typeface.createFromAsset(activity.getAssets(), fontPath);
// Applying font
name.setTypeface(tf);
ImageView play=(ImageView)convertView.findViewById(R.id.play);
play.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Toast.makeText(activity, "Show Layout!", Toast.LENGTH_SHORT).show();
}
});
ImageView options=(ImageView)convertView.findViewById(R.id.options_popup);
options.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
showFilterPopup(view);
}
});
return convertView;
}
}
MainActivity.java
public class MainActivity extends ActionBarActivity {
RelativeLayout player;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.app_bar);
setSupportActionBar(toolbar);
TextView mToolBarTextView = (TextView) findViewById(R.id.text_view_toolbar_title);
mToolBarTextView.setText("Home");
getSupportActionBar().setHomeButtonEnabled(true);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
listView = (InnerGridView) findViewById(R.id.list);
feedItems = new ArrayList<FeedItem>();
listAdapter = new FeedListAdapter(this, feedItems);
listView.setAdapter(listAdapter);
player = (RelativeLayout) findViewById(R.id.player);
player.setVisibility(View.GONE);
}
}
You can create your own interface with a method like this
public interface OnClickInMyAdapterListener {
public void onItemclicked();
}
than your activity should implement this interface and override its method
public class MainActivity extends ActionBarActivity implements OnClickInMyAdapterListener {
...
...
}
#Override
public void onItemclicked() {
// do what you want
}
change your adapter in order to recive the interface
private OnClickInMyAdapterListener myActivityInterface;
public FeedListAdapter(Activity activity, List<FeedItem> feedItems, OnClickInMyAdapterListener myActivityInterface ) {
this.activity = activity;
this.feedItems = feedItems;
this.myActivityInterface= myActivityInterface;
}
in the activity pass the interface to the adapter
listAdapter = new FeedListAdapter(this, feedItems, (OnClickInMyAdapterListener ) this);
and use it in your adapter wherever you want
this.myActivityInterface.onItemclicked();
... This solution is useful also if your adapter is used in more diffrent activites
You can write one public method in Activity
And cast your activity context to your Activity
((MainActivity)activity).doSomething();
activity is context you are passing to adapter
doSomething is method in activity
Rather than setting OnClickListeners on the Views within your custom Adapter, you should call:
listView.setOnItemSelectedListener(this);
And have your Activity implement AdapterView.OnItemSelectedListener
See http://developer.android.com/reference/android/widget/AdapterView.OnItemSelectedListener.html
Related
I have a problem with the recyclerview in my app i have 2 fragments in the first one there is the recycler view which has to find the songs present in the device and put them in line in the second for now nothing. when I switch from one fragment to another the recycler view items double each time.
CODE:
HomeActvity
public class HomeActivity extends AppCompatActivity {
BottomNavigationView bottomNavigationView;
RecyclerView recyclerView;
TextView noMusicTextView;
HomeFragment homeFragment = new HomeFragment();
ProvaFragment provaFragment = new ProvaFragment();
#SuppressLint("MissingInflatedId")
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
getSupportActionBar().hide();
noMusicTextView = findViewById(R.id.noSongs);
recyclerView = findViewById(R.id.recycler_view);
bottomNavigationView = findViewById(R.id.barra_navigazione);
getSupportFragmentManager().beginTransaction().replace(R.id.contenitore_frammenti, homeFragment).commit();
bottomNavigationView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
#Override
public boolean onNavigationItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.home:
getSupportFragmentManager().beginTransaction().replace(R.id.contenitore_frammenti, homeFragment).commit();
return true;
case R.id.prova:
getSupportFragmentManager().beginTransaction().replace(R.id.contenitore_frammenti, provaFragment).commit();
return true;
}
return false;
}
});
}
}
HomeFragment
public class HomeFragment extends Fragment {
ArrayList<AudioModel> songsList = new ArrayList<>();
RecyclerView recyclerView;
TextView noMusicTextView;
#SuppressLint("MissingInflatedId")
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
recyclerView = view.findViewById(R.id.recycler_view);
noMusicTextView = view.findViewById(R.id.noSongs);
String[] projection = {
MediaStore.Audio.Media.TITLE,
MediaStore.Audio.Media.DATA,
MediaStore.Audio.Media.DURATION,
};
String selection = MediaStore.Audio.Media.IS_MUSIC + " !=0";
Cursor cursor = getActivity().getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,projection,selection,null,null);
while(cursor.moveToNext()){
AudioModel songData = new AudioModel(cursor.getString(1), cursor.getString(0),cursor.getString(2));
if(new File(songData.getPath()).exists())
songsList.add(songData);
}
if(songsList.size() == 0){
noMusicTextView.setVisibility(View.VISIBLE);
}else{
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
recyclerView.setAdapter(new MusicListAdapter(songsList, getContext()));
}
return view;
}
}
MusicListAdapter
public class MusicListAdapter extends RecyclerView.Adapter<MusicListAdapter.ViewHolder>{
ArrayList<AudioModel> songsList;
Context context;
public MusicListAdapter(ArrayList<AudioModel> songsList, Context context) {
this.songsList = songsList;
this.context = context;
}
#Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.recycler_item,parent,false);
return new MusicListAdapter.ViewHolder(view);
}
#Override
public void onBindViewHolder(ViewHolder holder, int position) {
AudioModel songData = songsList.get(position);
holder.titleTextView.setText(songData.getTitle());
}
#Override
public int getItemCount() {
return songsList.size();
}
public class ViewHolder extends RecyclerView.ViewHolder{
TextView titleTextView;
ImageView iconImageView;
public ViewHolder(View itemView) {
super(itemView);
titleTextView = itemView.findViewById(R.id.music_title_text);
iconImageView = itemView.findViewById(R.id.icon_view);
}
}
}
I have tryed to use songsList.clear(); but this don't work(Sorry for my english).
When switching fragments, existing fragments aren't deleted.
Also, songsList isn't initialized; onViewCreated() is called at this time, so it seems that the transition adds the item to the songsList.
In order to solve the problem, it seems that it is necessary to do a good comparison so that the same item as the previously saved item is not added, or to not add an item every time in onViewCreated.
So I have an activity with a listview inside of it and when I click a delete button I want to remove the object from the list. I already know how to find which object I want to remove and remove it from the list that populates my array adapter but I am not sure what i need to do to call the .notifyDataSetChanged() routine which Is what I believe I need to do. Any help would be much appreciated.
My activity code
public class MealActivity2 extends AppCompatActivity {
private ListView lv;
public static ArrayList<Model> modelArrayList;
private CustomAdapter customAdapter;
private Button btnnext;
private String[] fruitlist = new String[]{"Apples", "Oranges", "Potatoes", "Tomatoes","Grapes"};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meal2);
Integer numFoodItems = ((Globals) getApplication()).getLength();
lv = (ListView) findViewById(R.id.lv);
btnnext = (Button) findViewById(R.id.next);
modelArrayList = getModel(numFoodItems);
customAdapter = new CustomAdapter(this);
lv.setAdapter(customAdapter);
btnnext.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(MealActivity2.this,NextActivity.class);
startActivity(intent);
}
});
}
// this builds the array list of model opbjects that will be used by the adapter to populate
// the list view dynamically
private ArrayList<Model> getModel(Integer length){
ArrayList<Model> list = new ArrayList<>();
for(int i = 0; i < length; i++){
FoodDetailsPost food = ((Globals) getApplication()).getFoodList().get(i);
Model model = new Model();
model.setNumber(((Globals) getApplication()).getServing(i));
model.setFruit(food.getDescription());
list.add(model);
}
return list;
}
}
and here is my custom adapter code if you look near the end at the last comment that is where i need to notify my activity that I have changed the contents of the list and should update the displaying items
public class CustomAdapter extends BaseAdapter {
private Context context;
private adapterGlobalAccess g = new adapterGlobalAccess();
private CustomAdapter customAdapter;
public CustomAdapter(Context context) {
this.context = context;
}
#Override
public int getViewTypeCount() {
return getCount();
}
#Override
public int getItemViewType(int position) {
return position;
}
#Override
public int getCount() {
return MealActivity2.modelArrayList.size();
}
#Override
public Object getItem(int position) {
return MealActivity2.modelArrayList.get(position);
}
#Override
public long getItemId(int position) {
return 0;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
final ViewHolder holder;
if (convertView == null) {
holder = new ViewHolder(); LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
convertView = inflater.inflate(R.layout.lv_item, null, true);
holder.tvFruit = (TextView) convertView.findViewById(R.id.animal);
holder.tvnumber = (TextView) convertView.findViewById(R.id.number);
holder.btn_edit = (Button) convertView.findViewById(R.id.plus);
holder.btn_minus = (Button) convertView.findViewById(R.id.minus);
convertView.setTag(holder);
}else {
// the getTag returns the viewHolder object set as a tag to the view
holder = (ViewHolder)convertView.getTag();
}
holder.tvFruit.setText(MealActivity2.modelArrayList.get(position).getFruit());
holder.tvnumber.setText(String.valueOf(MealActivity2.modelArrayList.get(position).getNumber()));
holder.btn_edit.setTag(R.integer.btn_plus_view, convertView);
holder.btn_edit.setTag(R.integer.btn_plus_pos, position);
holder.btn_edit.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View tempview = (View) holder.btn_edit.getTag(R.integer.btn_plus_view);
TextView tv = (TextView) tempview.findViewById(R.id.number);
Integer pos = (Integer) holder.btn_edit.getTag(R.integer.btn_plus_pos);
Double number = Double.parseDouble(tv.getText().toString()) + 1;
tv.setText(String.valueOf(number));
MealActivity2.modelArrayList.get(pos).setNumber(number);
g.setServing(pos, number);
}
});
holder.btn_minus.setTag(R.integer.btn_minus_view, convertView);
holder.btn_minus.setTag(R.integer.btn_minus_pos, position);
holder.btn_minus.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View tempview = (View) holder.btn_minus.getTag(R.integer.btn_minus_view);
TextView tv = (TextView) tempview.findViewById(R.id.number);
Integer pos = (Integer) holder.btn_minus.getTag(R.integer.btn_minus_pos);
((Globals) context.getApplicationContext()).remove(pos);
MealActivity2.modelArrayList.remove(pos);
// i need to do .notifyDataSetChanged() here but im not sure how
}
});
return convertView;
}
You can just use a interface to solve the problem
CustomAdapter
public class CustomAdapter extends BaseAdapter {
...
private CustomAdapterListener listener;
interface CustomAdapterListener{
void itemClick();
}
public CustomAdapter(Context context, CustomAdapterListener listener) {
this.context = context;
this.listener = listener;
}
MainActivity2
public class MealActivity2 extends AppCompatActivity implements CustomAdapterListener {
...
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_meal2);
...
customAdapter = new CustomAdapter(this, this);
}
#Override
public void itemClick() {
// you can do .notifyDataSetChanged() here
}
after that you can use listener to callback to Activity and do anything you want
CustomAdapter
#Override
public void onClick(View v) {
listener.itemClick();
// i need to do .notifyDataSetChanged() here but im not sure how
}
I have a class called ResultActivity which display a list of place'info. This activity request to server and receive a json object. But my activity doesn't work and I found this error
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.shameal/com.example.shameal.ResultActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'com.android.volley.toolbox.ImageLoader com.example.shameal.controller.AppController.getImageLoader()' on a null object reference
ResultActivity
public class ResultActivity extends ListActivity{
private ListView listView;
private FeedListAdapter listAdapter;
private List<FeedItem> feedItems;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
...
listView = (ListView) findViewById(R.id.list);
feedItems = new ArrayList<FeedItem>();
listAdapter = new FeedListAdapter(this, feedItems);
listView.setAdapter(listAdapter);
...
}
FeedListAdapter
public class FeedListAdapter extends BaseAdapter {
private Activity activity;
private LayoutInflater inflater;
private List<FeedItem> feedItems;
ImageLoader imageLoader = AppController.getInstance().getImageLoader();
public FeedListAdapter(Activity activity, List<FeedItem> feedItems) {
this.activity = activity;
this.feedItems = feedItems;
}
#Override
public int getCount() {
return feedItems.size();
}
#Override
public Object getItem(int location) {
return feedItems.get(location);
}
#Override
public long getItemId(int position) {
return position;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
if (inflater == null)
inflater = (LayoutInflater) activity
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
if (convertView == null)
convertView = inflater.inflate(R.layout.feed_item, null);
if (imageLoader == null)
imageLoader = AppController.getInstance().getImageLoader();
TextView name = (TextView) convertView.findViewById(R.id.name);
TextView address = (TextView) convertView
.findViewById(R.id.address);
TextView description = (TextView) convertView
.findViewById(R.id.description);
TextView rate = (TextView) convertView.findViewById(R.id.rate);
NetworkImageView image = (NetworkImageView) convertView
.findViewById(R.id.image);
FeedImageView feedImageView = (FeedImageView) convertView
.findViewById(R.id.feedImage1);
FeedItem item = feedItems.get(position);
name.setText(item.getName());
// Converting timestamp into x ago format
address.setText(item.getAddress());
// Chcek for empty status message
if (!TextUtils.isEmpty(item.getDescription())) {
description.setText(item.getDescription());
description.setVisibility(View.VISIBLE);
} else {
// status is empty, remove from view
description.setVisibility(View.GONE);
}
rate.setText(item.getRate());
image.setImageUrl(item.getImage(), imageLoader);
// Feed image
if (item.getMenu() != null || item.getMenu() != "0") {
feedImageView.setImageUrl(item.getMenu(), imageLoader);
feedImageView.setVisibility(View.VISIBLE);
feedImageView
.setResponseObserver(new FeedImageView.ResponseObserver() {
#Override
public void onError() {
}
#Override
public void onSuccess() {
}
});
} else {
feedImageView.setVisibility(View.GONE);
}
return convertView;
}
}
I think the error in this line: listAdapter = new FeedListAdapter(this, feedItems); but I can not found the solution to fix it.
Thanks for your help!
Edited: I followed this tutorial: http://www.androidhive.info/2014/06/android-facebook-like-custom-listview-feed-using-volley/. I just use the code of this tutorial but my app doesn't work.
Add one line to manifest
<application
android:name=".AppController" //this one
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme">
It seems AppController.getInstance() returns null so when you execute getImageLoader(), it fails
This is what i have tried, but my ListView doesn't get filled. I use a custom adapter because i wan't to change the background color of the items that't got a boolean value = true. I am using Android Studio.
Hope someone can help.
i'm new to android.
public class ShoppingListActivity extends ActionBarActivity {
private TextView header;
private ListView listView;
private CustomArrayAdapter arrayAdapter;
private ShoppingList shoppingList;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shopping_list);
header = (TextView)findViewById(R.id.textView2);
//get reference to ListView
listView = (ListView)findViewById(R.id.shoppingListItemsView);
shoppingList = (ShoppingList) getIntent().getSerializableExtra(Globals.CHOSENLISTKEY);
arrayAdapter = new CustomArrayAdapter(this, R.layout.custom_list_view, shoppingList.getItemList());
listView.setAdapter(arrayAdapter);
header.setText(shoppingList.toString());
Button btnShop = (Button) findViewById(R.id.btnShop);
btnShop.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(ShoppingListActivity.this, SelectStoreActivity.class);
startActivity(intent);
}
});
}
public void setData() {
for(int i = 0; i < shoppingList.getItemList().size(); i++) {
arrayAdapter.add(shoppingList.getItemList().get(i));
}
}
}
public class CustomArrayAdapter extends ArrayAdapter<Entry> {
private int resource;
private ArrayList<Entry> list;
public CustomArrayAdapter(Context context, int resource, ArrayList<Entry> list) {
super(context, resource);
this.resource = resource;
this.list = list;
}
#Override
public View getView(int position, View convertView, ViewGroup parentGroup) {
View view = convertView;
Entry entry = list.get((position));
if(view == null) {
LayoutInflater layoutInflater = ((Activity) getContext()).getLayoutInflater();
view = layoutInflater.inflate(resource, parentGroup, false);
}
TextView textView = (TextView) view.findViewById(R.id.customName);
if(entry.getItem().isBought()) {
textView.setBackgroundColor(Color.BLUE);
}
return view;
}
}
To show data in ListView rows call setText method of TextView which is return from getView method:
TextView textView = (TextView) view.findViewById(R.id.customName);
// get Text from entry and pass it to setText method
String strTextViewData=entry.getItem()...;
textView.setText(strTextViewData);
if(entry.getItem().isBought()) {
textView.setBackgroundColor(Color.BLUE);
}
I've make it more simple and updated it based on the answers in my previous post: Adding Assigned Values in Spinner NullPointerException
I have a MainAcitivty that uses a ViewPager. I have 2 Fragments in my MainActivity (FragA and FragB)
In my FragA I have a spinner. While in FragB, I have a TextView and a Button.
Now what am I trying to do is, when I select "Hello" in my spinner, my int a will have a value of 5. And when I click the Button, 5 will display in the TextView.
Here's my code:
FragA
public class FragA extends Fragment {
Spinner spinner1;
String s1;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fraga, container, false);
spinner1 = (Spinner) view.findViewById(R.id.spinner1);
ArrayAdapter<CharSequence> adapter_a = ArrayAdapter.createFromResource(getActivity(), R.array.spinner1,android.R.layout.simple_spinner_item );
spinner1.setAdapter(adapter_a);
s1 = spinner1.getSelectedItem().toString();
return view;
}
public int getInt() {
int a = 0;
if(s1.equals("Hello")) {
a = 5;
}
return a;
}
}
MainActivity
public class MainActivity extends FragmentActivity {
ViewPager viewPager = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
viewPager = (ViewPager)findViewById(R.id.pager);
FragmentManager fragmentManager = getSupportFragmentManager();
viewPager.setAdapter(new MyAdapter(fragmentManager));
}
public class MyAdapter extends FragmentStatePagerAdapter {
public MyAdapter (FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
Fragment fragment = null;
if (i == 0)
{
fragment = new FragA();
}
if (i == 1)
{
fragment = new FragB();
}
return fragment;
}
#Override
public int getCount() {
return 2;
}
}
public String get() {
FragA FragA = new FragA();
return Integer.toString(FragA.getInt());
}
}
FragB
public class FragB extends Fragment{
TextView textView;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragb, container, false);
textView = (TextView) view.findViewById(R.id.textview);
Button button = (Button) view.findViewById(R.id.button);
button.setOnClickListener(Click);
return view;
}
OnClickListener Click = new OnClickListener() {
#Override
public void onClick(View v) {
textView.setText(((MainActivity)getActivity()).get());
}
};
}
By the way, I have no problem passing the value of a from FragA to FragB when this is my code:
public int getInt() {
int a = 5;
return a;
}
But, it doesn't involve my spinner and that's not I want to do.
Here is a simple way to communicate between fragments.
In MainActivity, keep static instances of the fragments.
public static FragA fragmentA;
public static FragB fragmentB;
Now if you want to access FragB from FragA, write something similar:
((MainActivity) getActivity()).fragmentB.setSomething();
And Here is a better/proper way to communicate between fragments:
http://developer.android.com/training/basics/fragments/communicating.html