Привет!
Меня зовут Никита. Я занимаюсь разработкой под Android. Хотел бы написать продолжение публикации «Как я с лагом Navigation Drawer боролся», где автор рассказывал, что обойти лаг Navigation Drawer при загрузке фрагмента можно через поток, который будет спать 300мс, и, соответственно, за это время должен успеть загрузиться фрагмент, а после закрыться NavigationDrawer.
Но, как я посчитал, это не наилучший метод решения проблемы, ибо для каждого устройства может понадобиться разное время, так как время работы потока зависит напрямую от характеристик устройства: чем оно слабее — тем больше времени требуется и наоборот.
Huawei Honor 3x (8 ядер — 1.7 ГГц)
Конечно же, устройства неслабые (для тестового приложения), но одноядерного бюджетного смартфона у меня не имеется, а чтобы проверить работоспособность своего метода, добавил в фрагменты различные элементы (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 — сайт Александра Климова»