Program Club

다중 조각 활동에서 onContextItemSelected를 처리하는 방법은 무엇입니까?

proclub 2020. 11. 7. 10:40
반응형

다중 조각 활동에서 onContextItemSelected를 처리하는 방법은 무엇입니까?


현재 Android 1.6 사용자에게도 프래그먼트 사용의 이점을 제공하기 위해 "Android v4 용 호환성 라이브러리"를 사용하도록 내 애플리케이션을 조정하려고합니다.

상황에 맞는 메뉴의 구현은 까다로운 것 같습니다.

  • 애플리케이션의 주요 활동은 FragmentActivity 클래스를 확장하는 것 입니다.
  • 프래그먼트는 모두 Fragment 클래스를 확장하는 하나의 클래스를 기반으로합니다.
  • 조각 클래스는 onCreateView () 메서드 에서 registerForContextMenu ()호출 하고 onCreateContextMenu ()onContextItemSelected () 메서드를 재정의합니다 .

들어 인, onCreateContextMenu () 이 꽤 잘 작동합니다. 컨텍스트 메뉴는 리소스 파일에서 부풀려지고 선택한 항목에 따라 약간 수정됩니다 (조각이 ListFragment가 아닌 경우에도 listView ... 기반).

상황에 맞는 메뉴 항목을 선택하면 문제가 발생합니다. onContextItemSelected () 는 처음 추가 된 조각부터 시작하여 현재 존재하는 모든 조각에 대해 호출됩니다.

제 경우에는 조각이 폴더 구조의 내용을 표시하는 데 사용됩니다. 하위 폴더 조각의 컨텍스트 메뉴가 열리고 메뉴 항목이 선택되면 먼저 상위 수준 에서 onContextItemSelected () 가 호출됩니다 (현재 허용 / 표시되는 조각 수에 따라 다름).

지금은 onCreateContextMenu ()를 호출하는 마지막 조각의 태그를 보유하는 활동 수준의 필드에서 해결 방법을 사용합니다 . 이렇게 하면 저장된 태그가 getTag ()와 동일하지 않을 때 onContextItemSelected () 시작 부분에서 "return super.onContextItemSelected (item)"를 호출 할 수 있습니다 . 그러나이 접근법은 나에게 약간 더러워 보입니다.

모든 조각에서 onContextItemSelected ()가 호출되는 이유는 무엇입니까? 그리고 onCreateContextMenu ()를 호출 한 것뿐만 아니라 ?

이것을 처리하는 가장 우아한 방법은 무엇입니까?


비슷한 문제를 방금 처리했기 때문에 해결 방법을 찾았더라도 답변을 게시하겠습니다. 특정 조각에 대한 컨텍스트 메뉴를 확장 할 때 각 메뉴 항목에 조각에 고유 한 groupId를 할당합니다. 그런 다음 'onContextItemSelected'에서 groupId를 테스트합니다. 예를 들면 :

public void onCreateContextMenu(ContextMenu menu, View v,ContextMenuInfo menuInfo) {
    menu.add(UNIQUE_FRAGMENT_GROUP_ID, MENU_OPTION_1, 0, R.string.src1);
    menu.add(UNIQUE_FRAGMENT_GROUP_ID, MENU_OPTION_2, 0, R.string.src2);
}
public boolean onContextItemSelected(MenuItem item) {
    //only this fragment's context menus have group ID of -1
    if (item.getGroupId() == UNIQUE_FRAGMENT_GROUP_ID) {
        switch(item.getItemId()) {
        case MENU_OPTION_1: doSomething(); break;
        case MENU_OPTION_2: doSomethingElse(); break;
    }
}

이렇게하면 모든 조각이 여전히 'onContextItemSelected'에 대한 호출을 수신하지만 올바른 조각 만 응답하므로 활동 수준 코드를 작성할 필요가 없습니다. 이 기술의 수정 된 버전은 'menu.add (...)'를 사용하지 않아도 작동 할 수 있다고 가정합니다.


또 다른 해결책 :

@Override
public boolean onContextItemSelected(MenuItem item) {
    if (getUserVisibleHint()) {
        // context menu logic
        return true;
    }
    return false;
}

Jake Wharton 의이 패치기반으로 합니다 .


Sergei G (Jake Wharton 수정 기반)의 간단한 솔루션이 마음에 들었지만 여러 조각에 추가하는 것이 더 쉽기 때문에 반전되었습니다.

public boolean onContextItemSelected(android.view.MenuItem item) 
{  
    if( getUserVisibleHint() == false ) 
    {
        return false;
    }

    // The rest of your onConextItemSelect code
    AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();
 }

그 후, 이전과 동일한 코드.


아주 쉬운 해결책을 찾았습니다. ContextMenu가 생성 될 때마다 onCreateContextMenu ()가 호출되므로 부울 변수를 true로 설정합니다.

public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
    super.onCreateContextMenu(menu, v, menuInfo);
    MenuInflater inflater = getActivity().getMenuInflater();
    inflater.inflate(R.menu.film_menu, menu);
    bMenu=true;
}

내가해야 할 유일한 다른 일은 해당 변수 OnContextItemSelected ()를 요청하는 것입니다.

public boolean onContextItemSelected(MenuItem item) {
    if (bMenu) {
        bMenu=false;
        if (item.getItemId() == R.id.filmProperties) {
            ///Your code
            return true;
        } else {
            return super.onContextItemSelected(item);
        }
    } else {
        return super.onContextItemSelected(item);
    }
}

그게 다야.


대안을 찾았습니다. 위의 내 문제에 대해 아무것도 변경하지 않지만 의미가 없습니다.

내 응용 프로그램에서 컨텍스트 메뉴를 완전히 제거했습니다. 대신 목록 항목을 길게 클릭하고이 순간 작업 표시 줄의 보이는 버튼을 변경합니다. 사용자 관점에서 이것은 컨텍스트 메뉴와 같은 훨씬 더 태블릿입니다.

이전 버전과 호환되는 응용 프로그램에서는 작업 표시 줄이 없습니다. 그래서 저는 Honeycomb 이전의 장치를 위해 나만의 도구 모음을 만들기로 결정했습니다.

상황에 맞는 메뉴를 계속 사용하고 싶다면 위에서 언급 한 해결 방법으로 더 나은 솔루션을 찾지 못했습니다.


내 첫 번째 조각에서는 모든 메뉴 ID> 5000을 설정 했으므로 첫 번째 조각의 onContextItemSelected 코드의 첫 번째 줄로

if (item.getItemId() < 5000) return false;

두 번째 조각이 호출됩니다.


조각에 목록보기가있는 어댑터를 사용하는 경우 도움이 될 수 있습니다.

public boolean onContextItemSelected(final MenuItem item) {
    final AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) item.getMenuInfo();

    //Check if the context menu call came from the list in this fragment (needed for support for multiple fragments in one screen)
    if (info.targetView.getParent() != getView().findViewById(android.R.id.list))
        return super.onContextItemSelected(item);

    //Handle context menu item call
    switch (item.getItemId()) {
        ...
    }
}

그냥 바꿔

 @Override
    public boolean onContextItemSelected(MenuItem item) {
    return true;
 }

...에

@Override
    public boolean onContextItemSelected(MenuItem item) {
    return super.onContextItemSelected(item); 
 }

그리고 훌륭하게 작동합니다 !!!


IMHO 우리는 대상 뷰가 조각 목록 뷰의 자식인지 확인할 수 있습니다. 매우 간단하고 잘 작동합니다. 방금 모든 조각에 추가했습니다. if (getListView.getPositionForView(info.targetView) == -1) return false이전 API에서 마이그레이션 할 때

이것은 내 부모 조각 중 하나의 예입니다. 이것은 Scala이지만 아이디어가 있으 셨기를 바랍니다.

@Loggable
override def onContextItemSelected(menuItem: MenuItem): Boolean = {
  for {
    filterBlock <- TabContent.filterBlock
    optionBlock <- TabContent.optionBlock
    environmentBlock <- TabContent.environmentBlock
    componentBlock <- TabContent.componentBlock
  } yield menuItem.getMenuInfo match {
  case info: AdapterContextMenuInfo =>
    if (getListView.getPositionForView(info.targetView) == -1)
      return false
    TabContent.adapter.getItem(info.position) match {
      case item: FilterBlock.Item =>
        filterBlock.onContextItemSelected(menuItem, item)
      case item: OptionBlock.Item =>
        optionBlock.onContextItemSelected(menuItem, item)
      case item: EnvironmentBlock.Item =>
        environmentBlock.onContextItemSelected(menuItem, item)
      case item: ComponentBlock.Item =>
        componentBlock.onContextItemSelected(menuItem, item)
      case item =>
        log.debug("skip unknown context menu item " + info.targetView)
        false
    }
  case info =>
    log.fatal("unsupported menu info " + info)
    false
  }
} getOrElse false

P.S. If you trace calls of onContextItemSelected(...) you may notify that super.onContextItemSelected(item) return always false. Valid onContextItemSelected invoked AFTER, not WITHIN. So super.onContextItemSelected(item) is useless and I replaced it with false.


I found an easier solution than the exposed:

public boolean onContextItemSelected(MenuItem item) {
    ListView yourList = (ListView) (ListView) getView().findViewById(R.id.yourList);

    if (!yourList.hasFocus())
        return false;

    switch(item.getItemId()) {
        ...
    }
}

In the method changed return true; to return super.onContextItemSelected(item); in my onContextItemSelected() override and everything started working.

참고URL : https://stackoverflow.com/questions/5297842/how-to-handle-oncontextitemselected-in-a-multi-fragment-activity

반응형