1.android实现底部弹框的两种实现方式:
(1) 使用系统自带对话框AlertDialog 实现
(2)自定义对话框实现
1.1使用系统自带对话框AlertDialog 实现
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mButton;
private String[] items = {"色情/辱骂", "广告骚扰", "政治", "其他"};
@Override
protected void onCreate(Bundle savedInstanceState) {
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mButton = (Button) findViewById(R.id.activity_bt);
initListener();
}
private void initListener() {
mButton.setOnClickListener(this);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.activity_bt:
showDialog();
break;
}
}
private void showDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setItems(items, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, items + "", Toast.LENGTH_SHORT);
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Toast.makeText(MainActivity.this, "取消", Toast.LENGTH_SHORT).show();
}
});
AlertDialog mDialog = builder.create();
mDialog.show();
Window window = mDialog.getWindow();
window.setGravity(Gravity.BOTTOM);
window.setWindowAnimations(R.style.popupAnimation);
mDialog.setCanceledOnTouchOutside(true);
mDialog.setCancelable(true);
}
}
动画主题
anim文件夹下进入代码 pop_in.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromYDelta="100%p"
android:toYDelta="0" />
</set>
anim文件夹下退出代码pop_out.xml:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
<translate
android:duration="300"
android:fromYDelta="0"
android:toYDelta="100%p" />
</set>
styles.xml 主题
<!-- alertDialog animation 样式 -->
<style name="popupAnimation" parent="android:Animation">
<item name="android:windowEnterAnimation">@anim/pop_in</item>
<item name="android:windowExitAnimation">@anim/pop_out</item>
</style>
运行效果图如下:
这是第一种底部弹出提示框的实现方法。
(2)可能你已经发现了,其实Alertdialog 并不是紧挨着底部的,另外就是两边也会留下间隙,这是主题导致的。要想去除掉间隙,可以使用我们可以使用第二种方法:
在这里我贴出showDialog()的方法,其他的部分和上面的一样,
private void showDialog() {
AlertDialog mDialog = new AlertDialog.Builder(this).create();
mDialog.show();
Window window = mDialog.getWindow();
window.setGravity(Gravity.BOTTOM);
window.setWindowAnimations(R.style.popupAnimation);
View view = View.inflate(this, R.layout.alert_dialog_view, null);
final TextView mAdTv = (TextView) view.findViewById(R.id.dialog_ad);
final TextView mSexTv = (TextView) view.findViewById(R.id.dialog_eroticism);
mAdTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "mAdTv.getText():" + mAdTv.getText(), Toast.LENGTH_SHORT).show();
}
});
mSexTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "mSexTv.getText():" + mSexTv.getText(), Toast.LENGTH_SHORT).show();
}
});
window.setContentView(view);
window.setLayout(WindowManager.LayoutParams.MATCH_PARENT, WindowManager.LayoutParams.WRAP_CONTENT);//设置横向全屏
mDialog.setCanceledOnTouchOutside(true);
mDialog.setCancelable(true);
}
layout.alert_dialog_view的布局如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/dialog_ad"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#46a3e7"
android:gravity="center"
android:text="广告" />
<View
android:layout_width="match_parent"
android:layout_height="0.5dp"
android:background="#dddddd" />
<TextView
android:id="@+id/dialog_eroticism"
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="#46a3e7"
android:gravity="center"
android:text="色情" />
</LinearLayout>
效果图如下:
通过自定义布局的形式就能实现从底部弹出,并且没有和屏幕没有任何间距。但是但是这样就是变得麻烦起来:在一个项目中这种提示框有可能会用到好几次,每一次内容和条目数都是有可能不同的,难道还要每次都新建布局吗?这也太麻烦了。于是我就自己封装了一个底部弹出对话框,可以添加任意多个Item,方便调用。请看最后一种方法:
1.2 自定义对话框实现
写的这个对话框的支持放任意多个Item,而无须重复的创建布局。只需要调用简单的方法即可达到想要的效果,贴出核心方法:
public class DialogUtil {
/**
* 此 dialog 效果从底部弹出,可以添加任意多个Item。
*
* @param context
* @param mWidth 需要设置的dialog的宽度
* @param listener 选择Item会调用此监听
* @param contents 任意多个Item选项内容(从最顶端到最低端)
* @return
*/
public static Dialog showItemSelectDialog(Context context
, int mWidth
, final OnItemSelectedListener listener
, final String... contents) {
final Dialog mDialog = new Dialog(context, R.style.Dialog_Transparent_Theme);
View rootView = LayoutInflater.from(context).inflate(R.layout.layout_choice, null);
LinearLayout contentsView = (LinearLayout) rootView.findViewById(R.id.dialogContent);
for (int i = 0; i < contents.length; i++) {
if (i == 0) {
View topView = LayoutInflater.from(context).inflate(R.layout.dialog_top_item, null);
TextView topText = (TextView) topView.findViewById(R.id.dialog_top);
topText.setText(contents[0]);
topText.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
if (listener != null)
listener.getSelectedItem(contents[0]);
}
});
contentsView.addView(topView);
} else if (i == contents.length - 1) {
View bottomView = LayoutInflater.from(context).inflate(R.layout.dialog_bottom_item, null);
TextView boottomTv = (TextView) bottomView.findViewById(R.id.dialog_bottom);
boottomTv.setText(contents[contents.length - 1]);
boottomTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
if (listener != null)
listener.getSelectedItem(contents[contents.length - 1]);
}
});
contentsView.addView(bottomView);
} else {
View centerView = LayoutInflater.from(context).inflate(R.layout.dialog_center_item, null);
TextView centTv = (TextView) centerView.findViewById(R.id.dialog_center_item);
final int finalI = i;
centTv.setText(contents[finalI]);
centTv.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
if (listener != null)
listener.getSelectedItem(contents[finalI]);
}
});
contentsView.addView(centerView);
}
}
rootView.findViewById(R.id.btn_cancel).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDialog.dismiss();
}
});
mDialog.setContentView(rootView);
mDialog.setCanceledOnTouchOutside(true);
Window window = mDialog.getWindow();
WindowManager.LayoutParams params = window.getAttributes();
params.gravity = Gravity.BOTTOM;
params.width = mWidth * 9 / 10;
window.setWindowAnimations(R.style.popupAnimation);
window.setAttributes(params);
mDialog.show();
return mDialog;
}
监听事件代码:
public interface OnItemSelectedListener {
public void getSelectedItem(String content);
}
布局layout_choice如下:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:gravity="bottom"
android:orientation="vertical">
<LinearLayout
android:id="@+id/dialogContent"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical" />
<Button
android:id="@+id/btn_cancel"
android:layout_width="fill_parent"
android:layout_height="45dp"
android:layout_gravity="center"
android:layout_marginBottom="5dp"
android:layout_marginTop="10dp"
android:background="@drawable/tv_shape"
android:gravity="center"
android:text="取消"
android:textColor="@drawable/text_select_selector"
android:textSize="16sp" />
</LinearLayout>
实现这个定义的dialog的原理很简单,加入传递了三条数据,会动态的将这三条数据加入到LineLayout,然后再显示dilog就可以了。接下来就是调用了。还是showDialog()这个方法:
private void showDialog() {
DialogUtil.showItemSelectDialog(MainActivity.this, mWidth
, onIllegalListener
, "色情/辱骂"
, "广告骚扰"
, "政治"
, "其他");//可填添加任意多个Item呦
}
private OnItemSelectedListener onIllegalListener = new OnItemSelectedListener() {
@Override
public void getSelectedItem(String content) {
Toast.makeText(MainActivity.this, content, Toast.LENGTH_SHORT).show();
}
};
效果图:
是不是很像ios的弹框效果,并且方法调用也很简单。从图中可以看到Item中只有最顶部和最底部是带有圆角的中间的部分是没有圆角的,所以我才使用了上 中 下 三个布局进行动态的加载,如何大家不需要这中效果根据想要的效果自己布置一下UI即可。