Android Fragment 핸들 뒤로 버튼 누름
이 질문에는 이미 답변이 있습니다.
내 활동에 파편이 있습니다
[1], [2], [3], [4], [5], [6]
Back 버튼을 누르면 현재 활성 조각이 [2] 인 경우 [2]에서 [1]로 돌아가거나 다른 작업을 수행하지 않아야합니다.
가장 좋은 방법은 무엇입니까?
편집 : 응용 프로그램이 [3] ... [6]에서 [2] (으)로 돌아 가지 않아야합니다.
당신은 조각, 호출 사이에 전환 할 때 addToBackStack()
당신의 한 부분으로 FragmentTransaction
:
FragmentTransaction tx = fragmentManager.beginTransation();
tx.replace( R.id.fragment, new MyFragment() ).addToBackStack( "tag" ).commit();
보다 세부적인 제어가 필요한 경우 (즉, 일부 조각이 표시 될 때 뒤로 키를 표시하지 않으려는 경우) 조각 OnKeyListener
의 부모보기에서을 설정할 수 있습니다 .
//You need to add the following line for this solution to work; thanks skayred
fragment.getView().setFocusableInTouchMode(true);
fragment.getView().requestFocus();
fragment.getView().setOnKeyListener( new OnKeyListener()
{
@Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
return true;
}
return false;
}
} );
차라리 이런 식으로 뭔가를하고 싶습니다 :
private final static String TAG_FRAGMENT = "TAG_FRAGMENT";
private void showFragment() {
final Myfragment fragment = new MyFragment();
final FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.fragment, fragment, TAG_FRAGMENT);
transaction.addToBackStack(null);
transaction.commit();
}
@Override
public void onBackPressed() {
final Myfragment fragment = (Myfragment) getSupportFragmentManager().findFragmentByTag(TAG_FRAGMENT);
if (fragment.allowBackPressed()) { // and then you define a method allowBackPressed with the logic to allow back pressed or not
super.onBackPressed();
}
}
프래그먼트 뷰의 onKey 메소드를 재정의하면 다음이 필요합니다.
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.i(tag, "keyCode: " + keyCode);
if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
Log.i(tag, "onKey Back listener is working!!!");
getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
return true;
}
return false;
}
});
한 조각을 다른 조각으로 교체 할 때는 addToBackStack 메서드를 사용하십시오 .
getFragmentManager().beginTransaction().replace(R.id.content_frame, fragment).addToBackStack("my_fragment").commit();
그런 다음 활동에서 다음 코드를 사용하여 조각에서 다른 조각으로 이동하십시오 (이전 코드).
@Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0) {
getFragmentManager().popBackStack();
} else {
super.onBackPressed();
}
}
하드웨어 Back key 이벤트를 처리하려면 Fragment의 onActivityCreated () 메소드에서 다음 코드를 수행해야합니다.
또한 Action_Down 또는 Action_UP 이벤트를 확인해야합니다. 확인하지 않으면 onKey () 메서드가 두 번 호출됩니다.
또한 rootview (getView ())에 포커스가 없으면 작동하지 않습니다. 컨트롤을 클릭 한 경우 다시 getView (). requestFocus ();를 사용하여 rootview에 초점을 두어야합니다. 이 후에는 onKeydown () 만 호출됩니다.
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Toast.makeText(getActivity(), "Back Pressed", Toast.LENGTH_SHORT).show();
return true;
}
}
return false;
}
});
나를 위해 아주 잘 작동합니다.
이 작업을 수행하는 가장 이상적인 방법은 다음과 같습니다. Fragment : 뒤로 버튼을 누르고 사용자 정의 할 때 호출되는 콜백
public class MyActivity extends Activity
{
//...
//Defined in Activity class, so override
@Override
public void onBackPressed()
{
super.onBackPressed();
myFragment.onBackPressed();
}
}
public class MyFragment extends Fragment
{
//Your created method
public static void onBackPressed()
{
//Pop Fragments off backstack and do your other checks
}
}
인터페이스를 만듭니다.
BackButtonHandlerInterface
public interface BackButtonHandlerInterface {
void addBackClickListener (OnBackClickListener onBackClickListener);
void removeBackClickListener (OnBackClickListener onBackClickListener);
}
OnBackClickListener
public interface OnBackClickListener {
boolean onBackClick();
}
에서 활동 :
public class MainActivity extends AppCompatActivity implements BackButtonHandlerInterface {
private ArrayList<WeakReference<OnBackClickListener>> backClickListenersList = new ArrayList<>();
@Override
public void addBackClickListener(OnBackClickListener onBackClickListener) {
backClickListenersList.add(new WeakReference<>(onBackClickListener));
}
@Override
public void removeBackClickListener(OnBackClickListener onBackClickListener) {
for (Iterator<WeakReference<OnBackClickListener>> iterator = backClickListenersList.iterator();
iterator.hasNext();){
WeakReference<OnBackClickListener> weakRef = iterator.next();
if (weakRef.get() == onBackClickListener){
iterator.remove();
}
}
}
@Override
public void onBackPressed() {
if(!fragmentsBackKeyIntercept()){
super.onBackPressed();
}
}
private boolean fragmentsBackKeyIntercept() {
boolean isIntercept = false;
for (WeakReference<OnBackClickListener> weakRef : backClickListenersList) {
OnBackClickListener onBackClickListener = weakRef.get();
if (onBackClickListener != null) {
boolean isFragmIntercept = onBackClickListener.onBackClick();
if (!isIntercept) isIntercept = isFragmIntercept;
}
}
return isIntercept;
}
}
에 조각 :
public class MyFragment extends Fragment implements OnBackClickListener{
private BackButtonHandlerInterface backButtonHandler;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
backButtonHandler = (BackButtonHandlerInterface) activity;
backButtonHandler.addBackClickListener(this);
}
@Override
public void onDetach() {
super.onDetach();
backButtonHandler.removeBackClickListener(this);
backButtonHandler = null;
}
@Override
public boolean onBackClick() {
//This method handle onBackPressed()! return true or false
return false;
}
}
@Override
public void onResume() {
super.onResume();
getView().setFocusableInTouchMode(true);
getView().requestFocus();
getView().setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK){
if (mDrawerLayout.isDrawerOpen(GravityCompat.START)){
mDrawerLayout.closeDrawer(GravityCompat.START);
}
return true;
}
return false;
}
});
}
또는 getSupportFragmentManager().getBackStackEntryCount()
수행 할 작업을 확인하는 데 사용할 수 있습니다 .
@Override
public void onBackPressed() {
logger.d("@@@@@@ back stack entry count : " + getSupportFragmentManager().getBackStackEntryCount());
if (getSupportFragmentManager().getBackStackEntryCount() != 0) {
// only show dialog while there's back stack entry
dialog.show(getSupportFragmentManager(), "ConfirmDialogFragment");
} else if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
// or just go back to main activity
super.onBackPressed();
}
}
모든 트랜잭션을 백 스택에 추가하는 흐름을 관리하는 경우 사용자가 뒤로 버튼을 누를 때 이전 조각을 표시하기 위해 이와 같은 작업을 수행 할 수 있습니다 (홈 버튼도 매핑 할 수 있음).
@Override
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() > 0)
getFragmentManager().popBackStack();
else
super.onBackPressed();
}
여러 프래그먼트 및 / 또는 액티비티에서 백 프레스를 처리하기위한 작은 라이브러리를 만들었습니다. gradle 파일에 종속성을 추가하는 것만 큼 사용법이 간단합니다.
compile 'net.skoumal.fragmentback:fragment-back:0.1.0'
프래그먼트가 BackFragment
인터페이스를 구현하도록하십시오 .
public abstract class MyFragment extends Fragment implements BackFragment {
public boolean onBackPressed() {
// -- your code --
// return true if you want to consume back-pressed event
return false;
}
public int getBackPriority() {
return NORMAL_BACK_PRIORITY;
}
}
백 프레스에 대해 조각에 알리십시오.
public class MainActivity extends AppCompatActivity {
@Override
public void onBackPressed() {
// first ask your fragments to handle back-pressed event
if(!BackFragmentHelper.fireOnBackPressedEvent(this)) {
// lets do the default back action if fragments don't consume it
super.onBackPressed();
}
}
}
자세한 내용 및 기타 사용 사례는 GitHub 페이지를 방문하십시오.
https://github.com/skoumalcz/fragment-back
SlidingMenu 및 Fragment와 협력하고 있으며 여기에 내 사례를 제시하고 누군가를 도울 수 있기를 바랍니다.
[뒤로] 키를 눌렀을 때의 논리 :
- 슬라이딩 메뉴가 표시되면 더 이상 할 일이 없습니다.
- 또는 두 번째 (또는 그 이상) 조각이 표시되면 이전 조각으로 다시 슬라이드하면 더 이상 할 일이 없습니다.
SlidingMenu가 표시되지 않음, 현재 조각은 # 0이며 원래 [뒤로] 키가 수행합니다.
public class Main extends SherlockFragmentActivity { private SlidingMenu menu=null; Constants.VP=new ViewPager(this); //Some stuff... @Override public void onBackPressed() { if(menu.isMenuShowing()) { menu.showContent(true); //Close SlidingMenu when menu showing return; } else { int page=Constants.VP.getCurrentItem(); if(page>0) { Constants.VP.setCurrentItem(page-1, true); //Show previous fragment until Fragment#0 return; } else {super.onBackPressed();} //If SlidingMenu is not showing and current Fragment is #0, do the original [Back] key does. In my case is exit from APP } } }
근무 코드 :
package com.example.keralapolice;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentManager.OnBackStackChangedListener;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
public class ChiefFragment extends Fragment {
View view;
// public OnBackPressedListener onBackPressedListener;
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle args) {
view = inflater.inflate(R.layout.activity_chief, container, false);
getActivity().getActionBar().hide();
view.setFocusableInTouchMode(true);
view.requestFocus();
view.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
Log.i(getTag(), "keyCode: " + keyCode);
if (keyCode == KeyEvent.KEYCODE_BACK) {
getActivity().getActionBar().show();
Log.i(getTag(), "onKey Back listener is working!!!");
getFragmentManager().popBackStack(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
// String cameback="CameBack";
Intent i = new Intent(getActivity(), home.class);
// i.putExtra("Comingback", cameback);
startActivity(i);
return true;
} else {
return false;
}
}
});
return view;
}
}
이것은 매우 훌륭하고 안정적인 솔루션입니다. 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;
}
}
가장 쉬운 방법은 인터페이스를 만들고 활동에서 프래그먼트가 인터페이스 유형인지 확인하고 그렇다면 해당 메서드를 호출하여 팝을 처리하는 것입니다. 다음은 프래그먼트에서 구현할 인터페이스입니다.
public interface BackPressedFragment {
// Note for this to work, name AND tag must be set anytime the fragment is added to back stack, e.g.
// getActivity().getSupportFragmentManager().beginTransaction()
// .replace(R.id.fragment_container, MyFragment.newInstance(), "MY_FRAG_TAG")
// .addToBackStack("MY_FRAG_TAG")
// .commit();
// This is really an override. Should call popBackStack itself.
void onPopBackStack();
}
그것을 구현하는 방법은 다음과 같습니다.
public class MyFragment extends Fragment implements BackPressedFragment
@Override
public void onPopBackStack() {
/* Your code goes here, do anything you want. */
getActivity().getSupportFragmentManager().popBackStack();
}
그리고 Activity에서 pop을 처리 할 때 (onBackPressed 및 onOptionsItemSelected에서와 같이)이 방법을 사용하여 백 스택을 팝하십시오.
public void popBackStack() {
FragmentManager fm = getSupportFragmentManager();
// Call current fragment's onPopBackStack if it has one.
String fragmentTag = fm.getBackStackEntryAt(fm.getBackStackEntryCount() - 1).getName();
Fragment currentFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
if (currentFragment instanceof BackPressedFragment)
((BackPressedFragment)currentFragment).onPopBackStack();
else
fm.popBackStack();
}
모든 솔루션을 살펴본 후 훨씬 간단한 솔루션이 있음을 깨달았습니다.
모든 조각을 호스팅하는 활동의 onBackPressed ()에서 뒤로 누르기를 방지하려는 조각을 찾으십시오. 그런 다음 발견되면 돌아 오십시오. 그런 다음이 조각에 대해 popBackStack이 발생하지 않습니다.
@Override
public void onBackPressed() {
Fragment1 fragment1 = (Fragment1) getFragmentManager().findFragmentByTag(“Fragment1”);
if (fragment1 != null)
return;
if (getFragmentManager().getBackStackEntryCount() > 0){
getFragmentManager().popBackStack();
}
}
rootView.setFocusableInTouchMode(true);
rootView.requestFocus();
rootView.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
Fragment NameofFragment = new NameofFragment;
FragmentTransaction transaction=getFragmentManager().beginTransaction();
transaction.replace(R.id.frame_container,NameofFragment);
transaction.commit();
return true;
}
return false;
}
});
return rootView;
다음에서 사용할 수 있습니다 getActionBar().setDisplayHomeAsUpEnabled()
.
@Override
public void onBackStackChanged() {
int backStackEntryCount = getFragmentManager().getBackStackEntryCount();
if(backStackEntryCount > 0){
getActionBar().setDisplayHomeAsUpEnabled(true);
}else{
getActionBar().setDisplayHomeAsUpEnabled(false);
}
}
정적 조각을 사용하는 사람들을 위해
정적 조각이있는 경우 바람직합니다. 프래그먼트의 인스턴스 객체 만들기
private static MyFragment instance=null;
MyFragment의 onCreate ()에서 해당 인스턴스를 초기화합니다.
instance=this;
또한 인스턴스를 얻는 기능을
public static MyFragment getInstance(){
return instance;
}
또한 기능을
public boolean allowBackPressed(){
if(allowBack==true){
return true;
}
return false;
}
//allowBack is a boolean variable that will be set to true at the action
//where you want that your backButton should not close activity. In my case I open
//Navigation Drawer then I set it to true. so when I press backbutton my
//drawer should be get closed
public void performSomeAction(){
//.. Your code
///Here I have closed my drawer
}
당신의 활동에서 할 수있는 일
@Override
public void onBackPressed() {
if (MyFragment.getInstance().allowBackPressed()) {
MyFragment.getInstance().performSomeAction();
}
else{
super.onBackPressed();
}
}
addToBackStack ()을 조각화 트랜잭션에 추가 한 다음 조각에 대한 역 탐색 구현을 위해 아래 코드를 사용하십시오.
getSupportFragmentManager().addOnBackStackChangedListener(
new FragmentManager.OnBackStackChangedListener() {
public void onBackStackChanged() {
// Update your UI here.
}
});
FragmentActivity를 사용하는 경우 그런 다음 이렇게
먼저 조각 내에서 이것을 호출하십시오.
public void callParentMethod(){
getActivity().onBackPressed();
}
그런 다음 onBackPressed
부모 FragmentActivity
클래스 옆에 메소드 를 호출 하십시오 .
@Override
public void onBackPressed() {
//super.onBackPressed();
//create a dialog to ask yes no question whether or not the user wants to exit
...
}
활동에이 코드를 추가하십시오
@우세하다
public void onBackPressed() {
if (getFragmentManager().getBackStackEntryCount() == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
그리고 commit () 전에 Fragment 에이 줄을 추가하십시오.
ft.addToBackStack ( "모든 이름");
프래그먼트 클래스에서 back 이벤트를 위해 다음 코드를 입력하십시오
rootView.setFocusableInTouchMode(true);
rootView.requestFocus();
rootView.setOnKeyListener( new OnKeyListener()
{
@Override
public boolean onKey( View v, int keyCode, KeyEvent event )
{
if( keyCode == KeyEvent.KEYCODE_BACK )
{
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction()
.replace(R.id.frame_container, new Book_service_provider()).commit();
return true;
}
return false;
}
} );
백 스택 확인이 완벽하게 작동
@Override
public boolean onKeyDown(int keyCode, KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{
if (getFragmentManager().getBackStackEntryCount() == 1)
{
// DO something here since there is only one fragment left
// Popping a dialog asking to quit the application
return false;
}
}
return super.onKeyDown(keyCode, event);
}
oncreateView () 메소드에서이 코드를 작성해야하며 KEYCODE_BACk 조건에서 원하는 기능을 작성할 수 있습니다.
View v = inflater.inflate(R.layout.xyz, container, false);
//Back pressed Logic for fragment
v.setFocusableInTouchMode(true);
v.requestFocus();
v.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
getActivity().finish();
Intent intent = new Intent(getActivity(), MainActivity.class);
startActivity(intent);
return true;
}
}
return false;
}
});
참고 URL : https://stackoverflow.com/questions/7992216/android-fragment-handle-back-button-press
'development' 카테고리의 다른 글
std :: string을 char *로 (0) | 2020.03.15 |
---|---|
RecyclerView로 수평 ListView를 작성하는 방법은 무엇입니까? (0) | 2020.03.15 |
node.js 해시 문자열? (0) | 2020.03.15 |
Vim에서 전체 라인을 위아래로 이동 (0) | 2020.03.15 |
설치 스크립트가 오류와 함께 종료되었습니다 : 'x86_64-linux-gnu-gcc'명령이 종료 상태 1로 실패했습니다. (0) | 2020.03.15 |