国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > Android > 正文

Android仿網易嚴選底部彈出菜單效果

2019-12-12 02:27:02
字體:
來源:轉載
供稿:網友

在網易嚴選的看東西的時候在商品詳情頁里看到他的底部彈出菜單,本能反應是想用DottomSheetDialog或者PopupWindow來實現,可是發現實現不了他那種效果,于是就自己模仿一個像嚴選這樣的底部彈出菜單。

不管是DottomSheetDialog或者PopupWindow他們的陰影背景都是全部覆蓋的,這就造成除了菜單內容的View之外其他都是陰影的,而嚴選不是這樣的。嘮叨到此,首先展示效果圖如下:

是不是還可以呢,由于代碼量不多卻注釋詳細,所以先貼出代碼再一一詳說:

BottomPopupWindowView類:

 public class BottomPopupWindowView extends LinearLayout{  private AnimatorListener animatorListener;  //底部內容的View  private FrameLayout base_view;  //內容的View  private FrameLayout content_view;  //背景的View  private RelativeLayout popup_bg;  //xml加載的View  private View bottomPopouView;  //外部加載的內容View  private View contentView;  //外部加載的底部內容View  private View baseView;  //手勢的最小值  private float minVelocity=0;  //加載一次的判斷值  private boolean mDrawable=true;  public void setAnimatorListener(AnimatorListener animatorListener) {    this.animatorListener = animatorListener;  }  public void setBaseView(View baseView){    this.baseView=baseView;  }  public void setContextView(View view){    this.contentView=view;  }  public void setContentView(int id){    this.contentView=LayoutInflater.from(getContext()).inflate(id,null);  }  public BottomPopupWindowView(Context context) {    this(context,null);  }  public BottomPopupWindowView(Context context, @Nullable AttributeSet attrs) {    this(context,attrs,0);  }  public BottomPopupWindowView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {    super(context, attrs, defStyleAttr);    //初始化各種數值    minVelocity=ViewConfiguration.get(getContext()).getScaledTouchSlop();    bottomPopouView= LayoutInflater.from(getContext()).inflate(R.layout.layout_bottom_popup,null);    base_view=(FrameLayout)bottomPopouView.findViewById(R.id.bottom_view);    content_view=(FrameLayout)bottomPopouView.findViewById(R.id.content_view);    popup_bg=(RelativeLayout)bottomPopouView.findViewById(R.id.popup_bg);    //把整個View都加載在LinearLayout里以顯示出來    addView(bottomPopouView);    //背景顏色監聽    popup_bg.setOnClickListener(new OnClickListener() {      @Override      public void onClick(View v) {        disMissPopupView();      }    });    //屏蔽內容區域點擊事件    content_view.setOnClickListener(new OnClickListener() {      @Override      public void onClick(View view){}    });    //屏蔽底部內容區域點擊事件    base_view.setOnClickListener(new OnClickListener() {      @Override      public void onClick(View view){}    });    //內容區域判斷是否向下,手勢向下就關閉彈框    content_view.setOnTouchListener(new OnTouchListener() {      @Override      public boolean onTouch(View view, MotionEvent motionEvent) {        float y1=0,y2=0;        if(motionEvent.getAction() == MotionEvent.ACTION_DOWN) {          y1 = motionEvent.getY();        }        if(motionEvent.getAction() == MotionEvent.ACTION_UP){          y2 = motionEvent.getY();          if((y2-y1)>minVelocity){            disMissPopupView();          }        }        return false;      }    });  }  @Override  protected void onDraw(Canvas canvas) {    super.onDraw(canvas);    if(mDrawable&&baseView!=null){      //剛開始加載底部內容區域,只需一次就行,多次報錯      base_view.addView(baseView);      mDrawable=false;    }  }  public void showPopouView(){    if(contentView!=null){      //開始動畫數據      startAnimation();      //開啟背景顏色的漸變動畫      popup_bg.setVisibility(View.VISIBLE);      popup_bg.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.bp_bottom_bg_in));      //把這個區域全部顯示出來      ((BottomPopupWindowView)this).setLayoutParams(new RelativeLayout.LayoutParams(          RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));      //假如內容區域      content_view.addView(contentView,0);      content_view.setVisibility(View.VISIBLE);      //開啟內容區域動畫      content_view.setAnimation(AnimationUtils.loadAnimation(getContext(),R.anim.bp_bottom_view_in));    }  }  public void disMissPopupView(){    //開始關閉動畫數據    endAnimation();    //開啟內容區域動畫    content_view.setVisibility(View.GONE);    Animation animation=AnimationUtils.loadAnimation(getContext(),R.anim.bp_bottom_view_out);    animation.setAnimationListener(new Animation.AnimationListener() {      @Override      public void onAnimationStart(Animation animation) {}      @Override      public void onAnimationRepeat(Animation animation) {}      @Override      public void onAnimationEnd(Animation animation) {        //等內容區域動畫結束后,清楚所有View        content_view.removeAllViews();        //開啟背景顏色的漸變動畫        popup_bg.setVisibility(View.GONE);        popup_bg.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.bp_bottom_bg_out));        //把整個控件的大小恢復到底部View區域的大小        RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(            RelativeLayout.LayoutParams.MATCH_PARENT,getViewHeight((BottomPopupWindowView)BottomPopupWindowView.this));        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,-1);        ((BottomPopupWindowView)BottomPopupWindowView.this).setLayoutParams(layoutParams);      }    });    //開始動畫    content_view.setAnimation(animation);  }  //獲取View的高度  public int getViewHeight(View view){    int width =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);    int height =View.MeasureSpec.makeMeasureSpec(0,View.MeasureSpec.UNSPECIFIED);    view.measure(width,height);    return view.getMeasuredHeight();  }  //開始動畫數據變化  public void startAnimation(){    ValueAnimator valueAnimator = ValueAnimator.ofInt(0,40);    valueAnimator.setDuration(250);    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {      @Override      public void onAnimationUpdate(ValueAnimator valueAnimator) {        if(animatorListener!=null){          animatorListener.startValue((int) valueAnimator.getAnimatedValue());        }      }    });    valueAnimator.start();  }  //結束動畫數值變化  public void endAnimation() {    ValueAnimator valueAnimator = ValueAnimator.ofInt(40,0);    valueAnimator.setDuration(250);    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {      @Override      public void onAnimationUpdate(ValueAnimator valueAnimator) {        if(animatorListener!=null){          animatorListener.endValue((int) valueAnimator.getAnimatedValue());        }      }    });    valueAnimator.start();  }}

對應的加載的xml布局是:
layout_bottom_popou.xml如下:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:orientation="vertical"  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:background="#707A7A7A">  <RelativeLayout    android:id="@+id/popup_bg"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="#707A7A7A"    android:layout_above="@+id/bottom_view"></RelativeLayout>  <FrameLayout    android:id="@+id/content_view"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_above="@+id/bottom_view"    android:orientation="horizontal">  </FrameLayout>  <FrameLayout    android:id="@+id/bottom_view"    android:layout_width="match_parent"    android:layout_height="wrap_content"    android:layout_alignParentBottom="true"></FrameLayout></RelativeLayout>

1.在BottomPopupWindowView是繼承LinearLayout,而layout_bottom_popou.xml是這整個BottomPopupWindowView里的骨架,然后在BottomPopupWindowView初始化的時候通過addView()來加載整個骨架布局。在onDraw()里只需加載一次baseView就可以了,不然后重復加載導致報錯。這樣就初始化成功了,剛開始只會加載baseView的界面,就相當于嚴選最下面的購物車立即購買等界面。

2.當調用showPopouView()時顯示菜單的。startAnimation()方法只是為了產生動畫的數據。

popup_bg.setVisibility(View.VISIBLE);popup_bg.setAnimation(AnimationUtils.loadAnimation(getContext(), R.anim.bp_bottom_bg_in));

只是為了開啟背景漸變的動畫沒什么說的。最重要的是顯示菜單實現是把BottomPopupWindowView的大小擴展到全屏,所以設置((BottomPopupWindowView)this).setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT,RelativeLayout.LayoutParams.MATCH_PARENT));,然后把彈出菜單的View即contentView裝進content_view即可,然后開啟彈出動畫就實現了。

3.最后是disMissPopupView()方法關閉彈窗。endAnimation()方法只是為了產生動畫的數據。再啟動內容域View即content_View的退出動畫,在動畫結束后用content_view.removeAllViews();
起初菜單內容,再像上面一樣開啟背景顏色漸變動畫,最后只需使BottomPopupWindowView恢復原來的baseView的大小及可以了,具體如下:

RelativeLayout.LayoutParams layoutParams=new RelativeLayout.LayoutParams(     RelativeLayout.LayoutParams.MATCH_PARENT,getViewHeight((BottomPopupWindowView)BottomPopupWindowView.this));        layoutParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM,-1);        ((BottomPopupWindowView)BottomPopupWindowView.this).setLayoutParams(layoutParams);

這就是核心的代碼功能了,代碼量不多具體細節看上面的源碼。

有人或許會問返回動畫的數據有什么用,很簡單就是為了實現嚴選菜單框出來時整個上面詳情的縮放。具體看如下demo,首先給出界面xml,如下:

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  android:layout_width="match_parent"  android:layout_height="match_parent">  <LinearLayout    android:id="@+id/main_view"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@color/colorAccent"    android:orientation="vertical">    <ImageView      android:id="@+id/banner_img"      android:layout_width="match_parent"      android:layout_height="300dp"      android:scaleType="fitXY"      android:src="@mipmap/banner"/>    <View      android:layout_width="match_parent"      android:layout_height="0.1dp"      android:background="@color/colorPrimary"></View>    <RelativeLayout      android:id="@+id/guige"      android:layout_width="match_parent"      android:layout_height="50dp"      android:background="#ffffff">      <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_centerVertical="true"        android:layout_marginLeft="15dp"        android:textSize="15dp"        android:text="規格數量選擇"/>      <ImageView        android:layout_width="20dp"        android:layout_height="20dp"        android:layout_alignParentRight="true"        android:layout_centerVertical="true"        android:layout_marginRight="15dp"        android:src="@mipmap/ic_jiantou"/>    </RelativeLayout>    <View      android:layout_width="match_parent"      android:layout_height="0.1dp"      android:background="@color/colorPrimary"></View>  </LinearLayout>  <com.jack.bottompopupwindowview.BottomPopupWindowView    android:id="@+id/bottom_popup"    android:layout_width="match_parent"    android:layout_height="50dp"    android:background="@android:color/transparent"    android:layout_alignParentBottom="true">  </com.jack.bottompopupwindowview.BottomPopupWindowView></RelativeLayout>

這就是上面效果圖的界面布局,沒什么可以說的,再看事例代碼如下:

public class MainActivity extends AppCompatActivity implements View.OnClickListener, AnimatorListener {  private BottomPopupWindowView bottomPopupWindowView;  private View contentView;  private View bottomView;  private LinearLayout mainView;  @Override  protected void onCreate(Bundle savedInstanceState) {    super.onCreate(savedInstanceState);    setContentView(R.layout.activity_main);    mainView=(LinearLayout)findViewById(R.id.main_view);    bottomView=LayoutInflater.from(this).inflate(R.layout.layout_bottom_view,null);    (bottomView.findViewById(R.id.promptly_buy)).setOnClickListener(this);    (findViewById(R.id.guige)).setOnClickListener(this);    bottomPopupWindowView=(BottomPopupWindowView)findViewById(R.id.bottom_popup);    bottomPopupWindowView.setOnClickListener(this);    bottomPopupWindowView.setBaseView(bottomView);    contentView=LayoutInflater.from(this).inflate(R.layout.layout_content_view,null);    bottomPopupWindowView.setContextView(contentView);    (contentView.findViewById(R.id.ic_cancel)).setOnClickListener(this);    bottomPopupWindowView.setAnimatorListener(this);  }  @Override  public void onClick(View view) {    switch(view.getId()){      case R.id.promptly_buy:      case R.id.ic_cancel:        bottomPopupWindowView.disMissPopupView();        break;      case R.id.guige:        bottomPopupWindowView.showPopouView();        break;    }  }  @Override  public void startValue(int value) {    setMargins (mainView,value-10,value,value-10,value);  }  @Override  public void endValue(int value) {    setMargins (mainView,value,value,value,value);  }  public static void setMargins (View v, int l, int t, int r, int b) {    if (v.getLayoutParams() instanceof ViewGroup.MarginLayoutParams) {      ViewGroup.MarginLayoutParams p = (ViewGroup.MarginLayoutParams) v.getLayoutParams();      p.setMargins(l, t, r, b);      v.requestLayout();    }  }}

其中設置內容菜單的View
BottomPopupWindowView.setContextView(bottomView);
設置沒有顯示菜單時候顯示的View(注:bottomView的高度要和BottomPopupWindowView的高度一樣,具體看demo)
BottomPopupWindowView.setBaseView(bottomView);

而回調的public void startValue(int value)和public void endValue(int value)設置動畫監聽放回的數據,以便根據數據實現動畫,嚴選的彈出和顯示商品詳情動畫很簡單就是不斷設設置View的間距就可以了。

最后附上demo和源碼鏈接https://github.com/jack921/BottomPopupWindowDemo

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 辉县市| 明光市| 北海市| 滨州市| 宜都市| 鄂伦春自治旗| 靖安县| 墨江| 藁城市| 楚雄市| 桓台县| 凤阳县| 贵州省| 卢氏县| 芦山县| 年辖:市辖区| 启东市| 老河口市| 湖南省| 青龙| 永福县| 贵南县| 宝鸡市| 察雅县| 湘乡市| 巍山| 南充市| 赤城县| 蒙阴县| 万州区| 天津市| 泽州县| 富川| 涿州市| 兴隆县| 攀枝花市| 清原| 海原县| 商都县| 峡江县| 灌阳县|