Android SlidingPaneLayout
SlidingPaneLayout and Fragments
Action bar
- left side: The master part. It usually contains a list of values (i.e. Contacts and so on)
- right side: The detail part. It contains the details of the values in the left side.
In this post, we will show how to use this component implementing a bookmark list in one side and the corresponding web content view in the other side. SlidingPaneLayout can be used with fragment or with other standard components, we will show how to use it with fragments. One thing we have to remember is that in our main layout it has to be the root. At the end, we want to have something like the picture shown below:
Let’s start.
SlidingPaneLayout set up
The first thing we need is creating our main layout:<android.support.v4.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/sp" >
<!-- Left side pane. (Master) -->
<fragment android:id="@+id/leftpane"
android:name="com.survivingwithandroid.slidingpanelayout.ListBookmarkFragment"
android:layout_width="190dp"
android:layout_height="match_parent"
android:layout_gravity="left" />
<!-- Right side page. (Slave) -->
<fragment android:id="@+id/rightpane"
android:name="com.survivingwithandroid.slidingpanelayout.ViewBookmarkFragment"
android:layout_width="350dp"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_weight="1"
/>
</android.support.v4.widget.SlidingPaneLayout>
Notice we have two fragment: one on the left side called ListBookmarkFragment and the other one on the right side called ViewBookmarkFragment. At line 1, we have our SlidingPaneLayout as the root element. One thing we have to set up is the width of this two fragment, at line 9 and 16. If the screen width is more than the sum of the two fragments width then the two fragments are visible at the same time, otherwise we have to slide left and right to enable one of them.
I won’t spend much time talking about fragment implementation details because is out of the topic, if you are interested you can give a look at the source code.
The main activity that holds the two fragments and handle the sliding pane is shown below:
public class MainActivity extends Activity {
SlidingPaneLayout pane;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
...
}
Everything is very simple, but we need to implement more thing is we want to “use” the SlidingPaneLayout.
SlidingPaneLayout Listener
The api gives us the capability to listen when the user slide our panes left and right so that we can react in the right way and implement here our business logic. We have to implements an interface called SlidingPaneLayout.PanelSlideListener.private class PaneListener implements SlidingPaneLayout.PanelSlideListener {
@Override
public void onPanelClosed(View view) {
System.out.println("Panel closed");
}
@Override
public void onPanelOpened(View view) {
System.out.println("Panel opened");
}
@Override
public void onPanelSlide(View view, float arg1) {
System.out.println("Panel sliding");
}
}
So in our Activity let’s add this piece of code. As you can notice at line 1 we implement that interface and we get notified when the left panel is closed, is opened and when the user is sliding. We are more interested on the first two events (closed and opened). Then we have to register our listener:
...
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pane = (SlidingPaneLayout) findViewById(R.id.sp);
pane.setPanelSlideListener(new PaneListener());
}
....
Running the code we can notice that when the left pane is closed or opened in the log we get the message. Now we can a way to get notified about the main two events. We can use it to set up correctly the action bar, for example.
SlidingPaneLayout and Actionbar
Using the listener, we can setup correctly the action bar. This aspect is very important because we can change the action bar icons according to the opened panel. In other words, when the left panel is open we can show some icons and when it is closed we can show other icons. To do it, we have simply implement our logic inside the listener methods:private class PaneListener implements SlidingPaneLayout.PanelSlideListener {
@Override
public void onPanelClosed(View view) {
System.out.println("Panel closed");
getFragmentManager().findFragmentById(R.id.leftpane).setHasOptionsMenu(false);
getFragmentManager().findFragmentById(R.id.rightpane).setHasOptionsMenu(true);
}
@Override
public void onPanelOpened(View view) {
System.out.println("Panel opened");
getFragmentManager().findFragmentById(R.id.leftpane).setHasOptionsMenu(true);
getFragmentManager().findFragmentById(R.id.rightpane).setHasOptionsMenu(false);
}
@Override
public void onPanelSlide(View view, float arg1) {
System.out.println("Panel sliding");
}
}
We use setHasOptionMenu to turn on and off the fragment menu (line 7,8,14,15). Running the code we have:
As you can notice when you open the left panel the action bar icons change.
Inter fragment communication
One more thing we need to explain: how to exchange information between fragments. In other word, we want when user clicks on a bookmark list on the left side the corresponding web page is opened on the right side.To get it, we can simply create our interface that acts as a listener and let our main activity implement it. So that when user select an item in the list on the left panel we notify the event to the main activity, that in turns call the right method in fragment that handles the right panel. So we have:
public interface BookmarkListener {
public void onChangeBookmark(String bookmark);
}
The interface. In the fragment that handles the left panel we have:
....In the main activity, we have:
@Override
public void onAttach(Activity activity) {
// It's time we check if our activity implements the right inteface
if (! (activity instanceof BookmarkListener) )
throw new ClassCastException();
super.onAttach(activity);
}
...
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.leftside_layout, container, true);
ListView lView = (ListView) v.findViewById(R.id.bookList);
LinkAdapter la = new LinkAdapter(bookmarkList, getActivity());
lView.setAdapter(la);
lView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
( (BookmarkListener) getActivity()).onChangeBookmark( bookmarkList.get(position).link );
}
});
setHasOptionsMenu(true);
return v;
}
...
public class MainActivity extends Activity implements BookmarkListener{
....
@Override
public void onChangeBookmark(String bookmark) {
// We get notified when user clicks on a bookmark in the ListBookmarkFragment
System.out.println("Bookmark ["+bookmark+"]");
ViewBookmarkFragment f = (ViewBookmarkFragment) getFragmentManager().findFragmentById(R.id.rightpane);
f.setBookmark(bookmark);
}
....
}
At the end we have:
The last thing we need to take care is to set up correctly the icons the first time the app is launched. In this case we need to add this piece of code to the onCreate method:
public class MainActivity extends Activity implements BookmarkListener{Source code available @ github.
SlidingPaneLayout pane;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
pane = (SlidingPaneLayout) findViewById(R.id.sp);
pane.setPanelSlideListener(new PaneListener());
if (!pane.isSlideable()) {
getFragmentManager().findFragmentById(R.id.leftpane).setHasOptionsMenu(false);
getFragmentManager().findFragmentById(R.id.rightpane).setHasOptionsMenu(true);
}
}
0 comments:
Post a Comment