조각이있는 작업 표시 줄 위로 탐색


88

A , B , C 라는 세 개의 탭이있는 탭이있는 Actionbar / viewpager 레이아웃이 있습니다. 탭에서 C의 탭 (조각), 나는 또 다른 조각 말 조각 추가하고 D를 . 와

 DFragment f= new DFragment();
 ft.add(android.R.id.content, f, "");
 ft.remove(CFragment.this);
 ft.addToBackStack(null);
 ft.commit();

DFragment의 onResume에서 액션 바를 수정하여 버튼을 추가합니다.

ActionBar ab = getActivity().getActionBar();
ab.setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
ab.setDisplayHomeAsUpEnabled(true);
ab.setDisplayShowHomeEnabled(true);

이제 DFragment에서 하드웨어 (전화) 뒤로 버튼을 누르면 CFragment가 선택된 원래 Tabbed (ABC) 레이아웃으로 돌아갑니다. 액션 바 업 버튼으로이 기능을 어떻게 달성 할 수 있습니까?


답변:


185

OnBackStackChangedListener이 코드를 구현 하고 조각 활동에 추가합니다.

@Override
public void onCreate(Bundle savedInstanceState) {
    //Listen for changes in the back stack
    getSupportFragmentManager().addOnBackStackChangedListener(this);
    //Handle when activity is recreated like on orientation Change
    shouldDisplayHomeUp();
}

@Override
public void onBackStackChanged() {
    shouldDisplayHomeUp();
}

public void shouldDisplayHomeUp(){
   //Enable Up button only  if there are entries in the back stack
   boolean canGoBack = getSupportFragmentManager().getBackStackEntryCount()>0;
   getSupportActionBar().setDisplayHomeAsUpEnabled(canGoBack);
}

@Override
public boolean onSupportNavigateUp() {
    //This method is called when the up button is pressed. Just the pop back stack.
    getSupportFragmentManager().popBackStack();
    return true;
}

20
정보 onSupportNavigateUp(), "메소드는 수퍼 클래스의 메서드를 재정의하지 않습니다."
Fred

10
이미있는 경우 추가하는 대신 onOptionsItemSelecteditemId를 확인할 수도 있습니다 . android.R.id.homeonSupportNavigateUp
domsom 2014 년

1
API 버전이 14보다 크면 onSupportNavigateUp 대신 onNavigateUp을 사용합니다. @Override public boolean onNavigateUp () {//이 메서드는 up 버튼을 누르면 호출됩니다. 그냥 팝백 스택. getFragmentManager (). popBackStack (); true를 반환하십시오. }
Tejasvi Hegde 2014

1
?에서 앱 아이콘 옆에 표시되는 업 캐럿이 있어야 ActionBar합니까? 이 코드를 구현할 때 보이지 않습니다. 아이콘 만 클릭 할 수 있지만 아무 동작도하지 않습니다. Android 4.0 이상.
Azurespot

3
onBackStackChanged ()가 재정의되지 않는 경우 활동이 FragmentManager.OnBackStackChangedListener 인터페이스를 구현하는지 확인합니다.
CBA110

41

알았어. 단지 오버라이드 (override) onOptionsItemSelected을 활동을 주최하고, 예를 들면 가기 backstack 팝업

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home: {
            FragmentManager fm = getSupportFragmentManager();
            if (fm.getBackStackEntryCount() > 0) {
                fm.popBackStack();
                return true;
            }
            break;
        }
    }
    return super.onOptionsItemSelected(item);
}

전화 getActionBar().setDisplayHomeAsUpEnabled(boolean);getActionBar().setHomeButtonEnabled(boolean);onBackStackChanged()아래 답변에 설명 된대로.


3
또한 getActivity (). getActionBar (). setDisplayHomeAsUpEnabled (false); 백 스택을 팝업하면 위로 버튼을 제거하는 방법
JoP

이것은 올바른 방법이 아닙니다. 위쪽 버튼을 계속 활성화합니다.
Roger Garzon Nieto

1
해당 코드를 switchcase와 함께 문 안에 넣어야합니다 android.R.id.home.
Fred

18

상위 활동이 하나 있고이 위로 버튼이 뒤로 버튼으로 작동하도록하려면 다음 코드를 사용할 수 있습니다.

이것을 기본 활동 클래스의 onCreate에 추가하십시오.

getSupportFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
        @Override
        public void onBackStackChanged() {
            int stackHeight = getSupportFragmentManager().getBackStackEntryCount();
            if (stackHeight > 0) { // if we have something on the stack (doesn't include the current shown fragment)
                getSupportActionBar().setHomeButtonEnabled(true);
                getSupportActionBar().setDisplayHomeAsUpEnabled(true);
            } else {
                getSupportActionBar().setDisplayHomeAsUpEnabled(false);
                getSupportActionBar().setHomeButtonEnabled(false);
            }
        }

    });

다음과 같이 onOptionsItemSelected를 추가하십시오.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            getSupportFragmentManager().popBackStack();
            return true;
     ....
 }

나는 일반적으로 이것을 항상 사용하고 꽤 합법적 인 것 같습니다


1
나는 Activity그것이 시작된 조각으로 돌아 가기를 희망 하면서이 코드를 정확하게 사용해 보았습니다 . 으로 이동하면 앱 아이콘 근처에 뒤로 버튼이 표시 Activity되지만 아이콘을 클릭해도 아무 일도 일어나지 않습니다 (조각으로 돌아 가야 함). 왜 그런지 아세요? 감사.
Azurespot

1
@Daniel 귀하의 코드는 합법적입니다 .. 작동합니다. 당신은 당신이 어떤 예상치 못한 예외를 방지하기 위해 알고 .. 그냥 넣다 시도 캐치 옵션을 sorround 싶은 충돌 애플 리케이션 수
Zuko

1
@NoniA. 이것은 이전 프래그먼트 (예 : 프래그먼트 B-> 프래그먼트 A)로만 돌아갈 것입니다. 새 활동에서 1 개의 프래그먼트를 팽창시키는 경우 이전 활동으로 돌아 가지 않습니다.
Daniel Jonker

10

뒤로 버튼과 같은 위로 버튼으로 돌아갈 수 있습니다.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case android.R.id.home:
            super.onBackPressed();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

8

나는이 질문이 오래되었다는 것을 알고 있지만 (나 같은) 누군가도 그것을 필요로 할 수 있습니다.

활동이 AppCompatActivity를 확장 하는 경우 더 간단한 (2 단계) 솔루션을 사용할 수 있습니다.

1-홈이 아닌 프래그먼트를 추가 할 때마다 프래그먼트 트랜잭션을 커밋 한 직후 up 버튼 만 표시됩니다. 이렇게 :

    // ... add a fragment
    // Commit the transaction
    transaction.commit();

    getSupportActionBar().setDisplayHomeAsUpEnabled(true);

2-UP 버튼을 누르면 숨 깁니다.

@Override
public boolean onSupportNavigateUp() {
    getSupportActionBar().setDisplayHomeAsUpEnabled(false);        
    return true;
}

그게 다야.


7

Roger Garzon Nietosohailaziz의 답변을 조합하여 사용했습니다 . 내 앱에는 단일 MainActivity와 여기에로드 된 조각 A, B, C가 있습니다. 내 "홈"조각 (A)은 OnBackStackChangedListener를 구현하고 backStack의 크기를 확인합니다. 1보다 작 으면 UP 버튼을 숨 깁니다. 조각 B와 C는 항상 뒤로 버튼을로드합니다 (제 디자인에서 B는 A에서 시작되고 C는 B에서 시작됨). MainActivity 자체는 UP 버튼 탭에서 백 스택을 팝하고 프래그먼트가 호출하는 버튼을 표시하거나 숨기는 메서드가 있습니다.

주요 활동:

public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        // Respond to the action bar's Up/Home button
        case android.R.id.home:
            getSupportFragmentManager().popBackStack();
            return true;
    }
    return super.onOptionsItemSelected(item);
}

public void showUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(true); }
public void hideUpButton() { getSupportActionBar().setDisplayHomeAsUpEnabled(false); }

fragmentA (FragmentManager.OnBackStackChangedListener 구현) :

public void onCreate(Bundle savedinstanceSate) {
    // listen to backstack changes
    getActivity().getSupportFragmentManager().addOnBackStackChangedListener(this);

    // other fragment init stuff
    ...
}

public void onBackStackChanged() {
    // enable Up button only  if there are entries on the backstack
    if(getActivity().getSupportFragmentManager().getBackStackEntryCount() < 1) {
        ((MainActivity)getActivity()).hideUpButton();
    }
}

fragmentB, fragmentC :

public void onCreate(Bundle savedinstanceSate) {
    // show the UP button
    ((MainActivity)getActivity()).showUpButton();

    // other fragment init stuff
    ...
}

5

이것은 나를 위해 일했습니다. 예를 들어 (Kotlin의 코드) onSupportNavigateUp 및 onBackPressed를 재정의합니다.

override fun onBackPressed() {
    val count = supportFragmentManager.backStackEntryCount
    if (count == 0) {
        super.onBackPressed()
    } else {
        supportFragmentManager.popBackStack()
    }
}

override fun onSupportNavigateUp(): Boolean {
    super.onSupportNavigateUp()
    onBackPressed()
    return true
}

이제 조각에서 위쪽 화살표를 표시하면

activity.supportActionBar?.setDisplayHomeAsUpEnabled(true)

클릭하면 이전 활동으로 돌아갑니다.


5

Kotlin :

class MyActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        ...
        supportFragmentManager.addOnBackStackChangedListener { setupHomeAsUp() }
        setupHomeAsUp()
    }

    private fun setupHomeAsUp() {
        val shouldShow = 0 < supportFragmentManager.backStackEntryCount
        supportActionBar?.setDisplayHomeAsUpEnabled(shouldShow)
    }

    override fun onSupportNavigateUp(): Boolean = 
        supportFragmentManager.popBackStack().run { true }

    ...
}

2

이것은 매우 훌륭하고 신뢰할 수있는 솔루션입니다. http://vinsol.com/blog/2014/10/01/handling-back-button-press-inside-fragments/

그 사람은 backPress 동작을 처리하는 추상 조각을 만들고 전략 패턴을 사용하여 활성 조각 사이를 전환합니다.

여러분 중 일부에게는 추상 클래스에 약간의 단점이있을 수 있습니다.

곧 링크의 솔루션은 다음과 같습니다.

// Abstract Fragment handling the back presses

public abstract class BackHandledFragment extends Fragment {
    protected BackHandlerInterface backHandlerInterface;
    public abstract String getTagText();
    public abstract boolean onBackPressed();

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if(!(getActivity()  instanceof BackHandlerInterface)) {
            throw new ClassCastException("Hosting activity must implement BackHandlerInterface");
        } else {
            backHandlerInterface = (BackHandlerInterface) getActivity();
        }
    }

    @Override
    public void onStart() {
        super.onStart();

        // Mark this fragment as the selected Fragment.
        backHandlerInterface.setSelectedFragment(this);
    }

    public interface BackHandlerInterface {
        public void setSelectedFragment(BackHandledFragment backHandledFragment);
    }
}   

그리고 활동에서의 사용법 :

// BASIC ACTIVITY CODE THAT LETS ITS FRAGMENT UTILIZE onBackPress EVENTS 
// IN AN ADAPTIVE AND ORGANIZED PATTERN USING BackHandledFragment

public class TheActivity extends FragmentActivity implements BackHandlerInterface {
    private BackHandledFragment selectedFragment;

    @Override
    public void onBackPressed() {
        if(selectedFragment == null || !selectedFragment.onBackPressed()) {
            // Selected fragment did not consume the back press event.
            super.onBackPressed();
        }
    }

    @Override
    public void setSelectedFragment(BackHandledFragment selectedFragment) {
        this.selectedFragment = selectedFragment;
    }
}

이 링크가 질문에 답할 수 있지만 여기 에 답변의 필수 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다 . 링크 된 페이지가 변경되면 링크 전용 답변이 무효화 될 수 있습니다.
bummi

BTW : 중복 항목을 식별하는 경우 플래그를 지정하십시오. 고마워.
bummi 2015 년

onStart 내부에서 setSelectedFragment가 중요합니까?
VLeonovs
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.