<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          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ī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  特黄AAAAAAAA片免费直播 | 久久性爱电影 | 亚州高清免费播放 | 波多野结衣一区不卡 | 国产一级片哪里可以看 |