Android ActionProvider를 이용한 액션바 아이템 액션에 대한 커스텀뷰 생성

안드로이드의 액션바는 구글 개발 디자인가이드라인에 따라 공식적으로 지원하며 권장하는 디자인이다. 약간의 제약사항도 있지만 디자인가이드라인이니 되도록 사용을 해야하는것이 맞다고 생각한다. 국내 일부와 해외 유명한 앱대부분은 액션바를 사용하고 있다. 

구글에서도 이런 제약사항에 대한 보완책으로 약간의 커스터마이징을 사용 할수 있도록 ActionProvider을 제공한다. 액션바의 Item을 Action하게 되면 커스텀뷰를 보여주게 한다던가, 서브아이템을 표시할 수 있다. 

menu xml의 item에 actionProviderClass를 통해 커스텀 ActionProvider를 설정하게 되면 구현한 것이 로드 되게 되는 구조이다.


<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/action_search"
        android:actionProviderClass="com.kmshack.actionbar.SearchActionProvider"
        android:showAsAction="ifRoom|withText|collapseActionView"
        android:title="검색"/>

</menu>


커스터 마이징은 ActionProvider를 상속받아서 구현하면 되는데 아래 코드와 같다.

public class SearchActionProvider extends ActionProvider{

    private Context mContext;
    private EditText mEditText;
    private TextWatcher mTextWatcher;
    
    public SearchActionProvider(Context context) {
        super(context);
        mContext = context;
    }

    @Override
    public View onCreateActionView() {
        LayoutInflater layoutInflater = LayoutInflater.from(mContext);
        View view = layoutInflater.inflate(R.layout.search_layout,null);

        mEditText = (EditText)view.findViewById(R.id.edt_search);
        
        if(mTextWatcher!=null)
            mEditText.addTextChangedListener(mTextWatcher);
        return view;
    }
    
    @Override
    public boolean hasSubMenu() {
        return super.hasSubMenu();
    }

    @Override
    public boolean onPerformDefaultAction() {
        return super.onPerformDefaultAction();
    }

    @Override
    public void onPrepareSubMenu(SubMenu subMenu) {
        super.onPrepareSubMenu(subMenu);
    }

    public void setTextChangedListener(TextWatcher textWatcher){
        mTextWatcher = textWatcher;
    }

}


onCreateActionView()에서 액션바의 아이콘을 누른 후 보여줄 View를 생성해서 return 해주면 된다. 위의 예제는 검색을 위해서 EditText가 있는 커스텀 레이아웃을 만들었다. 그렇다면 ActionProvider에서 구현한것과 액티비티와의 CallBack처리는 어떻게 하는지 다음 코드에서 확인 해볼 수 있다. 

@Override
public boolean hasSubMenu() {
    return true;
}

@Override
public void onPrepareSubMenu(SubMenu subMenu) {
    subMenu.clear();

    subMenu.add(0, 1, 1, "설정").setOnMenuItemClickListener(this);
    subMenu.add(0, 2, 1, "추가").setOnMenuItemClickListener(this);
}


View를 변경 하는것이 아닌 서브아이템을 추가하고 싶은 경우 hasSubMenu() return true로 한후,  onPrepareSubMenu()에서 서브아이템을 추가 하면된다.

public class MainActivity extends Activity {

    private SearchActionProvider mSearchActionProvider;
    private TextView mTitle;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        setContentView(R.layout.main);
        mTitle = (TextView) findViewById(R.id.title);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.items, menu);
        MenuItem searchItem = menu.findItem(R.id.action_search);
        mSearchActionProvider = (SearchActionProvider) searchItem.getActionProvider();

        mSearchActionProvider.setTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mTitle.setText(s);
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {

            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        return super.onCreateOptionsMenu(menu);
    }
}

Activity에서 onCreateOptionsMenu()에서 inflate한 메뉴를 finditem을 통해 가져온후 getActionProvider() 메소드를 통해 ActionProvider을 가져올 수 있다. 위와 같이 가져온후 ActionProvider를 상속 받아 구현 해놓은 기능을 수행할 수 있다. 위의 예제는 ActionProvider를 통해 구현 해놓은 EditText에 TextChangedListener를 넘겨준다.  


SupportLibrary v7을 사용하면 안드로이드 2.3에서도 사용가능하며, ActionProvider를 이용하면 다양한 액션바를 만들수 있다. 

코드:

cfile21.uf.216D794652A02AD427F99F.zip

댓글 남기기