I would like to get the Context of another activity where I created an object (an adapter that contains a list of objects I need to display in the second activity).
public class Activity1 extends Activity {
private Context context = this;
private GridView gridView;
private MyAdapter myAdapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.myLayout);
myAdapter = new MyAdapter(context);
gridView = (GridView) findViewById(R.id.mylayout2);
gridView.setAdapter(myAdapter);
}
public class Activity2 extends Activity {
Context context = this;
private MyAdapter myAdapter;
private GridView gridView;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.mylayout3);
//what I want to do
cardAdapter = new CardAdapter(manageCardContext); //I want this adapter to be the one in Activity1
gridView.setAdapter(myAdapter);
}
How can I do that ?
I created an adapter in Activity1 that contains a list of objects.
Only create an Adapter in the activity that will use the Adapter, and only use that Adapter in that activity.
With the adapter I can display the list of objects, but I need to display them in Activity2
Then move the adapter-creation code from Activity1 to Activity2. Or, if you need the same sort of adapter in both places, copy the code, or have both activities inherit from some base class that has the adapter-creation code.
In similar vein to CommonsWare suggestion, I defined a public adapter class outside the Activity, just in a class file (sorry, this is C# code, but you should get the point if you already written yer adapter)
CommonAdapter.java
public class CommonAdapter : ArrayAdapter<AttachmentDetails>
{
private readonly List<AttachmentDetails> _attachments;
public CommonAdapter( Context context, List<AttachmentDetails> attachments )
: base( context, 0, attachments )
{
_attachments = attachments;
}
public override View GetView( int position, View convertView, ViewGroup parent )
{
...
}
}
and the instantiate wherever i need it
_recordAttachmentsGrid.Adapter = new CommonAdapter(this.ApplicationContext, Model.Attachments);
Related
My fragment:
public class FragmentSort extends Fragment {
#BindView(R.id.sortRecyclerView)
RecyclerView sortRecyclerView;
protected RecyclerView.Adapter adapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(layoutResId, container, false);
adapter = new StoreListItemAdapter(getActivity(), collection);
sortRecyclerView.setAdapter((RecyclerView.Adapter) adapter);
return rootView;
}
#Subscribe
public void onStoreClickEvent(Store store) {
Debug.d(TAG, "onStoreClickEvent: store = " + store);
handleFilterItemSelect(store.getAddress());
}
}
Here my custom adapter:
public class StoreListItemAdapter extends RecyclerView.Adapter {
private Context context;
private List<?> data = new ArrayList<>();
public DataBindingRecyclerViewAdapter(Context context, List<?> data) {
this.context = context;
this.data = data;
}
public void onClick(Store store) {
EventBus.getDefault().post(store);
}
}
When click on some item in list then call method onClick().
So I need my fragment to handle click of item.
To to do this I use EventBus.
After click I call
EventBus.getDefault().post(store);
And as result in fragment call method:
onStoreClickEvent(Store store)
So this is my model to communicate between my custom fragment and my custom adapter.
It's work. Fine.
The quesion is: Is this a best approach for communicate between fragment and adapter?
P.S. My custom adapter can use by fragment, activity or custom view.
An alternative would be to create a listener interface like this:
public interface OnStoreItemClickListener {
public void onStoreItemClicked(Store item);
}
Then, in your Adapter, you declare a field of type OnStoreItemClickListener and you create a setter method for it.
When you detect a click, you simply check if your listener is set and call the onStoreItemClicked() method.
You can register a listener via the setter from wherever you need.
My fragment:
public class FragmentSort extends Fragment {
#BindView(R.id.sortRecyclerView)
RecyclerView sortRecyclerView;
protected RecyclerView.Adapter adapter;
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(layoutResId, container, false);
adapter = new StoreListItemAdapter(getActivity(), collection);
sortRecyclerView.setAdapter((RecyclerView.Adapter) adapter);
return rootView;
}
#Subscribe
public void onStoreClickEvent(Store store) {
Debug.d(TAG, "onStoreClickEvent: store = " + store);
handleFilterItemSelect(store.getAddress());
}
}
Here my custom adapter:
public class StoreListItemAdapter extends RecyclerView.Adapter {
private Context context;
private List<?> data = new ArrayList<>();
public DataBindingRecyclerViewAdapter(Context context, List<?> data) {
this.context = context;
this.data = data;
}
public void onClick(Store store) {
EventBus.getDefault().post(store);
}
}
When click on some item in list then call method onClick().
So I need my fragment to handle click of item.
To to do this I use EventBus.
After click I call
EventBus.getDefault().post(store);
And as result in fragment call method:
onStoreClickEvent(Store store)
So this is my model to communicate between my custom fragment and my custom adapter.
It's work. Fine.
The quesion is: Is this a best approach for communicate between fragment and adapter?
P.S. My custom adapter can use by fragment, activity or custom view.
An alternative would be to create a listener interface like this:
public interface OnStoreItemClickListener {
public void onStoreItemClicked(Store item);
}
Then, in your Adapter, you declare a field of type OnStoreItemClickListener and you create a setter method for it.
When you detect a click, you simply check if your listener is set and call the onStoreItemClicked() method.
You can register a listener via the setter from wherever you need.
My question is a design question. I have two custom fragments CustomFrag1 and CustomFrag2. Both these fragments have a method swapCursor.
CustomFrag1:
public class CustomFrag1 extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
// .... code
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// .... code
MyAdapter mAdapter = new MyAdapter();
// .... code
}
public static void swapCursor(final Cursor cursor, Activity ctx){
// .... code
}
}
CustomFrag2:
public class CustomFrag1 extends Fragment {
#Override
public void onCreate(Bundle savedInstanceState) {
// .... code
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// .... code
MyAdapter mAdapter = new MyAdapter();
// .... code
}
public static void swapCursor(final Cursor cursor, Activity ctx){
// .... code
}
}
I don't want to make a seperate adapter class for each fragment. I do however, want to call swapCursor in the adapter class. If the adapter has been instantied from CustomeFrag1 I want swapCurosr to swap the cursor in CustomFrag1. If the adapter has been instantiated from CustomeFrag2 I want swapCurosr to swap the cursor in CustomFrag2.
Is it possible to pass in an instance of the Fragment...
MyAdapter mAdapter = new MyAdapter(this);
...and somehow represent that instance with a generic variable that has swapCursor defined as a method? If not, what strategy can I use? Interfaces? Generics? Something?
edit
I tried inheriting swapCursor but that would just swap out the cursor out on the parent and not the child.
swapCursor shouldn't be static at the first place, because there's no inheritance for static methods.
You could create an interface (SwappableCursor as a name hint) which has a method swapCursor, then all of your fragments can implement this interface. So that you'll have to implement swapCursor.
In MyAdapter's constructor you can add a parameter which has the type of your interface (SwappableCursor). You'll be able to invoke swapCursor method.
Use interfaces.
public interface SwapFrag {
public swapCursor(final Cursor cursor, Activity ctx);
}
your fragments need to implement SwapFrag:
public class CustomFrag1 extends Fragment implements SwapFrag
and also need to implements the swapCursor method.
#Override
public static void swapCursor(final Cursor cursor, Activity ctx) {
...
}
I have a listView and I need when the user click on the some item it shows 5 images and when he click on another item it shows 5 different images with the ViewPager.. I don't know how to change the image array that will change with each item of the listView? any ideas to do that?
My code :
public class SwipeActivity extends Activity{
ViewPager vp;
Table_customSwipeAdapter adapter;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_swipe);
vp=(ViewPager)findViewById(R.id.view_pager);
adapter=new Table_customSwipeAdapter(this);
vp.setAdapter(adapter);
}
public void imageSwipe(View view){
Toast toast = Toast.makeText(getApplicationContext(), "Open Link!", Toast.LENGTH_SHORT);
toast.show();
}
}
class Table_customSwipeAdapter extends PagerAdapter{
int[] image_resources={R.drawable.i1,R.drawable.i2,R.drawable.i3,R.drawable.i4,R.drawable.i5};
private Context ctx;
private LayoutInflater layoutInflater;
public Table_customSwipeAdapter(Context ctx) {
this.ctx=ctx;
}
#Override
public int getCount() {
return image_resources.length;
}
#Override
public boolean isViewFromObject(View arg0, Object arg1) {
// TODO Auto-generated method stub
return (arg0==(LinearLayout)arg1);
}
public Object instantiateItem(ViewGroup container, int position){
layoutInflater=(LayoutInflater)ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View item_view=layoutInflater.inflate(R.layout.activity_table_custom_swipe_adapter, container,false);
ImageView imageView=(ImageView)item_view.findViewById(R.id.image_view);
TextView textView=(TextView)item_view.findViewById(R.id.image_count);
imageView.setImageResource(image_resources[position]);
textView.setText("Image "+(position+1));
container.addView(item_view);
return item_view;
}
public void destroyItem(ViewGroup container, int position, Object object){
container.removeView((LinearLayout)object);
}
}
Here ViewPager it shows the same 5 images..
//In your Table_customSwipeAdapter make these chages in contructor get the image array e.g
class Table_customSwipeAdapter extends PagerAdapter{
int[] image_resources;
private Context ctx;
private LayoutInflater layoutInflater;
public Table_customSwipeAdapter(Context ctx, int[] image_resources) {
this.ctx=ctx;
this.image_resources=image_resources
}
// In your SwipeActivity while calling the constructor pass the int array
adapter=new Table_customSwipeAdapter(this,image_resources);
You can have a callback interface defined in the ViewPager that the Activity can implement. At instantiateItem, the ViewPager can call a method in Activity through this callback to obtain the ListView position that was clicked. Based on that information it can show the images.
Its showing the same images because here
imageView.setImageResource(image_resources[position]);
You are setting the same images
First of all you need to create different Lists of images that you want to display on each different click in Activity like
public class SwipeActivity extends Activity{
ViewPager vp;
Table_customSwipeAdapter adapter;
int[] image_resources1 ={R.drawable.i1,R.drawable.i2,R.drawable.i3};
int[] image_resources2 ={R.drawable.i4,R.drawable.i5};
and then in your adapter
class Table_customSwipeAdapter extends PagerAdapter{
int[] image_resources;
private Context ctx;
private LayoutInflater layoutInflater;
public Table_customSwipeAdapter(Context ctx, int[] image_resources) {
this.ctx=ctx;
this.image_resources = image_resources;
}
and then pass different list to your adapter from your activity on each click like this
vp=(ViewPager)findViewById(R.id.view_pager);
//HERE YOU WILL PASS WHICHEVER LIST YOU WANT TO DISPLAY e.g image_resources1 or image_resources2 or ANY OTHER
adapter=new Table_customSwipeAdapter(this,image_resources);
vp.setAdapter(adapter);
Hope it helps
I have created an external class, NotesView, which extends View for implementation in my MainActivity.
This View requires information passed from the MainActivity, so its constructor takes an ArrayList of Note objects.
public class NotesView extends View {
private ArrayList<Note> notes = new ArrayList<>();
public NotesView(Context context, ArrayList<Note> notes) {
super(context);
this.notes = notes;
}
In my MainActivity, I used the following code to display this view: (Trying to add a CustomView in the Design tab of the layout does not work as I cannot supply the ArrayList parameter)
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
notesView = new NotesView(this, noteList);
setContentView(notesView);
}
Unfortunately, I am now not able to add any objects at all through the Design view of the layout, I assume this is because I have used setContentView. I do not wish to add all my components programmatically, is there a way around this?
Calling setContentView replaces the whole view for your layout. That means if you call setContentView twice, whatever was added to the screen from the first call is overridden and no longer accessible.
There are multiple answers to your question, here is a pragmatic one:
What is inside R.layout.activity_main? Let's assume there is a FrameLayout / LinearLayout / RelativeLayout with id root
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ViewGroup rootView = (ViewGroup) findViewById(R.id.root);
notesView = new NotesView(this, noteList);
rootView.addView(notesView);
}
Another choice, you could also take your custom view to have a setter if you wish:
public class NotesView extends View {
private final List<Note> notes = new ArrayList<>();
public NotesView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void replaceNotes(List<Note> notes) {
this.notes.clear();
this.notes.addAll(notes);
}
Then you can add this view in your XML file (R.layout.activity_main) and call the setter method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NotesView notesView = (NotesView) findViewById(R.id.notes);
notesView.replaceNotes(noteList);
}
You can add a setter function to your NotesView class:
public class NotesView extends View {
private ArrayList<Note> notes;
public NotesView(Context context) {
super(context);
}
public void setNotes(ArrayList<Note> notes) {
this.notes = notes;
}
}
And then set it in the main activity:
NotesView notesView = (NotesView) findViewById(R.id.yourNotesView);
notesView.setNotes(noteList);
By the way I recommend Butterknife to cast views in your layout without the verbose findViewByIds, declarations, onXListeners, etc.