1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Android仿大眾點評多條目下拉菜單篩選

        共 10306字,需瀏覽 21分鐘

         ·

        2022-07-07 22:14

        首先來看看我們要實現(xiàn)的效果,下面這張圖是大眾點評APP里面的一個多條目下拉菜單篩選的一個效果,這是很多App里面都比較常見的一種多條目篩選菜單。



        結(jié)構(gòu)分析:



        整個控件我么用一個LinearLayout  實現(xiàn),所以我們要繼承LinearLayout  .然后是上面紅色長方形部分的Tab欄,下面最外層黑色框框是一個FrameLayout用來存放陰影(綠色框框部分)和菜單布局(最里面紅色框框部分)


        實現(xiàn)

        分析完了,我們就可以用代碼來實現(xiàn)了,代碼如下:


        1、基本布局:

        public class ListDataScreenView extends LinearLayout  {    private Context mContext;    // 1.1 創(chuàng)建頭部用來存放 Tab    private LinearLayout mMenuTabView;    // 1.2 創(chuàng)建 FrameLayout 用來存放 = 陰影(View) + 菜單內(nèi)容布局(FrameLayout)    private FrameLayout mMenuMiddleView;    // 陰影    private View mShadowView;    // 創(chuàng)建菜單用來存放菜單內(nèi)容    private FrameLayout mMenuContainerView;    // 陰影的顏色    private int mShadowColor = 0x88888888;    // 篩選菜單的 Adapter    private BaseMenuAdapter mAdapter;    // 內(nèi)容菜單的高度    private int mMenuContainerHeight;    // 當(dāng)前打開的位置    private int mCurrentPosition = -1;    private long DURATION_TIME = 350;    // 動畫是否在執(zhí)行    private boolean mAnimatorExecute;
        public ListDataScreenView(Context context) { this(context, null); }
        public ListDataScreenView(Context context, @Nullable AttributeSet attrs) { this(context, attrs, 0); }
        public ListDataScreenView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); mContext = context; initLayout(); }
        /** * 1.布局實例化好 (組合控件) */ private void initLayout() { // 1. 先創(chuàng)建一個 xml 布局 ,再加載,findViewById // 2. 簡單的效果用代碼去創(chuàng)建 早期IOS 用代碼創(chuàng)建布局 setOrientation(VERTICAL);
        // 1.1 創(chuàng)建頭部用來存放 Tab mMenuTabView = new LinearLayout(mContext); mMenuTabView.setLayoutParams(new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); addView(mMenuTabView);
        // 1.2 創(chuàng)建 FrameLayout 用來存放 = 陰影(View) + 菜單內(nèi)容布局(FrameLayout) mMenuMiddleView = new FrameLayout(mContext); LinearLayout.LayoutParams params = new LinearLayout.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT, 0); params.weight = 1; mMenuMiddleView.setLayoutParams(params); addView(mMenuMiddleView);
        // 創(chuàng)建陰影 可以不用設(shè)置 LayoutParams 默認(rèn)就是 MATCH_PARENT ,MATCH_PARENT mShadowView = new View(mContext); mShadowView.setBackgroundColor(mShadowColor); mShadowView.setAlpha(0f); mShadowView.setOnClickListener(this); mShadowView.setVisibility(GONE); mMenuMiddleView.addView(mShadowView);//陰影View在下面
        // 創(chuàng)建菜單用來存放菜單內(nèi)容 mMenuContainerView = new FrameLayout(mContext); mMenuContainerView.setBackgroundColor(Color.WHITE); mMenuMiddleView.addView(mMenuContainerView);//菜單內(nèi)容在上面 }
        @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); Log.e("TAG", "onMeasure"); int height = MeasureSpec.getSize(heightMeasureSpec); if (mMenuContainerHeight == 0 && height > 0) { // 內(nèi)容的高度應(yīng)該不是全部 應(yīng)該是整個 View的 75% mMenuContainerHeight = (int) (height * 75f / 100); //獲取菜單內(nèi)容View的LayoutParams ViewGroup.LayoutParams params = mMenuContainerView.getLayoutParams(); //設(shè)置菜單內(nèi)容的高度 params.height = mMenuContainerHeight; mMenuContainerView.setLayoutParams(params); // 進(jìn)來的時候陰影不顯示 ,內(nèi)容也是不顯示的(把它移上去) //放菜單內(nèi)容 mMenuContainerView.setTranslationY(-mMenuContainerHeight); }    }}


        2、設(shè)置點擊事件,以及過程中的動畫

         /**     * 設(shè)置tab的點擊     *     * @param tabView     * @param position     */    private void setTabClick(final View tabView, final int position) {        tabView.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                if (mCurrentPosition == -1) {                    // 沒打開                    openMenu(position, tabView);                } else {                    if (mCurrentPosition == position) {                        // 打開了,關(guān)閉                        closeMenu();                    } else {                        // 切換一下顯示                        //拿到菜單容器里的子view(TextView)                        View currentMenu = mMenuContainerView.getChildAt(mCurrentPosition);                        currentMenu.setVisibility(View.GONE);//將子view(TextView)設(shè)置無不可見                        mAdapter.menuClose(mMenuTabView.getChildAt(mCurrentPosition));
        //拿到當(dāng)前點擊的位置 mCurrentPosition = position; currentMenu = mMenuContainerView.getChildAt(mCurrentPosition); currentMenu.setVisibility(View.VISIBLE); mAdapter.menuOpen(mMenuTabView.getChildAt(mCurrentPosition)); } } } }); }
        /** * 關(guān)閉菜單 */ private void closeMenu() { //動畫正在執(zhí)行,點擊無效 if (mAnimatorExecute) { return; } // 關(guān)閉動畫 位移動畫 透明度動畫 ObjectAnimator translationAnimator = ObjectAnimator.ofFloat(mMenuContainerView, "translationY", 0, -mMenuContainerHeight); translationAnimator.setDuration(DURATION_TIME); translationAnimator.start(); mShadowView.setVisibility(View.VISIBLE); ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha", 1f, 0f); alphaAnimator.setDuration(DURATION_TIME); // 要等關(guān)閉動畫執(zhí)行完才能去隱藏當(dāng)前菜單 alphaAnimator.addListener(new AnimatorListenerAdapter() { //動畫執(zhí)行完畢 @Override public void onAnimationEnd(Animator animation) { View menuView = mMenuContainerView.getChildAt(mCurrentPosition); menuView.setVisibility(View.GONE); mCurrentPosition = -1; mShadowView.setVisibility(GONE); mAnimatorExecute = false; }
        //關(guān)閉菜單動畫開始 @Override public void onAnimationStart(Animator animation) { mAnimatorExecute = true; mAdapter.menuClose(mMenuTabView.getChildAt(mCurrentPosition)); } }); alphaAnimator.start(); }
        /** * 打開菜單 * * @param position * @param tabView */ private void openMenu(final int position, final View tabView) { //動畫正在執(zhí)行,點擊無效 if (mAnimatorExecute) { return; } //設(shè)置陰影可見 mShadowView.setVisibility(View.VISIBLE); // 獲取當(dāng)前位置顯示當(dāng)前菜單,菜單是加到了菜單容器 View menuView = mMenuContainerView.getChildAt(position); menuView.setVisibility(View.VISIBLE);
        // 打開開啟動畫 位移動畫 透明度動畫 //位移動畫 ObjectAnimator translationAnimator = ObjectAnimator.ofFloat(mMenuContainerView, "translationY", -mMenuContainerHeight, 0); translationAnimator.setDuration(DURATION_TIME); translationAnimator.start();
        //透明度動畫 ObjectAnimator alphaAnimator = ObjectAnimator.ofFloat(mShadowView, "alpha", 0f, 1f); alphaAnimator.setDuration(DURATION_TIME); alphaAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { mAnimatorExecute = false; mCurrentPosition = position; }
        @Override public void onAnimationStart(Animator animation) { mAnimatorExecute = true; // 把當(dāng)前的 tab 傳到外面 mAdapter.menuOpen(tabView); } }); alphaAnimator.start(); }


        3、寫Adapter提供數(shù)據(jù)源


        這個時候我們的效果還是死的,我么得給他設(shè)置寫一個Adapter,現(xiàn)實情況下,我們的數(shù)據(jù)也是通常要去網(wǎng)絡(luò)獲取,所以不能寫死。

        >BaseMenuAdapter /** * 篩選菜單的 Adapter */
        public abstract class BaseMenuAdapter { // 獲取總共有多少條 public abstract int getCount(); // 獲取當(dāng)前的TabView public abstract View getTabView(int position, ViewGroup parent); // 獲取當(dāng)前的菜單內(nèi)容 public abstract View getMenuView(int position, ViewGroup parent);
        /** * 菜單打開 * @param tabView */ public void menuOpen(View tabView) {
        }
        /** * 菜單關(guān)閉 * @param tabView */ public void menuClose(View tabView) {
        }}

        具體的Adapter:

        public class ListScreenMenuAdapter extends BaseMenuAdapter{    private Context mContext;
        public ListScreenMenuAdapter(Context context){ this.mContext = context; }
        private String[] mItems ={"附近","美食","智能排序","篩選"};
        @Override public int getCount() { return mItems.length; }
        @Override public View getTabView(int position, ViewGroup parent) { TextView tabView = (TextView) LayoutInflater.from(mContext).inflate(R.layout.ui_list_data_screen_tab,parent,false); tabView.setText(mItems[position]); tabView.setTextColor(Color.BLACK); return tabView; }
        @Override public View getMenuView(int position, ViewGroup parent) { // 真正開發(fā)過程中,不同的位置顯示的布局不一樣 TextView menuView = (TextView) LayoutInflater.from(mContext).inflate(R.layout.ui_list_data_screen_menu,parent,false); menuView.setText(mItems[position]); return menuView; }
        @Override public void menuClose(View tabView) { TextView tabTv = (TextView) tabView; tabTv.setTextColor(Color.BLACK); }
        @Override public void menuOpen(View tabView) { TextView tabTv = (TextView) tabView; tabTv.setTextColor(Color.RED); }}


        有了Adapter之后,我們就可以給ListDataScreenView 以下方法,是不是感覺跟ListView很像。

         /**     * 設(shè)置 Adapter     *     * @param adapter     */    public void setAdapter(BaseMenuAdapter adapter) {        this.mAdapter = adapter;        // 獲取有多少條        int count = mAdapter.getCount();        for (int i = 0; i < count; i++) {            // 獲取菜單的Tab            View tabView = mAdapter.getTabView(i, mMenuTabView);            mMenuTabView.addView(tabView);//加一個TextView            LinearLayout.LayoutParams params = (LayoutParams) tabView.getLayoutParams();            params.weight = 1;            tabView.setLayoutParams(params);
        // 設(shè)置tab點擊事件 setTabClick(tabView, i);
        // 獲取菜單的內(nèi)容(一個TextView) View menuView = mAdapter.getMenuView(i, mMenuContainerView); menuView.setVisibility(GONE); mMenuContainerView.addView(menuView); } // 內(nèi)容還沒有顯示出來,打開的時候顯示當(dāng)前位置的菜單,關(guān)閉的時候隱藏,陰影點擊應(yīng)該要關(guān)閉菜單 // 動畫在執(zhí)行的情況下就不要在響應(yīng)動畫事件 // 打開和關(guān)閉 變化tab的顯示 , 肯定不能把代碼寫到 ListDataScreen 里面來 // 當(dāng)菜單是打開的狀態(tài) 不要執(zhí)行動畫只要切換    }

        最后看下我們實現(xiàn)的效果:



        到這里就結(jié)束啦。

        瀏覽 177
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            操美女免费视频 | 亚洲综合免费 | 韩国午夜久久久精品影院 | 北条麻妃中文字幕在线视频 | 无码高清网站 | 欧美激情hd | 四虎精品永久在线 | 熟女大香焦 | 日日日网站 | 国产三级在线观看完整版 |