티스토리 뷰
Stack Overflow에 자주 검색, 등록되는 문제들과 제가 개발 중 찾아 본 문제들 중에서 나중에도 찾아 볼 것 같은 문제들을 정리하고 있습니다.
Stack Overflow에서 가장 먼저 확인하게 되는 가장 높은 점수를 받은 Solution과 현 시점에 도움이 될 수 있는 가장 최근에 업데이트(최소 점수 확보)된 Solution을 각각 정리하였습니다.
아래 word cloud를 통해 이번 포스팅의 주요 키워드를 미리 확인하세요.
Getting the current Fragment instance in the viewpager
뷰페이저(viewpager) 내 현재 프래그먼트 인스턴스(instance) 가져오기
문제 내용
Below is my code which has 3 Fragment classes
each embedded with each of the 3 tabs on ViewPager
. I have a menu option. As shown in the onOptionsItemSelected()
, by selecting an option, I need to update the fragment that is currently visible. To update that I have to call a method which is in the fragment class. Can someone please suggest how to call that method?
아래는 뷰페이저의 3개 탭(tab) 중 하나에 포함된 3개의 프래그먼트 클래스가 있는 코드입니다. 메뉴 옵션이 있습니다. onOptionsItemSelected()에서 보여지듯이 옵션을 선택하면 현재 보이는 프래그먼트를 업데이트해야 합니다. 업데이트를 위해 프래그먼트 클래스에 있는 메소드를 호출해야 합니다. 해당 메소드를 호출하는 방법을 알려주세요.
public class MainActivity extends ActionBarActivity {
ViewPager ViewPager;
TabsAdapter TabsAdapter;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ViewPager = new ViewPager(this);
ViewPager.setId(R.id.pager);
setContentView(ViewPager);
final ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
//Attaching the Tabs to the fragment classes and setting the tab title.
TabsAdapter = new TabsAdapter(this, ViewPager);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass1"),
FragmentClass1.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass2"),
FragmentClass2.class, null);
TabsAdapter.addTab(bar.newTab().setText("FragmentClass3"),
FragmentClass3.class, null);
if (savedInstanceState != null) {
bar.setSelectedNavigationItem(savedInstanceState.getInt("tab", 0));
}
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.addText:
**// Here I need to call the method which exists in the currently visible Fragment class**
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putInt("tab", getSupportActionBar().getSelectedNavigationIndex());
}
public static class TabsAdapter extends FragmentPagerAdapter
implements ActionBar.TabListener, ViewPager.OnPageChangeListener {
private final Context mContext;
private final ActionBar mActionBar;
private final ViewPager mViewPager;
private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();
static final class TabInfo {
private final Class<?> clss;
private final Bundle args;
TabInfo(Class<?> _class, Bundle _args) {
clss = _class;
args = _args;
}
}
public TabsAdapter(ActionBarActivity activity, ViewPager pager) {
super(activity.getSupportFragmentManager());
mContext = activity;
mActionBar = activity.getSupportActionBar();
mViewPager = pager;
mViewPager.setAdapter(this);
mViewPager.setOnPageChangeListener(this);
}
public void addTab(ActionBar.Tab tab, Class<?> clss, Bundle args) {
TabInfo info = new TabInfo(clss, args);
tab.setTag(info);
tab.setTabListener(this);
mTabs.add(info);
mActionBar.addTab(tab);
notifyDataSetChanged();
}
@Override
public void onPageScrollStateChanged(int state) {
// TODO Auto-generated method stub
}
@Override
public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
// TODO Auto-generated method stub
}
@Override
public void onPageSelected(int position) {
// TODO Auto-generated method stub
mActionBar.setSelectedNavigationItem(position);
}
@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
Object tag = tab.getTag();
for (int i=0; i<mTabs.size(); i++) {
if (mTabs.get(i) == tag) {
mViewPager.setCurrentItem(i);
}
}
tabPosition = tab.getPosition();
}
@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
// TODO Auto-generated method stub
}
@Override
public Fragment getItem(int position) {
TabInfo info = mTabs.get(position);
return Fragment.instantiate(mContext, info.clss.getName(), info.args);
}
@Override
public int getCount() {
return mTabs.size();
}
}
}
Suppose below is the fragment class with the method updateList()
I want to call:
아래는 호출하려는 updateList() 메소드가 있는 프래그먼트 클래스입니다.
public class FragmentClass1{
ArrayList<String> originalData;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View fragmentView = inflater.inflate(R.layout.frag1, container, false);
originalData = getOriginalDataFromDB();
return fragmentView;
}
public void updateList(String text)
{
originalData.add(text);
//Here I could do other UI part that need to added
}
}
높은 점수를 받은 Solution
by selecting an option, I need to update the fragment that is currently visible.
단순한 방법은 FragmentPagerAdapter 구현과 관련된 트릭을 사용하는 것입니다.
A simple way of doing this is using a trick related to the FragmentPagerAdapter
implementation:
이를 위한 간단한 방법은 FragmentPagerAdapter 구현과 관련된 트릭을 사용하는 것입니다.
case R.id.addText:
Fragment page = getSupportFragmentManager().findFragmentByTag("android:switcher:" + R.id.pager + ":" + ViewPager.getCurrentItem());
// based on the current position you can then cast the page to the correct
// class and call the method:
if (ViewPager.getCurrentItem() == 0 && page != null) {
((FragmentClass1)page).updateList("new item");
}
return true;
Please rethink your variable naming convention, using as the variable name the name of the class is very confusing(so no ViewPager ViewPager
, use ViewPager mPager
for example).
변수명 지정 규칙에 대해 다시 생각해보세요. 변수 이름으로 클래스 이름을 사용하면 매우 혼란스러울 수 있습니다. (예: ViewPager ViewPager 사용하지 말고, ViewPager mPager와 같이 사용하세요.)
가장 최근 달린 Solution
In my previous implementation I stored a list of child Fragments to be able to access them later, but this turned out to be a wrong implementation causing huge memory leaks.
이전 구현에서는 나중에 액세스할 수 있도록 하위 프래그먼트 목록을 저장했지만, 이것은 매우 잘못된 구현으로 메모리 누수를 유발했습니다.
I end up using instantiateItem(...)
method to get current Fragment:
현재 프래그먼트를 가져오기 위해 instantiateItem(...) 메소드를 사용하게 되었습니다:
val currentFragment = adapter?.instantiateItem(viewPager, viewPager.currentItem)
Or to get any other Fragment on position:
또는 다른 위치(position)에 있는 프래그먼트를 가져오려면:
val position = 0
val myFirstFragment: MyFragment? = (adapter?.instantiateItem(viewPager, position) as? MyFragment)
From documentation:
문서에서:
Create the page for the given position. The adapter is responsible for adding the view to the container given here, although it only must ensure this is done by the time it returns from finishUpdate(ViewGroup).
주어진 위치에 대한 페이지를 만듭니다. 어댑터는 여기에 뷰를 추가하는 것이 책임이지만, finishUpdate(ViewGroup)에서 반환하기 전에 이 작업이 완료된 것만 보장하면 됩니다.
출처 : https://stackoverflow.com/questions/18609261/getting-the-current-fragment-instance-in-the-viewpager
'개발 > 안드로이드' 카테고리의 다른 글
'AppDatabase_Impl does not exist' 오류 수정하기 (0) | 2022.12.24 |
---|---|
ProgressDialog와 백그라운드 스레드가 활성화되어 있을 때 화면 회전 처리하기 (0) | 2022.12.24 |
putExtra(), getExtra()로 다른 액티비티로 문자열 보내기 (0) | 2022.12.24 |
안드로이드에서 클립보드에 텍스트 복사하기 (0) | 2022.12.23 |
비디오 태그를 포함한 HTML5 웹뷰로 로드하기 (0) | 2022.12.23 |