• Android 高级UI组件(三)


    一、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>

    <resource>元素的每个子元素在编译时都要被转换成一个应用程序资源对象,通过<style>元素的name属性值来引用,即使用@style/text_style来引用,<style>元素中的parent属性是可选的,他指定了另一个样式的资源ID,当前样式可以季程程这个指定样式的属性,所以如果需要,可以覆写被继承的样式属性。把XML中定义的一个样式用作一个Activity或应用程序的主题与给一个View对象定义样式完全相同。如上面得样式能够被应用于一个View对象,也可用作一个Activity或应用程序的主题。

    主题(Themes)

    主题是应用于整个Activity或应用程序的样式,而不是一个独立的View对象,当一个样式被用做主题时,Activity或应用程序中的每个View对象都会使用它所支持的每个样式属性。例如,把相同的text_style样式用作一个Activity的主题,那么这个Activity内的所有文本的北京都是指定的北京。

    实现自定义组件

    配合XML属性资源文件的方式

    第一步:attrs.xml文件

    首先写出自定义组件的类文件,然后将这个类里需要外界传入值得属性定义成一个属性资源文件,在工程里的../res/values/目录下创建一个attrs.xml文件,具体写法如下:

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <declare-styleable name="MyView">
            <attr name="textColor" format="color" />
            <attr name="textSize" format="dimension" />
            <attr name="text" format="string" />
        </declare-styleable>
    </resources>

    attrs.xml解释如下

    attrs子元素:

    定义具体的属性,format表示这个属性的值的类型,类型有以下几种:

       reference:参考指定Theme中资源ID,这个类型意思就是你传的值可以使引用资源

      string:字符串,如果你想别人技能直接写值也可以用类似“@string/test”引用资源的方式,可以写成format="string|reference"

      color、boolean、dimension、float、integer、fraction(百分数)、

      enum:枚举

            <attr name="language">
                <enum name="China" value="1" />
                <enum name="English" value="2" />
            </attr>

    flag:位或运算

    declare-styleable子元素:

     定义一个styleable对象,每个styleable对象就是一组attr属性的集合,注意:这里的name属性并不是一定要和自定义类名相同,只是为了好区分对应类的属性而已

    第二步:在自定义类里引用attrs文件里定义的属性为自己的属性设置值。

        <com.gaochunfa.jiexidemo.MyView
            android:layout_width="match_parent"
            android:layout_height="50dp"
            app:textColor="#ff0000"
            app:textSize="35sp"
            app:text="ssss"/>
    package com.gaochunfa.jiexidemo;
    
    import android.content.Context;
    import android.content.res.TypedArray;
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.support.annotation.Nullable;
    import android.util.AttributeSet;
    import android.view.View;
    
    
    public class MyView extends View{
        private Paint mPaint;
        private int textColor;
        private float textSize;
        private String text;
        public MyView(Context context) {
            super(context);
        }
    
        public MyView(Context context, @Nullable AttributeSet attrs) {
            super(context, attrs);
            mPaint = new Paint();
            //这里去的declare-styleable集合
            TypedArray array = context.obtainStyledAttributes(attrs,R.styleable.MyView);
    
            //获取配置文件中的属性值,第二个参数是如果使用着没有配置该属性时所用的默认值
            textColor = array.getColor(R.styleable.MyView_textColor,0xFFFFFF);
            textSize = array.getDimension(R.styleable.MyView_textSize,24);
            text = array.getString(R.styleable.MyView_text);
    
        }
    
        public MyView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
        }
    
        //视图的绘制事件
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            mPaint.setColor(textColor);
            mPaint.setTextSize(textSize);
    
            canvas.drawText(text,20,20,mPaint);
        }
    }
  • 相关阅读:
    <img>的onClick属性的问题。
    Struts2的声明式异常处理
    beginner项目
    Visual Studio 2010 SP1将支持HTML5和CSS3 狼人:
    技巧:你未必知道的IE8九大功能 狼人:
    Mozilla公布Firefox 2011年开发计划 狼人:
    如何真正提高ASP.NET网站的性能 狼人:
    互联网之父Vint Cerf谈重组互联网 狼人:
    一位资深IT自由职业者的2010年回顾 狼人:
    PHP框架 Raxan 1.0 最终版发布 狼人:
  • 原文地址:https://www.cnblogs.com/chhom/p/4705017.html
Copyright © 2020-2023  润新知