1

Я совершенно новичок в программировании на Android, но я сделаю все возможное, чтобы предоставить всю необходимую информацию. Я использую новые android.support.v7.app.ActionBarActivity и android.support.v4.app.Fragment, чтобы отобразить макет вкладок для API Android с 8 по 17. У меня возникла проблема, показывающая мои два фрагмента правильно в моей деятельности, потому что они накладываются друг на друга после того, как я выберу один из них. Итак, это мой основной вид деятельности:Android TabLayout с использованием android.support.v7.app.ActionBar и android.support.v4.app.Fragment фрагменты наложения

package it.koopa.scank; 

import android.os.Build; 
import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentTransaction; 
import android.support.v7.app.ActionBar; 
import android.support.v7.app.ActionBar.Tab; 
import android.support.v7.app.ActionBarActivity; 
import android.util.Log; 
import android.view.Menu; 

public class MainActivity extends ActionBarActivity { 

    private final static String TAG = "MainActivity"; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     //have to use getSupportActionBar from android.support.v7.app 
     ActionBar actionBar = getSupportActionBar(); 

     //hello tab 
     Tab tab = actionBar.newTab() 
       .setText(R.string.tab_hello) 
       .setTabListener(new TabListener<HelloFragment>(this, "hello", HelloFragment.class)); 
     actionBar.addTab(tab); 

     //handle content tab 
     tab = actionBar.newTab() 
       .setText(R.string.tab_send) 
       .setTabListener(new TabListener<HandleContentFragment>(this, "handle", HandleContentFragment.class)); 
     actionBar.addTab(tab); 

     actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS); 

    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
    } 

    @Override 
    public boolean onCreateOptionsMenu(Menu menu) { 
     // Inflate the menu; this adds items to the action bar if it is present. 
     getMenuInflater().inflate(R.menu.scank, menu); 
     return true; 
    } 

    public static class TabListener<T extends Fragment> implements ActionBar.TabListener { 
     private Fragment mFragment; 
     private final ActionBarActivity mActivity; 
     private final String mTag; 
     private final Class<T> mClass; 

     /** 
     * Constructor used each time a new tab is created. 
     * @param activity The host Activity, used to instantiate the fragment 
     * @param tag The identifier tag for the fragment 
     * @param clz The fragment's Class, used to instantiate the fragment 
     */ 
     public TabListener(ActionBarActivity activity, String tag, Class<T> clz) { 
      mActivity = activity; 
      mTag = tag; 
      mClass = clz; 
     } 

     @Override 
     public void onTabSelected(Tab tab, FragmentTransaction ft) { 
      mFragment = mActivity.getSupportFragmentManager().findFragmentByTag(mTag); 

      // Check if the fragment is already initialized 
      if (mFragment == null) { 
       // If not, instantiate and add it to the activity 
       mFragment = Fragment.instantiate(mActivity, mClass.getName()); 
       ft.add(getCorrectActionBarId(), mFragment, mTag); 
       Log.i(TAG, "FragID " + mFragment.getId() + ", FragTAG=" + mFragment.getTag() + " ADDED!!!"); 
      } else { 
       // If it exists, simply attach it in order to show it 
       ft.attach(mFragment); 
       Log.i(TAG, "FragID " + mFragment.getId() + ", FragTAG=" + mFragment.getTag() + " attached."); 
      } 
     } 

     @Override 
     public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
      if (mFragment != null) { 
       // Detach the fragment, because another one is being attached 
       ft.detach(mFragment); 
       Log.i(TAG, "FragID " + mFragment.getId() + ", FragTAG=" + mFragment.getTag() + " detached."); 
      } 
     } 

     @Override 
     public void onTabReselected(Tab tab, FragmentTransaction ft) { 
      // User selected the already selected tab. Usually do nothing. 
     } 
    } 

    /** 
    * Returns the correct id of the action bar 
    * @return 
    */ 
    public static int getCorrectActionBarId() { 
     int androidVersion = Build.VERSION.SDK_INT; 
     if (androidVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 
      return android.R.id.content; 
     } else { 
      return R.id.action_bar_activity_content; 
     } 
    } 

} 

И это мои два фрагмента (оба используют свой собственный xml-макет). Первый из них:

package it.koopa.scank; 

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 

public class HelloFragment extends Fragment { 
    private int index; 

    public void onCreate(Bundle savedInstanceState) {   
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     View v = inflater.inflate(R.layout.hello, container, false); 
     Log.i("HelloFragment","I'm " + HelloFragment.class); 

     return v; 

    } 
} 

и второй один:

package it.koopa.scank; 

import android.os.Bundle; 
import android.support.v4.app.Fragment; 
import android.util.Log; 
import android.view.LayoutInflater; 
import android.view.View; 
import android.view.ViewGroup; 

public class HandleContentFragment extends Fragment { 
    private int index; 

    public void onCreate(Bundle savedInstanceState) {   
     super.onCreate(savedInstanceState); 
    } 

    @Override 
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { 

     View v = inflater.inflate(R.layout.handle_content, container, false); 
     Log.i("HandleContentFragment","I'm " + HandleContentFragment.class); 

     return v; 

    } 
} 

и, как результат, если я выбираю вторую вкладку, взгляды ставятся один над другим! Я нашел аналогичный вопрос здесь Tabs using android.support.v7.app.ActionBar, но принятое решение, похоже, не работает для меня. На самом деле, в моей основной деятельности вы можете видеть, что я получить идентификатор контента с

int androidVersion = Build.VERSION.SDK_INT; 
    if (androidVersion >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) { 
     return android.R.id.content; 
    } else { 
     return R.id.action_bar_activity_content; 
    } 

но фрагменты содержимого еще overlaied (я не могу загрузить изображения из-за моей почти с нулевой репутацией). Где я ошибаюсь?

Обновление: В моей деятельности используется android:theme="@style/Theme.AppCompat.Light". Я тестирую на Nexus i9250 с Android 4.2.1

+0

Попробованная подставляя 'ft.detach (mFragment)' с 'ft.remove (mFragment)', но это не решается. Когда я нажимаю вторую вкладку, она сначала накладывается, когда я нажимаю на нее, сначала спрятал первую и удерживал вторую, а когда я снова нажимал вторую, это тоже спрятало! Я думаю, проблема в том, как я обрабатываю 'FragmentTransaction'. :( – koopa

+0

Я решил совсем по-другому, и мне это нравится еще больше, потому что теперь я могу использовать swipes тоже. После [Swipes Tab Navigation] (http://developer.android.com/training/implementing-navigation/lateral. html) и немного адаптировав его к моим потребностям, теперь он отлично работает! Он ввел небольшую проблему с соединением между моими фрагментами и моей основной деятельностью, но, по крайней мере, он работает плавно! Поэтому я могу подтвердить, что новые библиотеки могут выполнять эту работу для вкладка макет с swipes с Android 2.2 до 4.3! Nice – koopa

+0

Вы знаете, поставить код вашего решения было бы неплохо ... –

ответ

2

Это известная ошибка. Вы можете найти обходной путь здесь:

https://code.google.com/p/android/issues/detail?id=58602

+0

+1 Хорошей обходной Нижняя линия поставить это после последней строки 'onTabUnselected' методы: если (Build.VERSION.SDK_INT> = Build.VERSION_CODES.ICE_CREAM_SANDWICH) { Ьгу { Метода фиксации = tab.getClass() .getDeclaredMethod ("commitActiveTransaction"); commit.setAccessible (true); commit.invoke (вкладка); \t } catch (RuntimeException e) { throw e; \t } catch (Исключение e) { throw new RuntimeException (e); } } –

0

Имейте каждый Фрагмент, реализующий ActionBar.TabListener. Добавьте эти методы ниже вместе с другим кодом в своем фрагменте

@Override 
public void onTabSelected(Tab tab, FragmentTransaction ft) { 
    mFragment = new MyFragment(); 
    ft.add(android.R.id.content, mFragment); 
    ft.attach(mFragment);  
} 

@Override 
public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
    ft.remove(mFragment); 
} 

@Override 
public void onTabReselected(Tab tab, FragmentTransaction ft) { 
    // TODO Auto-generated method stub 

} 

Вы можете удалить прослушиватель вкладок из своего основного вида деятельности. Это обрабатывает все это.

+0

Зачем мне это нужно? Разве это не то же самое (с гораздо большим количеством кода)? Не могли бы вы объяснить? Спасибо – koopa

+0

Я считаю, что Fragment Transaction - это ошибка для вас выше. Этот способ - более чистый способ узнать, на какой вкладке вы находитесь, и что транзакция фрагмента добавлена ​​и удалена. – BigT

0

ft.show(mfragment) Просто позвоните метод в onTabSelected и ft.hide(mfragment) метод в onTabUnselected.

Посмотрите ниже

public void onTabReselected(Tab tab, FragmentTransaction ft) { 
    // TODO Auto-generated method stub 
} 

public void onTabSelected(Tab tab, FragmentTransaction ft) { 
    ft.show(mfragment); 
} 

public void onTabUnselected(Tab tab, FragmentTransaction ft) { 
    ft.hide(mfragment);  
} 
Смежные вопросы