Android는 모든 Activity에 글로벌 사용자 지정 메뉴를 추가합니다.

14398 단어 수필 기록
최근 UI에서 2.0에 전체적인 메뉴 버튼을 만들어 달라는 기상천외한 생각이 크게 떠올랐다.
이 단추의 대체적인 수요는 화면 오른쪽 상단에 버튼을 추가하고 클릭한 후 화면 맨 위와 오른쪽에 일련의 기능 단추를 소환하는 것이다.
나는 이 부분의 코드를 추출하여 임의로 데모를 썼는데 위의 그림을 실현해야 한다.
(버튼 2를 눌렀을 때 이미 로그인 인터페이스에 있으면 다시 돌릴 필요가 없다는 알림이 있습니다. 아래에 설명이 있습니다)
필요에 따라 손에 넣는다. 다행히 이전에 타이틀은 사용자 정의 View를 사용했기 때문에 오른쪽에 단추를 아무렇게나 넣으면 되잖아!!결과는 너무 순진하다. 우선 위와 같은 효과를 실현하려면 이 레이아웃은 쓰기 어려울 것이다. 그 다음에 이 니마가 가지고 있는 페이지는 타이틀이 아예 없다. 그리고 이전에 전체적인 플로팅 버튼을 한 것을 연상할 수 있다. 그러나 이 물건은 플로팅 창의 권한이 필요하다. 사용자가 열지 않으면 플로팅 단추가 나오지 않는다.
그리고 첫 번째 생각은 여러 가지--, 결과적으로 인터넷에 이런 수요가 전혀 없다는 것을 발견했다. 설마 내가 찾은 자세가 틀린 건 아니겠지?이거 좀 어색하네. 그럼 스스로 바퀴를 만들 수밖에 없네..
어어, 쓸데없는 말 많이 했으니 본론으로 들어가자--
모든Activity에 통일된 전역menu를 추가하려면 BaseActivity에서 작업을 해야 합니다. 통일된 보기를 추가하려면 BaseActivity의setContentView () 방법에menu 보기를 추가해야 합니다.내 접근 방식은 다음과 같습니다.
    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        ((ViewGroup) getWindow().getDecorView()).addView(menu);
    }

이 getDecorView: 이 방법은 최고급 보기를 가져오는 것입니다
주의점1:addView에 추가된 보기는 기본적으로 왼쪽 상단에 있어야 하며 그룹의 원래 보기와 무관합니다
주의점 2:getDecorView는 최고급 보기이기 때문에 제목 표시줄을 포함한 전체 화면을 포함합니다
주의점3: 실제 테스트에 의하면 제목 표시줄의 왼쪽 상단 위치의 좌표가야말로 좌표 원점 위치이다
여기에서 참조http://blog.csdn.net/rnZuoZuo/article/details/44959873에 대한 소개, 이 방법에 관심 있는 어린이 신발은 스스로 자료를 찾을 수 있습니다, 여기서는 자세히 소개하지 않겠습니다~~
여기에서 menu는 사용자 정의 View입니다. Relative Layout을 계승하고 간단한 Relative Layout을 불러옵니다. 이 레이아웃은 모든 단추를 화면 오른쪽 상단에 추가합니다.



    


当然你可以做成动态添加选项按钮,增加拓展性,因为我比较懒,这里就不做这一步了,就只分享我项目用到的,实际上在打算写博客的时候我考虑到这个需求完全可以做成
动态配置的,包括menu的形式与item的个数配置等等都能做成动态的,我后面会提到。


眼尖的童鞋肯定会发现我上面的menu有一个展开与收缩的动画效果,感觉这个menu关键的就是实现这个动画就行了,贴出show()与dismiss()动画实现代码:
show()

     int n = btns.size();
        for (int i = 0; i < n; i++) {
            float curTranslationX = btns.get(i).getTranslationX();
            float curTranslationY = btns.get(i).getTranslationY();
            PropertyValuesHolder valuesHolderX, valuesHolderY;
            if (i <= 1) {//   item
                valuesHolderX = PropertyValuesHolder.ofFloat("translationX", curTranslationX, 
                        ((i - n + 5) * w / 5));//X          
                valuesHolderY = PropertyValuesHolder.ofFloat("translationY", curTranslationY, 0);

            } else {//   item
                valuesHolderX = PropertyValuesHolder.ofFloat("translationX", curTranslationX, 0);
                valuesHolderY = PropertyValuesHolder.ofFloat("translationY", curTranslationY, 
                        (-(i - n) * h / 7));//Y          
            }
            animatorX = ObjectAnimator.ofPropertyValuesHolder(btns.get(i), valuesHolderX, valuesHolderY);
            animatorX.setDuration(250);
            animatorX.setStartDelay(i * 50);
            animatorX.setInterpolator(new AnticipateOvershootInterpolator());
            animatorX.start();
        }

dismiss()
int n = btns.size();
        for (int i = 0; i < n; i++) {
            //         
        float curTranslationX = btns.get(i).getTranslationX();
        float curTranslationY = btns.get(i).getTranslationY();

        PropertyValuesHolder valuesHolderX = PropertyValuesHolder.ofFloat("translationX",
        curTranslationX, initX);
        PropertyValuesHolder valuesHolderY = PropertyValuesHolder.ofFloat("translationY",
        curTranslationY, initY);
        animatorX = ObjectAnimator.ofPropertyValuesHolder(btns.get(i), valuesHolderX, valuesHolderY);
        animatorX.setDuration(250);
        animatorX.setStartDelay(i * 50);
        animatorX.setInterpolator(new AnticipateOvershootInterpolator());
        animatorX.start();
        }

btns는 모든 하위 item의 집합이고 animator는 애니메이션 종류이다. 만약에 속성 애니메이션에 익숙하지 않은 어린이 신발이 여기 있는 코드를 보면 혼란스러울 수 있으므로 관련 자료를 많이 보는 것을 권장한다. 나는 여기에 많은 소개를 하지 않는다.valuesHolder는menu의 주button에 비해 w,h는 각각 화면의 넓이가 높다.
menu의 전시 형식은 바로 이 두 가지 방법에서 정의한 것이다. 만약에 다른 전시 애니메이션이 필요하다면 완전히 당신 자신의 논리에 따라 수정할 수 있다. 당신은 원심을 둘러싼 메뉴를 만들 수도 있고 90도의 위성 메뉴를 만들 수도 있다. 모든 것을 수요에 따라...
마지막으로 이 menu가 button에 사는 클릭 이벤트를 보십시오:
   btn_start.setOnClickListener(new OnClickListener() {

            @Override
            public void onClick(View v) {

                if (!isShowing) {
                    if (mChangeListener != null) {
                        mChangeListener.show();//        
                    }
                    show();


                    rl_parent.setFocusable(true);
                    rl_parent.setClickable(true);

                    rl_parent.setBackgroundColor(getResources().getColor(R.color.menuShow));
                    isShowing = !isShowing;


                } else {
                    if (mChangeListener != null) {
                        mChangeListener.dismiss();//        
                    }
                    dismiss();
                    rl_parent.setFocusable(false);
                    rl_parent.setClickable(false);

                    rl_parent.setBackgroundColor(getResources().getColor(R.color.menuDismiss));
                    isShowing = !isShowing;

                }


            }
        });

isshowing은 전체적인 전시 여부의 상태입니다.rlparent는 전체menu의 레이아웃과 레이아웃입니다.menu가 전개될 때menu의 다음 층에 있는 컨트롤러가 초점을 잃어야 합니다.Dialog가 setCancelable(false)의 효과를 설정한 것과 비슷하기 때문에rl 을 설정해야 합니다parent는 펼칠 때 초점을 얻고 숨길 때 초점을 취소합니다.실제로menu의 전개와 숨김은 시각적인 효과일 뿐,activity의setcontentview에addview를 통해 추가된menu는activity와의 최상층에 계속 존재하며,여기는show()와dismiss()를 통해 각각rlparent 투명도가 다른 배경색을 설정했을 뿐입니다.
이곳의 mChange Listener는menu 내부의 인터페이스입니다. 만약에 당신의 페이지가menu의 전시와 숨김에 대해 감청을 해야 한다면 이 인터페이스를 실현할 수 있습니다. 바로 일반적인 인터페이스 리셋입니다. 여기서 할 말이 없습니다.menu의 모든 하위 item의 클릭 이벤트도 이런 방법으로 이루어졌습니다. 아래에 두 개의 인터페이스를 붙입니다.
   public interface MenuChangeListener {
        public void show();

        public void dismiss();
    }

    public interface MenuItemClickListener {
        void menuOneItemClick();

        void menuTwoItemClick();

        void menuThreeItemClick();

        void menuFourItemClick();

        void menuFiveItemClick();

        void menuSixItemClick();

        void menuSevenItemClick();

    }

실제로 모든 item의 클릭 이벤트가 리셋을 써야 하는 것은 아니다. 만약에 특정한 item의 이벤트가 고정적이라면menu류에서 직접 이 방법을 실현할 수 있고 외부에 노출되지 않아도 된다.
내 프로젝트에서 item의 모든 이벤트는baseActivity에서 이루어졌기 때문에 특정한 item이 구체적인 activity에서 서로 다른 이벤트에 응답해야 한다면
BaseActivity에서 임시Activity 변수currentact, 그리고 모든 하위 Activity에서 현재 Activity 대상을currentact,
demo의 BaseActivity 코드는 다음과 같습니다.
package com.aking.globalmenumaster.activity;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.ViewGroup;
import android.widget.Toast;

import com.aking.globalmenumaster.GlobalMenu;

/**
 * Created by aking on 2017/4/6.
 */
public class BaseActivity extends AppCompatActivity {
    private GlobalMenu menu;
    public Activity current_act;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        menu = new GlobalMenu(this);
        menu.setMenuItemClickListener(new GlobalMenu.MenuItemClickListener() {
            @Override
            public void menuOneItemClick() {
                startActivity(new Intent(BaseActivity.this, FullscreenActivity.class));
            }

            @Override
            public void menuTwoItemClick() {
                if (current_act.getClass() == LoginActivity.class) {
                    Toast.makeText(BaseActivity.this, "         ", Toast.LENGTH_LONG).show();
                } else {
                    startActivity(new Intent(BaseActivity.this, LoginActivity.class));
                }

            }

            @Override
            public void menuThreeItemClick() {
                startActivity(new Intent(BaseActivity.this, Main2Activity.class));
            }

            @Override
            public void menuFourItemClick() {
                startActivity(new Intent(BaseActivity.this, Main22Activity.class));
            }

            @Override
            public void menuFiveItemClick() {
                startActivity(new Intent(BaseActivity.this, Main23Activity.class));
            }

            @Override
            public void menuSixItemClick() {
                startActivity(new Intent(BaseActivity.this, ScrollingActivity.class));
            }

            @Override
            public void menuSevenItemClick() {
                startActivity(new Intent(BaseActivity.this, MainActivity.class));
            }
        });


    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        ((ViewGroup) getWindow().getDecorView()).addView(menu);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (menu.isShowing()) {
            menu.dismiss();
        }
    }
}

menuTwoItemClick () 이벤트에서 창고 상단의 activity가 로그인 페이지인지 판단하고, 만약 그렇지 않으면 이동하지 않고 사용자에게 알립니다.만약에 어떤activity에서menu의item을 클릭해야 한다면 다른 페이지에 파라미터를 가져와야 한다고 생각합니다. 제 생각도 마찬가지로BaseActivty에서 임시 변수를 정의하여 이 파라미터를 저장하거나SharedPreferences 등을 사용해야 합니다. 제 프로젝트에 이런 수요가 없기 때문에 여기에 쓰지 않았지만 이런 수요가 있을 수 있다고 생각합니다.
설명이 필요한 것은 new Global Menu(this)입니다.여기에서menu를 초기화할 때 들어오는 상하문 대상은Activity 대상이어야 합니다. 왜냐하면menu 클래스에서 이 상하문 대상을 통해 화면의 넓이를 가져와야 하기 때문입니다. 물론 최적화할 수 있는 공간이 있습니다...
여기서 알 수 있는 문제는 만약menu의 주 Button이 틈이 있는 벡터 그래프일 때 수축할 때 아래에 덮어씌운 item의 일부분이 나타나 인터페이스에 영향을 미친다는 것이다. 여기서 세 가지 해결 방안을 제공한다.
1>dismiss()에 수축 애니메이션을 위한 감청기를 등록하고 수축 애니메이션이 완성된 후에 거두어들인 item을 숨기고 show()에 item을 표시하면 코드는 다음과 같다.
animatorX.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {

                }

                @Override
                public void onAnimationEnd(Animator animation) {
                    *//*          ,               
                    *         bug,                      ,menu  show   ,   item              
                    *
                    * *//*
                    if (btns.get(finalI).getVisibility() == VISIBLE) {
                        btns.get(finalI).setVisibility(INVISIBLE);
                    }
                }

                @Override
                public void onAnimationCancel(Animator animation) {

                }

                @Override
                public void onAnimationRepeat(Animator animation) {

                }
            });

이렇게 하는 한계성은 내가 이미 주석에서 언급했는데, 나의 원본 코드에서 이 부분의 코드는 주석된 것이다.
2>dismiss()에 애니메이션 감청을 등록하지 않고 show()에 표시하고 dismiss()에 숨기면 수축된 애니메이션을 볼 수 없다.
3>세 번째 방안은 제가 개인적으로 가장 완벽하다고 생각하는 것입니다. 바로 UI라고 완벽한 그림을 크게 잘라서 뒤에 있는 item을 완전히 덮어씌울 수 있습니다. 그러면 그들의 디스플레이와 숨김을 제어하지 않아도 됩니다. 하하하...
시간이 제한되어 이렇게 많은 것을 소개했는데 이 내용도 많지 않은 것 같다. 이 글을 본 어린이신발도 자신의 전역menu를 쉽게 맞춤 제작할 수 있을 거라고 믿고 마지막으로 코드 다운로드 연결을 첨부한다.
http://download.csdn.net/detail/u011907407/9807354
여기에 포인트 1개가 있어야 다운로드할 수 있습니다--저도 최근에 포인트 다운로드 자원이 없습니다. 지나가는 착한 사람이 포인트 2개를 주십시오!!!만약에 건물주와 같은 포인트 가난한 사람도 있다면 자원이 필요하면 당신의 메일박스를 남길 수 있습니다. 제가 답장을 보면 가장 먼저 첨부파일을 보내드리겠습니다--

좋은 웹페이지 즐겨찾기