本实例的自定义下拉菜单主要是继承PopupWindow类来实现的弹出窗体,各种布局效果可以根据自己定义设计。弹出的动画效果主要用到了translate、alpha、scale,具体实现步骤如下:
先上效果图如下:左边下拉菜单、中间下拉菜单、右边下拉菜单
1.主界面布局 activity_main.xml:
[html] view
plain copy
- <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:background="#ffffff" >
- <include
- android:id="@+id/main_top"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- layout="@layout/urm_top" />
- <TextView
- android:id="@+id/rule_line_tv"
- android:layout_width="match_parent"
- android:layout_height="0.5dp"
- android:layout_below="@id/main_top"
- android:background="@color/reserve_line" />
- <LinearLayout
- android:id="@+id/main_ll"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_below="@id/rule_line_tv"
- android:gravity="center_vertical"
- android:orientation="horizontal"
- android:padding="10dp" >
- <TextView
- android:id="@+id/left_tv"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:ellipsize="end"
- android:gravity="center_horizontal"
- android:maxLength="4"
- android:singleLine="true"
- android:text="我负责的线索" />
- <TextView
- android:id="@+id/middle_tv"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:ellipsize="end"
- android:gravity="center_horizontal"
- android:maxLength="4"
- android:singleLine="true"
- android:text="团队" />
- <TextView
- android:id="@+id/right_tv"
- android:layout_width="0dp"
- android:layout_height="wrap_content"
- android:layout_weight="1"
- android:ellipsize="end"
- android:gravity="center_horizontal"
- android:maxLength="4"
- android:singleLine="true"
- android:text="自定义" />
- </LinearLayout>
- <TextView
- android:id="@+id/rule_line01_tv"
- android:layout_width="match_parent"
- android:layout_height="0.5dp"
- android:layout_below="@id/main_ll"
- android:background="@color/reserve_line" />
- <TextView
- android:id="@+id/main_tv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:text="主界面" />
- </RelativeLayout>
2.主界面测试类 MainActivity.java
[java] view
plain copy
- package com.popuptest;
- import java.util.ArrayList;
- import android.os.Bundle;
- import android.util.DisplayMetrics;
- import android.view.View;
- import android.view.View.OnClickListener;
- import android.view.Window;
- import android.widget.AdapterView;
- import android.widget.Button;
- import android.widget.ImageButton;
- import android.widget.ImageView;
- import android.widget.LinearLayout;
- import android.widget.TextView;
- import android.widget.AdapterView.OnItemClickListener;
- import android.widget.RelativeLayout.LayoutParams;
- import android.app.Activity;
- public class MainActivity extends Activity implements OnClickListener {
- public static int screenW, screenH;
- private ImageButton backBtn, createBtn;
- private Button confirmBtn;
- private TextView topTv;
- private LinearLayout topll;
- private ImageView topIv;
- private TextView topLineTv;
- private TopMiddlePopup middlePopup;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- requestWindowFeature(Window.FEATURE_NO_TITLE);
- setContentView(R.layout.activity_main);
- getScreenPixels();
- initWidget();
- }
- /**
- * 初始化控件
- */
- private void initWidget() {
- backBtn = (ImageButton) findViewById(R.id.urm_back_btn);
- createBtn = (ImageButton) findViewById(R.id.urm_create_btn);
- confirmBtn = (Button) findViewById(R.id.urm_confirm_btn);
- topll = (LinearLayout) findViewById(R.id.urm_top_ll);
- topIv = (ImageView) findViewById(R.id.urm_top_iv);
- topLineTv = (TextView) findViewById(R.id.rule_line_tv);
- topTv = (TextView) findViewById(R.id.urm_top_tv);
- topTv.setText("企业客户");
- backBtn.setOnClickListener(this);
- createBtn.setOnClickListener(this);
- confirmBtn.setOnClickListener(this);
- topll.setOnClickListener(this);
- }
- /**
- * 设置弹窗
- *
- * @param type
- */
- private void setPopup(int type) {
- middlePopup = new TopMiddlePopup(MainActivity.this, screenW, screenH,
- onItemClickListener, getItemsName(), type);
- }
- /**
- * 设置弹窗内容
- *
- * @return
- */
- private ArrayList<String> getItemsName() {
- ArrayList<String> items = new ArrayList<String>();
- items.add("企业客户");
- items.add("集团客户");
- items.add("公海客户");
- return items;
- }
- @Override
- public void onClick(View v) {
- switch (v.getId()) {
- case R.id.urm_back_btn:
- setPopup(1);
- middlePopup.show(topLineTv);
- break;
- case R.id.urm_create_btn:
- setPopup(2);
- middlePopup.show(topLineTv);
- break;
- case R.id.urm_confirm_btn:
- break;
- case R.id.urm_top_ll:
- setPopup(0);
- middlePopup.show(topLineTv);
- break;
- }
- }
- /**
- * 弹窗点击事件
- */
- private OnItemClickListener onItemClickListener = new OnItemClickListener() {
- @Override
- public void onItemClick(AdapterView<?> parent, View view, int position,
- long id) {
- System.out.println("--onItemClickListener--:");
- middlePopup.dismiss();
- }
- };
- /**
- * 获取屏幕的宽和高
- */
- public void getScreenPixels() {
- DisplayMetrics metrics = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(metrics);
- screenW = metrics.widthPixels;
- screenH = metrics.heightPixels;
- }
- }
3.自定义弹窗类 TopMiddlePopup.java
[java] view
plain copy
- package com.popuptest;
- import java.util.ArrayList;
- import android.content.Context;
- import android.graphics.drawable.ColorDrawable;
- import android.view.LayoutInflater;
- import android.view.MotionEvent;
- import android.view.View;
- import android.view.View.OnTouchListener;
- import android.view.ViewGroup.LayoutParams;
- import android.widget.LinearLayout;
- import android.widget.ListView;
- import android.widget.PopupWindow;
- import android.widget.AdapterView.OnItemClickListener;
- public class TopMiddlePopup extends PopupWindow {
- private Context myContext;
- private ListView myLv;
- private OnItemClickListener myOnItemClickListener;
- private ArrayList<String> myItems;
- private int myWidth;
- private int myHeight;
- private int myType;
- // 判断是否需要添加或更新列表子类项
- private boolean myIsDirty = true;
- private LayoutInflater inflater = null;
- private View myMenuView;
- private LinearLayout popupLL;
- private PopupAdapter adapter;
- public TopMiddlePopup(Context context) {
- // TODO Auto-generated constructor stub
- }
- public TopMiddlePopup(Context context, int width, int height,
- OnItemClickListener onItemClickListener, ArrayList<String> items,
- int type) {
- inflater = (LayoutInflater) context
- .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
- myMenuView = inflater.inflate(R.layout.top_popup, null);
- this.myContext = context;
- this.myItems = items;
- this.myOnItemClickListener = onItemClickListener;
- this.myType = type;
- this.myWidth = width;
- this.myHeight = height;
- System.out.println("--myWidth--:" + myWidth + "--myHeight--:"
- + myHeight);
- initWidget();
- setPopup();
- }
- /**
- * 初始化控件
- */
- private void initWidget() {
- myLv = (ListView) myMenuView.findViewById(R.id.popup_lv);
- popupLL = (LinearLayout) myMenuView.findViewById(R.id.popup_layout);
- myLv.setOnItemClickListener(myOnItemClickListener);
- if (myType == 1) {
- android.widget.RelativeLayout.LayoutParams lpPopup = (android.widget.RelativeLayout.LayoutParams) popupLL
- .getLayoutParams();
- lpPopup.width = (int) (myWidth * 1.0 / 4);
- lpPopup.setMargins(0, 0, (int) (myWidth * 3.0 / 4), 0);
- popupLL.setLayoutParams(lpPopup);
- } else if (myType == 2) {
- android.widget.RelativeLayout.LayoutParams lpPopup = (android.widget.RelativeLayout.LayoutParams) popupLL
- .getLayoutParams();
- lpPopup.width = (int) (myWidth * 1.0 / 4);
- lpPopup.setMargins((int) (myWidth * 3.0 / 4), 0, 0, 0);
- popupLL.setLayoutParams(lpPopup);
- }
- }
- /**
- * 设置popup的样式
- */
- private void setPopup() {
- // 设置AccessoryPopup的view
- this.setContentView(myMenuView);
- // 设置AccessoryPopup弹出窗体的宽度
- this.setWidth(LayoutParams.MATCH_PARENT);
- // 设置AccessoryPopup弹出窗体的高度
- this.setHeight(LayoutParams.MATCH_PARENT);
- // 设置AccessoryPopup弹出窗体可点击
- this.setFocusable(true);
- // 设置AccessoryPopup弹出窗体的动画效果
- if (myType == 1) {
- this.setAnimationStyle(R.style.AnimTopLeft);
- } else if (myType == 2) {
- this.setAnimationStyle(R.style.AnimTopRight);
- } else {
- //this.setAnimationStyle(R.style.AnimTop);
- this.setAnimationStyle(R.style.AnimTopMiddle);
- }
- // 实例化一个ColorDrawable颜色为半透明
- ColorDrawable dw = new ColorDrawable(0x33000000);
- // 设置SelectPicPopupWindow弹出窗体的背景
- this.setBackgroundDrawable(dw);
- myMenuView.setOnTouchListener(new OnTouchListener() {
- @Override
- public boolean onTouch(View v, MotionEvent event) {
- int height = popupLL.getBottom();
- int left = popupLL.getLeft();
- int right = popupLL.getRight();
- System.out.println("--popupLL.getBottom()--:"
- + popupLL.getBottom());
- int y = (int) event.getY();
- int x = (int) event.getX();
- if (event.getAction() == MotionEvent.ACTION_UP) {
- if (y > height || x < left || x > right) {
- System.out.println("---点击位置在列表下方--");
- dismiss();
- }
- }
- return true;
- }
- });
- }
- /**
- * 显示弹窗界面
- *
- * @param view
- */
- public void show(View view) {
- if (myIsDirty) {
- myIsDirty = false;
- adapter = new PopupAdapter(myContext, myItems, myType);
- myLv.setAdapter(adapter);
- }
- showAsDropDown(view, 0, 0);
- }
- }
4.自定义弹窗布局 top_popup.xml
[html] view
plain copy
- <?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/popup_layout"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentTop="true"
- android:background="#ffffff"
- android:orientation="vertical" >
- <ListView
- android:id="@+id/popup_lv"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:divider="@color/content_line"
- android:dividerHeight="0.5dp" >
- </ListView>
- <TextView
- android:layout_width="match_parent"
- android:layout_height="0.5dp"
- android:background="@color/reserve_line" />
- </LinearLayout>
- </RelativeLayout>
5.弹窗类表适配器类 PopupAdapter
[java] view
plain copy
- package com.popuptest;
- import java.util.ArrayList;
- import android.content.Context;
- import android.view.Gravity;
- import android.view.LayoutInflater;
- import android.view.View;
- import android.view.ViewGroup;
- import android.widget.BaseAdapter;
- import android.widget.RelativeLayout.LayoutParams;
- import android.widget.TextView;
- public class PopupAdapter extends BaseAdapter {
- private Context myContext;
- private LayoutInflater inflater;
- private ArrayList<String> myItems;
- private int myType;
- public PopupAdapter(Context context, ArrayList<String> items, int type) {
- this.myContext = context;
- this.myItems = items;
- this.myType = type;
- inflater = LayoutInflater.from(myContext);
- }
- @Override
- public int getCount() {
- return myItems.size();
- }
- @Override
- public String getItem(int position) {
- return myItems.get(position);
- }
- @Override
- public long getItemId(int position) {
- return 0;
- }
- @Override
- public View getView(int position, View convertView, ViewGroup parent) {
- PopupHolder holder = null;
- if (convertView == null) {
- holder = new PopupHolder();
- convertView = inflater.inflate(R.layout.top_popup_item, null);
- holder.itemNameTv = (TextView) convertView
- .findViewById(R.id.popup_tv);
- if (myType == 0) {
- holder.itemNameTv.setGravity(Gravity.CENTER);
- } else if (myType == 1) {
- holder.itemNameTv.setGravity(Gravity.LEFT);
- } else if (myType == 2) {
- holder.itemNameTv.setGravity(Gravity.RIGHT);
- }
- convertView.setTag(holder);
- } else {
- holder = (PopupHolder) convertView.getTag();
- }
- String itemName = getItem(position);
- holder.itemNameTv.setText(itemName);
- return convertView;
- }
- private class PopupHolder {
- TextView itemNameTv;
- }
- }
6.子item布局 top_popup_item.xml
[html] view
plain copy
- <?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="wrap_content"
- android:background="#ffffff"
- android:padding="10dp" >
- <TextView
- android:id="@+id/popup_tv"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- style="@style/urm_tv"/>
- </RelativeLayout>
7.主界面顶部布局 urm_top.xml
[html] view
plain copy
- <?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="wrap_content"
- android:background="#eeeeee" >
- <ImageButton
- android:id="@+id/urm_back_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentLeft="true"
- android:background="@null"
- android:contentDescription="@string/app_name"
- android:src="@drawable/back" />
- <LinearLayout
- android:id="@+id/urm_top_ll"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:gravity="center_vertical"
- android:orientation="horizontal" >
- <TextView
- android:id="@+id/urm_top_tv"
- style="@style/main_tv_style"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="企业客户" />
- <ImageView
- android:id="@+id/urm_top_iv"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_marginLeft="5dp"
- android:background="@null"
- android:contentDescription="@string/app_name"
- android:src="@drawable/switch02" />
- </LinearLayout>
- <RelativeLayout
- android:id="@+id/urm_top_right_rl"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:layout_centerVertical="true" >
- <ImageButton
- android:id="@+id/urm_create_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@null"
- android:contentDescription="@string/app_name"
- android:src="@drawable/btn_add_2x" />
- <Button
- android:id="@+id/urm_confirm_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:background="@null"
- android:gravity="center_vertical"
- android:padding="10dp"
- android:text="确定"
- android:textColor="@color/blue2"
- android:textSize="18sp"
- android:visibility="gone" />
- </RelativeLayout>
- <ImageButton
- android:id="@+id/urm_search_btn"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerVertical="true"
- android:layout_toLeftOf="@id/urm_top_right_rl"
- android:background="@null"
- android:contentDescription="@string/app_name"
- android:src="@drawable/search"
- android:visibility="gone" />
- </RelativeLayout>
8.styles.xml文件
[html] view
plain copy
- <resources>
- <!--
- Base application theme, dependent on API level. This theme is replaced
- by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
- -->
- <style name="AppBaseTheme" parent="android:Theme.Light">
- <!--
- Theme customizations available in newer API levels can go in
- res/values-vXX/styles.xml, while customizations related to
- backward-compatibility can go here.
- -->
- </style>
- <!-- Application theme. -->
- <style name="AppTheme" parent="AppBaseTheme">
- <!-- All customizations that are NOT specific to a particular API-level can go here. -->
- </style>
- <style name="AnimTop" parent="@android:style/Animation">
- <item name="android:windowEnterAnimation">@anim/push_top_in</item>
- <item name="android:windowExitAnimation">@anim/push_top_out</item>
- </style>
- <style name="AnimTopRight" parent="@android:style/Animation">
- <item name="android:windowEnterAnimation">@anim/top_right_in</item>
- <item name="android:windowExitAnimation">@anim/top_right_out</item>
- </style>
- <style name="AnimTopLeft" parent="@android:style/Animation">
- <item name="android:windowEnterAnimation">@anim/top_left_in</item>
- <item name="android:windowExitAnimation">@anim/top_left_out</item>
- </style>
- <style name="AnimTopMiddle" parent="@android:style/Animation">
- <item name="android:windowEnterAnimation">@anim/top_middle_in</item>
- <item name="android:windowExitAnimation">@anim/top_middle_out</item>
- </style>
- <style name="main_tv_style">
- <item name="android:textSize">20sp</item>
- <item name="android:textColor">#000000</item>
- </style>
- <style name="urm_tv">
- <item name="android:textSize">18sp</item>
- </style>
- </resources>
9.各种动画效果
push_top_in.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <!-- 从屏幕上面进入 -->
- <set xmlns:android="http://schemas.android.com/apk/res/android" >
- <translate
- android:duration="500"
- android:fromYDelta="-100%p"
- android:toYDelta="0" />
- <alpha
- android:duration="500"
- android:fromAlpha="0.0"
- android:toAlpha="1.0" />
- </set>
push_top_out.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <!-- 从屏幕上面退出 -->
- <set xmlns:android="http://schemas.android.com/apk/res/android" >
- <translate
- android:duration="500"
- android:fromYDelta="0"
- android:toYDelta="-100%p" />
- <alpha
- android:duration="500"
- android:fromAlpha="1.0"
- android:toAlpha="0.0" />
- </set>
top_left_in.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android">
- <scale
- android:duration="500"
- android:fillAfter="false"
- android:fromXScale="0.0"
- android:fromYScale="0.0"
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:pivotX="0%"
- android:pivotY="0%"
- android:toXScale="1.0"
- android:toYScale="1.0" />
- </set>
top_left_out.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android" >
- <scale
- android:duration="500"
- android:fillAfter="false"
- android:fromXScale="1.0"
- android:fromYScale="1.0"
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:pivotX="0%"
- android:pivotY="0%"
- android:toXScale="0.0"
- android:toYScale="0.0" />
- </set>
top_middle_in.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android">
- <scale
- android:duration="500"
- android:fillAfter="false"
- android:fromXScale="0.0"
- android:fromYScale="0.0"
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:pivotX="50%"
- android:pivotY="0%"
- android:toXScale="1.0"
- android:toYScale="1.0" />
- </set>
top_middle_out.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android" >
- <scale
- android:duration="500"
- android:fillAfter="false"
- android:fromXScale="1.0"
- android:fromYScale="1.0"
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:pivotX="50%"
- android:pivotY="0%"
- android:toXScale="0.0"
- android:toYScale="0.0" />
- </set>
top_right_in.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android">
- <scale
- android:duration="500"
- android:fillAfter="false"
- android:fromXScale="0.0"
- android:fromYScale="0.0"
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:pivotX="100%"
- android:pivotY="0%"
- android:toXScale="1.0"
- android:toYScale="1.0" />
- </set>
top_right_out.xml
[html] view
plain copy
- <?xml version="1.0" encoding="utf-8"?>
- <set xmlns:android="http://schemas.android.com/apk/res/android" >
- <scale
- android:duration="500"
- android:fillAfter="false"
- android:fromXScale="1.0"
- android:fromYScale="1.0"
- android:interpolator="@android:anim/accelerate_decelerate_interpolator"
- android:pivotX="100%"
- android:pivotY="0%"
- android:toXScale="0.0"
- android:toYScale="0.0" />
- </set>
运行项目即可搞定!