Reputation: 145
I am making a history activity that implements fragments with a For cycle into a linear layout.
In that history activity, I have a horizontal scrollbar that when I click a view it returns the index of the view. Then I send it by a listener to a fragment, but the problem is that I have multiple fragments, and only one fragment is getting the response. I want all of the fragments to receive the call. How do I fix this?
This is the for that I have in my history activity:
OnCustomEventListener mListener;
View.OnClickListener myClickListener = new OnClickListener(){
@Override
public void onClick(View v) {
// here is where I get the index of the scroll bar
indexChild = ((ViewGroup) uno.getParent()).indexOfChild(v);
// here is where I call the method of the interface
mListener.onEvent(indexChild);
}};
// here is where i set the fragments to the linear layout
for(i = 0; i<cant;i++){
if(Utils.History_Thread == false) {
final Fragment Frag = new PlaceholderFragment();
Bundle bundle = new Bundle();
bundle.putInt("dispositivo", dev);
bundle.putInt("row",i);
Frag.setArguments(bundle);
getSupportFragmentManager().beginTransaction()
.add(R.id.container, Frag).commit();
try {
sleep(150);
} catch (InterruptedException e) {
e.printStackTrace();
}
} else {
break;
}
}
This is the fragment:
public class PlaceholderFragment extends org.holoeverywhere.app.Fragment
implements ScrollViewListener,OnCustomEventListener {
private static LinearLayout padre;
OnHeadlineSelectedListener mCallback;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
more.. implementations
// here is when i implement the listener of mListener of History Activ.
((History)activity).mListener = this;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " implement headlistener);
}
}
// here I override the method and set the background color of the view I want
@Override
public void onEvent(int index) {
padre.getChildAt(index).setBackgroundColor(Color.GREEN);
}
}
Only one of the fragments is being called, so only that fragment's view is painted.
interface
public interface OnCustomEventListener{
public void onEvent(int index);
}
Here is a picture of what is happening:
I want all to be painted with green.
Actually the last fragment of the for is painted, maybe this help.
Upvotes: 1
Views: 1040
Reputation: 753
I usually like to use a library like greenrobot's EventBus. It really makes communication between different components very clean, and also makes it easier dealing with background/UI threads. It saves a lot of repetitive code and interfaces and also tested by the community using it.
Example:
// sender (activity or other)
EventBus.getDefault().post(new ClickEvent(index));
// receiver (fragments, or other)
EventBus.getDefault().register(this); // in onCreate()
EventBus.getDefault().unregister(this); // in onDestroy()
public void onEvent(ClickEvent clickEvent) { ... }
Slide with additional info: http://www.slideshare.net/greenrobot/eventbus-for-android-15314813
Upvotes: 0
Reputation: 5012
Firstly, please format your code correctly. It's a mess and very difficult to read right now.
Also, you've got getSupportFragmentManager().beginTransaction().add(R.id.container, Frag).commit();
inside your for loop
. You are performing a completely new transaction for every fragment addition. Are you sure that's how you want to do it?
You could be doing something more like:
FragmentTransaction fragTrans = getSupportFragmentManager().beginTransaction();
for (...) {
....
fragTrans.add(...);
}
fragTrans.commit();
But as for your question:
You could send the message (call onEvent()) for each Fragment manually but then you'd have to keep track of every one you use. Not so difficult with only a few but if you start to use many then I guess it could get hard to follow before too long.
What I might do is collect all the Fragments into a collection and iterate over them inside that. Use a few Interfaces to make sure everything has the right methods and a reminder to the Fragments to register themselves if they should.
public interface MyActivityInterface
{
public void registerOnEventListener(MyFragmentInterface myFragment);
public void triggerEvent(int index);
}
public interface MyFragmentInterface
{
public void onEvent(int index);
public void registerSelf();
}
public class MyActivity
extends Activity
implements MyActivityInterface
{
private OnEventListenerCollection eventListeners;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//...
eventListeners = new OnEventListenerCollection();
}
@Override
public void registerOnEventListener(MyFragmentInterface myFragment)
{
eventListeners.add(myFragment);
}
@Override
public void triggerEvent(int index)
{
eventListeners.invokeOnEvents(index);
}
}
public class MyFragment
extends Fragment
implements MyFragmentInterface
{
private MyActivityInterface myActivity;
@Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try
{
myActivity = (MyActivityInterface) activity;
}
catch (ClassCastException e)
{
Log.e("TAG", "Parent Activity must implement MyActivityInterface");
throw e;
}
registerSelf();
}
@Override
public void onEvent(int index)
{
// do whatever it is you wanted to trigger
}
@Override
public void registerSelf()
{
myActivity.registerOnEventListener(this);
}
}
public class OnEventListenerCollection
{
private List<MyFragmentInterface> myFragments;
public OnEventListenerCollection()
{
myFragments = new ArrayList<MyFragmentInterface>();
}
public void add(MyFragmentInterface fragment)
{
myFragments.add(fragment);
}
public void invokeOnEvents(int index)
{
for (MyFragmentInterface fragment : myFragments)
{
fragment.onEvent(index);
}
}
}
Upvotes: 1