- PVSM.RU - https://www.pvsm.ru -
Привет!
Меня зовут Никита. Я занимаюсь разработкой под Android. Хотел бы написать продолжение публикации «Как я с лагом Navigation Drawer боролся» [1], где автор рассказывал, что обойти лаг Navigation Drawer при загрузке фрагмента можно через поток, который будет спать 300мс, и, соответственно, за это время должен успеть загрузиться фрагмент, а после закрыться NavigationDrawer.
Но, как я посчитал, это не наилучший метод решения проблемы, ибо для каждого устройства может понадобиться разное время, так как время работы потока зависит напрямую от характеристик устройства: чем оно слабее — тем больше времени требуется и наоборот.
Конечно же, устройства неслабые (для тестового приложения), но одноядерного бюджетного смартфона у меня не имеется, а чтобы проверить работоспособность своего метода, добавил в фрагменты различные элементы (ImageView с картинкой в разрешении HD, TextView, TabHost и другие), потому что если фрагмент будет пустой, то AsyncTask даже не понадобится, ибо ничего загружаться не будет.
Ну, давайте приступим:
Создадим разметку главного экрана main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<!-- The main content view -->
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent" />
<!-- The navigation drawer -->
<ListView
android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:background="#ff396c99"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" />
</android.support.v4.widget.DrawerLayout>
</RelativeLayout>
Теперь разметку фрагмента start_fragment.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/photo"/>
</LinearLayout>
Теперь перейдем к MainActivity:
public class MainActivity extends Activity {
private ListView mListView;
private DrawerLayout mDrawerLayout;
private FrameLayout mContainer;
private ActionBarDrawerToggle mDrawerToggle;
CharSequence mTitle;
MyAsyncTask mytask;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mListView = (ExpandableListView) findViewById(R.id.left_drawer);
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
mContainer = (FrameLayout) findViewById(R.id.container);
mTitle = getActionBar().getTitle();
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START); // установка тени к NavDrawer
final String[] names = new String[] {
"Фрагмент 1",
"Фрагмент 2",
"Фрагмент 3"
};
// используем адаптер данных
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, names);
mListView.setAdapter(adapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View itemClicked, int position,
long id) {
switch (position){
case 0:
mytask = new MyAsyncTask();
mytask.execute(new StartFragment()); //выбираете фрагмент, который хотите загрузить
break;
case 1:
mytask = new MyAsyncTask();
mytask.execute(new StartFragment2());
break;
default:;
}
}
});
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
invalidateOptionsMenu();
}
};
// Set the drawer toggle as the DrawerListener
mDrawerLayout.setDrawerListener(mDrawerToggle);
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
if (savedInstanceState == null){
/*Здесь загрузим стартовый фрагмент, если нужно*/
}
}
/*
*** Меню
*/
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mDrawerToggle.onOptionsItemSelected(item)) {
return true;
}
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
boolean drawerOpen = mDrawerLayout.isDrawerOpen(mListView);
return super.onPrepareOptionsMenu(menu);
}
@Override
protected void onPostCreate(Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
mDrawerToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mDrawerToggle.onConfigurationChanged(newConfig);
}
/*
* Собственно сам AsyncTask
* */
private class MyAsyncTask extends AsyncTask<Fragment, Integer, Fragment> {
@Override
protected Fragment doInBackground(Fragment... fragment) {
FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager
.beginTransaction();
fragment[0].setRetainInstance(true);
fragmentTransaction.replace(R.id.container, fragment[0]);
fragmentTransaction.commit();
return fragment[0];
}
@Override
protected void onPostExecute(Fragment fragment) {
super.onPostExecute(fragment);
mDrawerLayout.closeDrawers();
}
}
}
Не буду приводить пример Java кода фрагмента, ибо вы его сможете настроить сами и добавить свои элементы.
Пока каких-либо багов не обнаружено, приложение не вылетает и NavigationDrawer закрывается плавно.
Однако хочу отметить, что возможны зависания на слабых устройствах, если фрагмент действительно громоздкий, но в таком случае я бы добавил ProgressBar, который показывал бы, что приложение не зависло.
Был использован материал: «AsyncTask — сайт Александра Климова» [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/pesochnitsa/81024
Ссылки в тексте:
[1] «Как я с лагом Navigation Drawer боролся»: http://habrahabr.ru/post/220835/
[2] «AsyncTask — сайт Александра Климова»: http://developer.alexanderklimov.ru/android/theory/asynctask.php
Нажмите здесь для печати.