В этом посте мы хотим показать, как использовать SlidingPaneLayout . Это интересный компонент, который можно использовать, когда мы хотим иметь многопанельное горизонтальное расположение. Этот компонент разделен на две части:
- левая сторона: мастер часть. Обычно он содержит список значений (например, контакты и т. Д.)
- Правая сторона: деталь. Он содержит подробную информацию о значениях в левой части.
Этот компонент помогает нам разделить доступное пространство экрана на две разные стороны, которые не перекрываются и могут перемещаться горизонтально. Он достаточно умен, чтобы знать, когда пора включить функцию скольжения или когда ширина экрана достаточна для размещения обеих частей.
В этом посте мы покажем, как использовать этот компонент, реализуя список закладок с одной стороны и соответствующее представление веб-контента с другой стороны. SlidingPaneLayout может использоваться с фрагментом или с другими стандартными компонентами, мы покажем, как использовать его с фрагментами. Мы должны помнить одну вещь: в нашем основном макете это должен быть корень. В конце мы хотим получить что-то похожее на картинку ниже:
Давайте начнем.
SlidingPaneLayout настроен
Первое, что нам нужно, это создание нашего основного макета:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
|
< android.support.v4.widget.SlidingPaneLayout 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 > |
Обратите внимание, что у нас есть два фрагмента: один с левой стороны называется ListBookmarkFragment, а другой с правой стороны называется ViewBookmarkFragment. В строке 1 мы имеем наш SlidingPaneLayout в качестве корневого элемента. Одна вещь, которую мы должны установить, это ширина этих двух фрагментов, в строках 9 и 16. Если ширина экрана больше, чем сумма ширины двух фрагментов, то эти два фрагмента видны одновременно, в противном случае мы должны сдвиньте влево и вправо, чтобы включить один из них.
Я не буду тратить много времени на обсуждение деталей реализации фрагментов, потому что это выходит за рамки темы, если вам интересно, вы можете взглянуть на исходный код.
Основное действие, которое содержит два фрагмента и управляет скользящей панелью, показано ниже:
1
2
3
4
5
6
7
8
9
|
public class MainActivity extends Activity { SlidingPaneLayout pane; @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); } ... } |
Все очень просто, но нам нужно реализовать больше, мы хотим «использовать» SlidingPaneLayout.
SlidingPaneLayout Listener
API дает нам возможность слушать, когда пользователь перемещает наши панели влево и вправо, чтобы мы могли правильно реагировать и реализовывать здесь нашу бизнес-логику. Мы должны реализовать интерфейс под названием SlidingPaneLayout.PanelSlideListener .
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
|
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" ); } } |
Итак, в нашей деятельности давайте добавим этот кусок кода. Как вы можете заметить в строке 1, мы реализуем этот интерфейс и получаем уведомление, когда левая панель закрыта, открыта и когда пользователь скользит. Нас больше интересуют первые два события (закрытое и открытое). Затем мы должны зарегистрировать нашего слушателя:
1
2
3
4
5
6
7
8
9
|
... @Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); setContentView(R.layout.activity_main); pane = (SlidingPaneLayout) findViewById(R.id.sp); pane.setPanelSlideListener( new PaneListener()); } .... |
Запустив код, мы можем заметить, что когда левая панель закрывается или открывается в журнале, мы получаем сообщение. Теперь мы можем получить уведомление о двух основных событиях. Мы можем использовать его, например, для правильной настройки панели действий.
SlidingPaneLayout и Actionbar
Используя слушателя, мы можем правильно настроить панель действий. Этот аспект очень важен, потому что мы можем изменить значки панели действий в соответствии с открытой панелью. Другими словами, когда левая панель открыта, мы можем показать некоторые значки, а когда она закрыта, мы можем показать другие значки. Для этого мы просто реализуем нашу логику внутри методов слушателя:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
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" ); } } |
Мы используем setHasOptionMenu для включения и выключения меню фрагментов (строка 7,8,14,15). Запустив код мы имеем:
|
|
Как вы можете заметить, когда вы открываете левую панель, значки панели действий меняются.
Межфрагментное общение
Еще одну вещь, которую нам нужно объяснить: как обмениваться информацией между фрагментами. Другими словами, мы хотим, чтобы когда пользователь нажимал на список закладок слева, соответствующая веб-страница открывалась справа.
Чтобы получить его, мы можем просто создать наш интерфейс, который действует как слушатель, и позволить нашей основной деятельности реализовать его. Таким образом, когда пользователь выбирает элемент в списке на левой панели, мы уведомляем событие о главном действии, которое по очереди вызывает правильный метод во фрагменте, который обрабатывает правую панель. Итак, мы имеем:
1
2
3
|
public interface BookmarkListener { public void onChangeBookmark(String bookmark); } |
Интерфейс. Во фрагменте, который обрабатывает левую панель, мы имеем:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
.... @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; } ... |
В основном виде деятельности мы имеем:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
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); } .... } |
В конце мы имеем:
Последнее, что нам нужно позаботиться, это правильно настроить значки при первом запуске приложения. В этом случае нам нужно добавить этот фрагмент кода в метод onCreate:
01
02
03
04
05
06
07
08
09
10
11
12
13
14
|
public class MainActivity extends Activity implements BookmarkListener{ 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 ); } } |
- Доступен исходный код @ github