Android 高级UI组件(三)
阅读原文时间:2023年07月09日阅读:1

一、popupWindow

1.AlertDialog和PopupWindow最关键的区别是AlertDialog不能指定显示位置,只能默认显示在屏幕最中间(当然也可以通过设置WindowManager参数来改变位置)。而PopupWindow是可以指定显示位置的,更加灵活。

PopupWindow的位置按照有无偏移分,可以分为偏移和无偏移两种。

按照参照物的不同,可以分为相对于莫个控件(Anchor锚)和相对于父控件

showAsDropDown(View anchor):相对某个控件的位置(正左下方),无偏移

showSaDropDown(View anchor,int xoff ,int yoff)  :相对于空间的位置,有偏移

showAtLocation(View parent,int gravity, int x,int y):相对于父控件的位置(例如郑重眼Gravity.CENTER),可以设置偏移或无偏移

2.PopupWindow的相关函数

(1)构造函数

//方法一:
public PopupWindow (Context context)
//方法二:
public PopupWindow(View contentView)
//方法三:
public PopupWindow(View contentView, int width, int height)
//方法四:
public PopupWindow(View contentView, int width, int height, boolean focusable)

要生成一个PopupWindow最基本的三个条件是一定要设置的:View contentView,int width,int height,少一个就不可能弹出PopupWindow,所以如果使用方法一构造PopupWindow,完整的构造代码是这样的:

View contentView = LayoutInflater.from(MainActivity.this).inflate
(R.layout.popuplayout, null);
PopupWindwo popWnd = PopupWindow (context);
popWnd.setContentView(contentView);
popWnd.setWidth(ViewGroup.LayoutParams.WRAP_CONTENT);
popWnd.setHeight(ViewGroup.LayoutParams.WRAP_CONTENT);

(2)显示函数

//相对某个控件的位置(正左下方),无偏移
showAsDropDown(View anchor):
//相对某个控件的位置,有偏移;xoff表示x轴的偏移,正值表示向右,负值表示向左;yoff表示相对y轴的偏移,正值是向上,负值是向下;
showAsDropDown(View anchor, int xoff, int yoff):
//相对于父控件的位置(例如正中央Gravity.CENTER,下方Gravity.BOTTOM等),可以设置偏移或无偏移
showAtLocation(View parent, int gravity, int x, int y):

(3)其他函数

public void dismiss()
//另外几个函数,这里不讲其意义,下篇细讲
public void setFocusable(boolean focusable)
public void setTouchable(boolean touchable)
public void setOutsideTouchable(boolean touchable)
public void setBackgroundDrawable(Drawable background)

setOutside Touchable(boolean touchable)

这个函数的意义是指PopupWindow以外的区域是否可点击,即如果店家PopupWindow以外的区域,PopupWindow是否会消失

private void showPopupWindow() {
View contentView = LayoutInflater.from(MainActivity.this).inflate(
R.layout.popuplayout, null);
mPopWindow = new PopupWindow(contentView);
mPopWindow.setWidth(ViewGroup.LayoutParams.FILL_PARENT);
mPopWindow.setHeight(ViewGroup.LayoutParams.FILL_PARENT);

//外部是否可以点击  
mPopWindow.setBackgroundDrawable(new BitmapDrawable());  
mPopWindow.setOutsideTouchable(true);  

…………//各ITEM点击响应  

mPopWindow.showAsDropDown(mMenuTv);  

}

setBackgroundDrawable(Drawable background)

这个函数不知能设置背景,加上他之后,setOutsideTouchable()才会生效,而且,加上他后,PopupWindow才会对手机的返回按钮有响应,即点击手机返回按钮,可以关闭PopupWindow,如果不加将关闭PopupWindow所在的activity

    //获取屏幕尺寸  
    DisplayMetrics dm = new DisplayMetrics();  
    getWindowManager().getDefaultDisplay().getMetrics(dm);  
    int width = dm.widthPixels;  
    int height = dm.heightPixels;

二、Notification

是在常规界面之外展示的消息。当app让系统发送一个消息的时候,消息首先以图标的形式显示在通知栏。要查看消息的详情需要进入到通知抽屉(notificationdrawer)中查看。通知栏和通知抽屉都是系统层面控制的,你随时可以查看,不限制于app。

Notification的界面元素:

(1)普通视图

这种风格是notification drawer的标准显示方式。

(2)宽视图

指你的notification被展开的时候会显示更大的视图,这种风格是android4.1之后才有的新特性

创建一个Notification:

首先将Notification的一些UI信息及相关动作赋予NotificationCompat.Builder对象,然后通过NotificationCompat.Builder.build()来获得Notification对象自己,然后调用NotificationManager.notify()想系统转交这个通知。一个Notification对象需要包含以下内容:

小图标(setSmallIcon()获取)

标题(setContentTitle()获取)

详情文字(setContentText()获取)

其余内容是可选的

            //发送一个普通视图的通知  
            //API11之前创建通知的方式  

// Notification notification = new Notification();
//版本api11之后使用
// Notification.Builder builder = new Notification.Builder(MainActivity.this);
//v4支持包
NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);
//设置相关的属性
builder.setSmallIcon(R.mipmap.ic_launcher); //设置小图标
builder.setContentTitle("测试"); //设置通知标题
builder.setContentText("测试通知"); // 设置通知内容
builder.setAutoCancel(true); //设置自动清除
builder.setDefaults(Notification.DEFAULT_ALL);
builder.setNumber(10);
builder.setTicker("新消息");
// builder.setOngoing(true); //设置为常驻通知,不能被清除

            //设置单击的响应事件  
            //定义一个意图,当点击通知时要打开一个界面(Activity)  
            Intent intent = new Intent(MainActivity.this,SecondActivity.class);  
            //参数:上下文,请求编码,意图,创建PendingIntent的方式  

// PendingIntent.FLAG_CANCEL_CURRENT 取消当前的PI,创建新的
// PendingIntent.FLAG_NO_CREATE 如果有就是用,没有就不创建
// PendingIntent.FLAG_IMMUTABLE 只使用一次
// PendingIntent.FLAG_UPDATE_CURRENT 如果有就更新Intent
PendingIntent pi = PendingIntent.getActivity(MainActivity.this,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(pi);

            //创建一个通知对象  
            Notification notification = builder.build();  
            //获取系统的通知管理器 ,然后发送  
            NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION\_SERVICE);  
            nm.notify(N\_ID,notification);

public class SecondActivity extends AppCompatActivity {

@Override  
protected void onCreate(Bundle savedInstanceState) {  
    super.onCreate(savedInstanceState);  
    setContentView(R.layout.activity\_second);

    //打开界面取消指定ID的通知  
    NotificationManager nm = (NotificationManager) getSystemService(NOTIFICATION\_SERVICE);  
    nm.cancel(MainActivity.N\_ID);  
}  

}

            //发送一个大视图的通知  
            NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);  
            //设置相关的属性  
            builder.setSmallIcon(R.mipmap.ic\_launcher); //设置小图标  
            builder.setContentTitle("测试"); //设置通知标题  
            builder.setContentText("测试通知"); // 设置通知内容  
            //设置大视图样式  
            NotificationCompat.InboxStyle style = new NotificationCompat.InboxStyle();  
            style.setBigContentTitle("测试测试");  
            style.addLine("4444");  
            style.addLine("5555");  
            style.addLine("6666");  
            builder.setStyle(style);

            Notification n = builder.build();  
            NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION\_SERVICE);  
            nm.notify(N\_ID,n);

            //发送一个进度条的通知  
            NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);  
            //设置相关的属性  
            builder.setSmallIcon(R.mipmap.ic\_launcher); //设置小图标  
            builder.setContentTitle("测试"); //设置通知标题  
            builder.setContentText("测试通知"); // 设置通知内容  
            //设置进度条样式  
            builder.setProgress(100,5,false);  
            Notification n = builder.build();  
            NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION\_SERVICE);  
            nm.notify(N\_ID,n);

            //发送一个进度条的通知  
            final NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);  
            //设置相关的属性  
            builder.setSmallIcon(R.mipmap.ic\_launcher); //设置小图标  
            builder.setContentTitle("测试"); //设置通知标题  
            builder.setContentText("测试通知"); // 设置通知内容

            final NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION\_SERVICE);  
            nm.notify(N\_ID, builder.build());  
            //设置进度条样式

            //模拟更新的线程  
            new Thread(new Runnable() {  
                @Override  
                public void run() {  
                    for (int i = 0; i < 101; i++) {  
                        builder.setProgress(100, i, false);  
                        nm.notify(N\_ID, builder.build());  
                        try {  
                            Thread.sleep(500);  
                        } catch (InterruptedException e) {  
                            e.printStackTrace();  
                        }  
                    }

                    builder.setProgress(0, 0, false);  
                    builder.setContentText("更新完成");  
                    nm.notify(N\_ID, builder.build());  
                }  
            }).start();

        }  
    });

            //发送一个自定义视图的通知  
            NotificationCompat.Builder builder = new NotificationCompat.Builder(MainActivity.this);  
            builder.setSmallIcon(R.mipmap.ic\_launcher);  
            RemoteViews views = new RemoteViews(getPackageName(),R.layout.custom\_layout);  
            builder.setContent(views);  
            builder.setTicker("测试");  
            NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION\_SERVICE);  
            nm.notify(N\_ID1,builder.build());

三、 样式和主题

样式是给View或Window指定外观和格式的属性集合。样式能够指定如高、编剧、字体颜色、字体尺寸、背景颜色等属性。样式被定义在一个与布局XML文件分开的XML资源文件中。Android中的样式与Web设计中的层叠式列表类似,允许与内容分开设计。

样式(Style)

<style name="text\_style" parent="@style/AppTheme">  
    <item name="android:layout\_width">wrap\_content</item>  
    <item name="android:layout\_height">wrap\_content</item>  
    <item name="android:background">@color/colorAccent</item>  
</style>

元素的每个子元素在编译时都要被转换成一个应用程序资源对象,通过