精华内容
下载资源
问答
  • 本文实例讲述了Android编程Widget创建与使用方法。分享给大家供大家参考,具体如下: Android reference中有关于如何建立一个Widget的详细方法,这里简要说明一下,详情可以查看Android SDK中自带的reference。 要...
  • Flutter自定义Widget使用方法

    千次阅读 2019-03-27 13:37:54
    前面已经通过三个篇幅向大家介绍了Flutter原生提供的常用Widget和其使用方法,实际开发中我们会遇到一些特殊的需求或者规范一些常用的Widget作为基础UI组件来使用,这时我们就需要根据需求自定义Widget了。...

    前言

    前面已经通过三个篇幅向大家介绍了Flutter原生提供的常用Widget和其使用方法,实际开发中我们会遇到一些特殊的需求或者规范一些常用的Widget作为基础UI组件来使用,这时我们就需要根据需求自定义Widget了。Flutter中的自定义Widget和安卓、iOS原生平台类似,可以使用现有Widget进行组合,也可以自己根据需求来绘制,下面分别对两种自定义Widget的实现和使用方法做详细介绍。

    现有Widget组合自定义Widget

    现有Widget组合即是根据前面所介绍的基础Widget根据需求来组合成一个通用的Widget,这样在使用过程中避免设置过多的属性,且增强其复用性。
    比如,在实际开发中,我们经常会碰到一个Icon和一个标题组合而成的UI,且这个组合的区块可以处理点击事件,那么我们就可以根据现有Icon和Text widget组合成通用的类似UI组件。

    首先创建一个单独的dart文件来实现该自定义Widget,比如命名为custom_combined_widget.dart

    import 'package:flutter/material.dart';
    
    class CustomCombinedWidget extends StatefulWidget {
    
      final IconData iconData;
      final String title;
      final GestureTapCallback onTap;
    
      const CustomCombinedWidget({Key key, this.iconData, this.title, this.onTap}): super(key: key);
    
      @override
      State<StatefulWidget> createState() {
        // TODO: implement createState
        return CustomCombinedWidgetState();
      }
    
    }
    
    class CustomCombinedWidgetState extends State<CustomCombinedWidget> {
    
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return GestureDetector(
          onTap: this.widget.onTap,
          child: Column(
            children: <Widget>[
              Icon(this.widget.iconData, size: 45.0,),
              Text(this.widget.title == null ? "" : this.widget.title, style: TextStyle(fontSize: 14.0, color: Colors.black),),
            ],
          ),
        );
      }
    
    }
    

    上述代码中我们自定义了一个CustomCombinedWidget,这里面Icon的大小和标题的文本大小、颜色都是定好的,所以在使用时无法改变这些值,如果想在使用过程中改变这些值则需要从外部传值进来,比如标题的文本内容、icon和该Widget点击事件回调就是通过外部使用者传入的。

    以上自定义Widget的使用方法如下:

    //首先导入自定义Widget所在文件
    import 'package:demo_module/custom_combined_widget.dart';
    
    //在页面Widget中使用
    
    class HomePageState extends State<HomePage> {
      String tips = '这里是提示';
    
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return Scaffold(
          appBar: AppBar(
            title: Text('自定义组合Widget'),
          ),
          body: Container(
            child: buildCombinedWidget(),
          ),
        );
      }
    
      Widget buildCombinedWidget() {
        return Center(
          child: Column(
            children: <Widget>[
              Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  CustomCombinedWidget( //使用自定义Widget
                    iconData: Icons.home,
                    title: '首页',
                    onTap: () {
                      setState(() {
                        this.tips = '点击了首页';
                      });
                    },
                  ),
                  CustomCombinedWidget(
                    iconData: Icons.list,
                    title: '产品',
                    onTap: () {
                      setState(() {
                        this.tips = '点击了产品';
                      });
                    },
                  ),
                  CustomCombinedWidget(
                    iconData: Icons.more_horiz,
                    title: '更多',
                    onTap: () {
                      setState(() {
                        this.tips = '点击了更多';
                      });
                    },
                  ),
                ],
              ),
              Padding(
                padding: EdgeInsets.only(top: 50),
                child: Text(
                  this.tips,
                  style: TextStyle(fontSize: 20, color: Colors.blue),
                ),
              ),
            ],
          ),
        );
      }
    } 
    

    以上代码模拟器运行效果如下:

    通过CustomPainter绘制自定义Widget

    自定义绘制的Widget需要我们继承官方提供的CustomPainter抽象类,重写paint方法来实现,我们可以在paint方法中根据需求来绘制各种UI图形,最后根据该自定义CustomerPainter类创建一个painter对象作为系统提供的CustomPaint的painter属性值来实现自定义Widget。下面根据一个常用的柱状图的实现来学习CustomPainter的用法。

    首先我们创建一个自定义Widget对应的dart文件my_custom_painter.dart

    import 'dart:ui';
    import 'dart:ui' as ui show TextStyle;
    
    import 'package:flutter/material.dart';
    
    class BaseData {
      String name;
      int num;
      BaseData({this.name, this.num});
    }
    
    class MyCustomPainter extends CustomPainter {
      //绘制区域宽度
      final int width = 300;
      //绘制区域高度
      final int height = 350;
      //坐标原点
      final Offset origin = const Offset(50.0, 280.0);
      //纵坐标顶点
      final Offset vertexVer = const Offset(50.0, 20.0);
      //横坐标顶点
      final Offset vertexHor = const Offset(300.0, 280.0);
      //纵坐标刻度间隔
      final int scaleInterval = 1000;
      const MyCustomPainter(this.data);
      final List<BaseData> data;
    
      //根据文本内容和字体大小等构建一段文本
      Paragraph buildParagraph(String text, double textSize, double constWidth) {
        ParagraphBuilder builder = ParagraphBuilder(
          ParagraphStyle(
            textAlign: TextAlign.right,
            fontSize: textSize,
            fontWeight: FontWeight.normal,
          ),
        );
        builder.pushStyle(ui.TextStyle(color: Colors.black));
        builder.addText(text);
        ParagraphConstraints constraints = ParagraphConstraints(width: constWidth);
        return builder.build()..layout(constraints);
      }
    
      @override
      void paint(Canvas canvas, Size size) {
        // TODO: implement paint
        var paint = Paint()
          ..color = Colors.black
          ..strokeWidth = 2.0
          ..strokeCap = StrokeCap.square;
    
        //绘制纵坐标轴线
        canvas.drawLine(origin, vertexVer, paint);
        canvas.drawLine(
            vertexVer, Offset(vertexVer.dx - 5, vertexVer.dy + 10), paint);
        canvas.drawLine(
            vertexVer, Offset(vertexVer.dx + 5, vertexVer.dy + 10), paint);
        canvas.drawParagraph(buildParagraph('印刷量', 14, origin.dx-5),
            Offset(0, vertexVer.dy-8));
    
        //绘制横坐标轴线
        canvas.drawLine(origin, vertexHor, paint);
        canvas.drawLine(
            vertexHor, Offset(vertexHor.dx - 10, vertexHor.dy - 5), paint);
        canvas.drawLine(
            vertexHor, Offset(vertexHor.dx - 10, vertexHor.dy + 5), paint);
        canvas.drawParagraph(buildParagraph('书籍名', 14, origin.dx-5),
            Offset(vertexHor.dx, origin.dy+8));
    
        //绘制纵坐标刻度
        //实际最大值
        double realMaxY = origin.dy - vertexVer.dy - 20;
        //刻度间隔实际值
        double scaleInte = realMaxY / 5;
        for (int i = 0; i < 5; i++) {
          canvas.drawLine(Offset(origin.dx, origin.dy - (i + 1) * scaleInte),
              Offset(origin.dx + 5, origin.dy - (i + 1) * scaleInte), paint);
          canvas.drawParagraph(buildParagraph(((i+1)*scaleInterval).toString(), 12, origin.dx-5),
              Offset(0, origin.dy - (i + 1) * scaleInte - 8.0));
        }
    
        if (data == null || data.length == 0) {
          return;
        }
        //计算纵坐标上的刻度
        int size = data.length;
        //柱状图间隔值
        double horiScalInte = (vertexHor.dx - origin.dx - 20) / size;
        //柱状图宽
        double chartWidth = 5;
        for (int i = 0; i < size; i++) {
          BaseData curData = data[i];
          double valueY = curData.num * scaleInte / scaleInterval;
          canvas.drawRect(Rect.fromLTWH(origin.dx + (i+1)*horiScalInte, origin.dy - valueY, chartWidth, valueY), paint);
          canvas.drawParagraph(buildParagraph(curData.name, 12, origin.dx-5),
              Offset(origin.dx + (i+1) * horiScalInte - 25, origin.dy+8));
        }
      }
    
      @override
      bool shouldRepaint(MyCustomPainter oldDelegate) {
        // TODO: implement shouldRepaint
        return oldDelegate.data != data;
      }
    }
    

    代码实现中表示我们将传入一个包含柱状图数据的data对象,paint方法会根据data数据集合来在一个坐标系中绘制柱状图。在具体的Widget页面应用方法如下:

    class HomePageState extends State<HomePage> {
      List<BaseData> data = List();
    
      @override
      Widget build(BuildContext context) {
        // TODO: implement build
        return Scaffold(
          appBar: AppBar(
            title: Text('自定义绘制Widget'),
          ),
          body: Container(
            child: buildDemoPaintWidget(),
          ),
        );
      }
    
      Widget buildDemoPaintWidget() {
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Container(
              height: 350,
              child: buildPaintWidget(),
            ),
            Container(
              child: Row(
                mainAxisAlignment: MainAxisAlignment.spaceAround,
                children: <Widget>[
                  MaterialButton(
                    onPressed: () {
                      BaseData book1 = BaseData(name: '书籍A', num: 5000);
                      BaseData book2 = BaseData(name: '书籍B', num: 2000);
                      BaseData book3 = BaseData(name: '书籍C', num: 3000);
                      List<BaseData> dataList = List();
                      dataList.add(book1);
                      dataList.add(book2);
                      dataList.add(book3);
                      setState(() {
                        this.data = dataList;
                      });
                    },
                    child: Text('三本书'),
                  ),
                  MaterialButton(
                    onPressed: () {
                      BaseData book4 = BaseData(name: '书籍D', num: 4500);
                      setState(() {
                        this.data.add(book4);
                      });
                    },
                    child: Text('四本书'),
                  ),
                  MaterialButton(
                    onPressed: () {
                      BaseData book5 = BaseData(name: '书籍E', num: 2500);
                      setState(() {
                        this.data.add(book5);
                      });
                    },
                    child: Text('五本书'),
                  ),
                ],
              ),
            ),
          ],
        );
      }
    
      //构建自定义绘制的Widget
      Widget buildPaintWidget() {
        return CustomPaint(
          painter: MyCustomPainter(data),
        );
      }
    }
    

    以上代码,初始时data数据为空,通过点击三个按钮来改变data的值从而重新绘制柱状图,具体效果如下:

    总结

    本篇我们对自定义Widget进行了详细介绍,实际开发中无非就是使用者两种方式来实现五花八门的UI需求,其中绘制自定义Widget在图表较多的APP中会经常使用,后续我们会专门用一篇文章来介绍各种图形的绘制方法,敬请期待!

    说明:

    文章转载自对应的“Flutter编程指南”微信公众号,更多Flutter相关技术文章打开微信扫描二维码关注微信公众号获取。

    展开全文
  • UE4使用widget创建UI界面播放视频

    万次阅读 2016-07-12 16:14:55
    5.打开关卡蓝图,Blueprints/Open Level Blueprint,创建一个Widget并添加到View port上,然后设置鼠标可见 6.点击Play运行,点击屏幕右下角的按钮就可以实现视频的播放/暂停 7.声音播放,建议在...

    我的目的非常简单,点击按钮,播放或暂停场景中的视频


    1.准备了一个mp4视频资源,为视频资源创建了一个Media Texture,在Media Player中选择导入进来的视频资源,再为Media Textue创建一个Material


    2.再选择User Interface/Widget Blueprint创建UI,命名MyUI


    3.双击MyUI,创建一个图片,我希望全铺于屏幕,于是我在Anchors里选择了全铺,然后再Appearance/Image选择开始的创建的Media Material


    4.再在屏幕的右下角创建一个按钮,并在按钮上添加一个文本Play/Pause。双击按钮的OnClicked事件,并为视频创建一个Media Player变量,判断当时视频是否正在播放,并选择播放或暂停


    5.打开关卡蓝图,Blueprints/Open Level Blueprint,创建一个Widget并添加到View port上,然后设置鼠标可见


    6.点击Play运行,点击屏幕右下角的按钮就可以实现视频的播放/暂停


    7.声音播放,建议在外面将视频的声音分离出来做一个wav声音文件,再导入ue4,在播放视频的时候同步播放声音

    8.视频打包后不能播放,需要将视频文件放在Content/Movies文件夹下,然后MediaPlayer再去选择那个视频文件,你就会发现他的路径变为了相对路径后,打包出来后,Content文件中也会将Movies文件夹和视频文件打包出来,这里就能正常播放了

    展开全文
  • 本文实例讲述了Thinkphp 框架扩展之Widget扩展实现方法。分享给大家供大家参考,具体如下: Widget扩展 Widget扩展一般用于页面组件的扩展。 举个例子,我们在页面中实现一个分类显示的Widget,首先我们要定义一个...
  • 这是一个android widget的简单使用示例,对于android初学者有较大的借鉴价值。
  • Android平台以WebView和Widget方式集成HTML5+SDK方法。 包含两个两个基础环境项目demo: 1、Android平台以WebView方式集成HTML5+SDK方法。 2、Android平台以Widget方式集成HTML5+SDK方法
  • 本文实例讲述了ThinkPHP中Widget扩展的两种写法及调用方法。分享给大家供大家参考,具体如下: Widget扩展一般用于页面组件的扩展,在页面根据需要输出不同的内容,下面介绍一下ThinkPHP中Widget的两种写法及调用 ...
  • Widget的简单使用详解

    千次阅读 2016-11-09 15:27:16
    1、创建一个类继承AppWidgetProvider 并重写相应方法 默认实现了onReceive 方法。 2、在清单文件进行注册。 3、在res目录下新建xml文件夹 配置widget相关信息。 4、创建widget展示布局。 5、创建widge...

    Widget是安卓的一个桌面小工具组件—窗口小部件,是微型应用程序视图,可以嵌入到其他应用程序(如主屏幕)和接收定期更新。

    使用步骤:

    1、创建一个类继承 AppWidgetProvider  并重写相应方法 默认实现了onReceive 方法。

    2、在清单文件进行注册。

    3、在res目录下新建xml文件夹 配置widget相关信息。

    4、创建widget展示布局。

    5、创建widget的配置文件(可选)。

    6、更新数据。

     

    大概就是上述的一些步骤。如果在添加的widget之前需要进行一些配置 则需要实现第5步。

     

    第一步:创建类继承AppWidgetProvider   

     

    public class MyWidget extends AppWidgetProvider {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            super.onReceive(context, intent);
        }
    
        /**
         * 第一个widget被添加调用
         * @param context
         */
        @Override
        public void onEnabled(Context context) {
            super.onEnabled(context);
    
            context.startService(new Intent(context, WidgetService.class));
    
        }
    
        /**
         * widget被添加 || 更新时调用
         * @param context
         */
        @Override
        public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
            super.onUpdate(context, appWidgetManager, appWidgetIds);
            context.startService(new Intent(context, WidgetService.class));
        }
    
        /**
         * 最后一个widget被删除时调用
         * @param context
         */
        @Override
        public void onDisabled(Context context) {
            super.onDisabled(context);
            context.stopService(new Intent(context, WidgetService.class));
        }
    
        /**
         * widget被删除时调用
         * @param context
         * @param appWidgetIds
         */
        @Override
        public void onDeleted(Context context, int[] appWidgetIds) {
            super.onDeleted(context, appWidgetIds);
        }
    
    }

     

     

    2、清单文件注册

     

            <receiver android:name=".MyWidget">
    
                <intent-filter>
                    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                </intent-filter>
    
                <meta-data android:name="android.appwidget.provider"
                    android:resource="@xml/example_appwidget_info" /> //widget的配置信息文件
    
            </receiver>


    3、创建配置信息 目录 res/xml/xxx.xml

     

     

    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:minWidth="40dp" //widget的最小宽度
        android:minHeight="40dp"//widget的最小高度
        android:updatePeriodMillis="86400000"//更新的频率  google规定最小时间为30分钟
        android:previewImage="@drawable/preview" //widget的预览图 即在添加是看到的图片 一般为logo
        android:initialLayout="@layout/example_appwidget" // widget的布局文件
        android:configure="com.example.android.ExampleAppWidgetConfigure" //widget配置activity
        android:resizeMode="horizontal|vertical" //widget是否可以水平 竖直缩放 
        android:widgetCategory="home_screen|keyguard"> //widget可以被添加主屏幕或者锁屏
    </appwidget-provider>

     

    以上这些信息并不是必须  是可以选择的。updatePeriodMillis的时间最小限定在了30分钟,对于有些app来说可能时间太久了,那么我们可以将updatePeriodMillis的时间设置为0,然后通过自定义service去更新widget。

    Demo中的配置信息如下:

     

    <appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
        android:initialLayout="@layout/example_appwidget"
        android:minHeight="80dp"
        android:minWidth="250dp"
        android:previewImage="@mipmap/ic_launcher"
        android:updatePeriodMillis="0"
        android:widgetCategory="home_screen|keyguard">
    
    </appwidget-provider>


    4、创建widget的展示布局,这个就根据设计,自己去码布局了。

     

    Demo中布局文件内容如下:

     

    <?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="horizontal">
    
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@mipmap/bg_icon"
            android:gravity="center_vertical"
            android:orientation="horizontal"
            android:paddingLeft="30dp"
            android:paddingRight="30dp">
    
            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="1"
                android:orientation="vertical">
    
                <TextView
                    android:id="@+id/tv_date"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="16sp" />
    
                <TextView
                    android:id="@+id/tv_money"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textColor="#000"
                    android:textSize="16sp" />
    
            </LinearLayout>
    
            <Button
                android:id="@+id/btn_refound"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:background="@null"
                android:gravity="right|center"
                android:text="点击" 
                android:textColor="#000"
                android:textSize="16sp" />
    
        </LinearLayout>
    
    </LinearLayout>


    就是简单的来个TextView来显示文案。

     

    Demo中不需要对在添加widget进行配置所以不需要第5步。

    这样简单的widget使用就完成了。

     

    最后就是更新widget数据了,为了满足自定义时间可以对widget进行更新,我们采取使用service的方式进行。同样,创建类继承Service。

    Demo中的service代码如下:

     

    public class WidgetService extends Service {
    
        private Timer mTimer;
        private SimpleDateFormat mFormat;
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
    
            mFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    
            mTimer = new Timer();
            mTimer.schedule(new TimerTask() {
                @Override
                public void run() {
                    updateWidget(WidgetService.this);
                }
            }, 0, 5000); 
    
        }
    
        private void updateWidget(Context context) {
    
            RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.example_appwidget);
            long millis = System.currentTimeMillis();
            String format = mFormat.format(new Date(millis));
            remoteViews.setTextViewText(R.id.tv_date, "日  期:" + format);
            remoteViews.setTextViewText(R.id.tv_money, "毫秒值:" + millis);
    
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
            remoteViews.setOnClickPendingIntent(R.id.btn_refound, pendingIntent);
    
            ComponentName componentName = new ComponentName(this, MyWidget.class);
            AppWidgetManager.getInstance(this).updateAppWidget(componentName, remoteViews);
    
        }
    
    
        @Override
        public void onDestroy() {
            super.onDestroy();
    
            mTimer.cancel();
            mTimer = null;
    	stopForeground(true);
    
        }
        
    }	stopForeground(true);
    
        }
        
    }


    在service的oncreate方法中创建一个Timer定时器,这个定时器每个5秒钟就会执行updateWidget方法,在updateWidget方法里面实现了具体的更新widget的逻辑。通过RemoteViews去加载布局文件 在通过setTextViewText等方法实现对控件的控制。

     

    这个地方使用了PendingIntent  ,PendingIntent 其实和Intent效果是一样的,都是充当信使的作用,但是区别就是 PendingIntent 定义的事件是提前预知的,就是不知道事件什么时候发生,但是只要发生了,就要执行PendingIntent 定义的逻辑。

    最后通过AppWidgetManager.getInstance(this).updateAppWidget(componentName, remoteViews);去更新widget组件的信息。

     

    这样看,大概一个widget的功能就已经完成了,创建了,数据也可以更新了,但是有一个问题就是,我们使用的是service去更新widget,那么我们创建的service是一个后台进程,后台进程的优先级比较低,当手机内存不足的时候 就会优先kill掉这些进程。这个时候,widget在桌面上就不会得到更新了。那么怎么解决呢? 

    这里的思路是提升service进程的优先级,将其提升为前台进程,这样就可以最大程度的保证service不会被系统kill掉了。

    在service的oncreate方法中创建一个通知,这样就将此service由后台进程变为前台进程了。代码如下:

     

    @TargetApi(Build.VERSION_CODES.JELLY_BEAN)
        private void improvePriority() {
            PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new Intent(this, WidgetService.class), 0);
            Notification notification = new Notification.Builder(this)
                    .setContentTitle("Foreground Service")
                    .setContentText("Foreground Service Started.")
                    .setSmallIcon(R.mipmap.ic_launcher).build();
            notification.contentIntent = contentIntent;
            startForeground(1, notification); 
        }


    在oncreate方法中调用此方法即可。 Demo源码中startForeground(1, notification);  第一个参数写的是0  这个是不行的  谷歌文档提示 must not be 0 , 写0之后就not working了。但是这样,当SDK<18时,通知栏不会显示该通知,当SDK>=18时,通知栏就会显示该通知 了。关于这个问题请移步到消除前台进程通知 本人未做实践,不过的确是一种思路。

     

     

    这样基本就完成了widget的创建了。这个时候可能又会问了,万一此时service还是被kill了怎么办呢?

    一种方式是我们重写service的onStartCommand方法 并返回START_STICKY,这样如果是系统自动将service kill了,在一段时间后 在内存比较充裕的心情下 系统会自动启动这个service的。

     

        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return START_STICKY;
        }

     

     

     

     

     

    另外一种方式就是通过广播来监听此service,安卓系统提供了一个时间改变的广播接受者— ACTION_TIME_TICK 每隔一分钟 就会发送一个广播。由于此广播是系统级别的广播,所以不可以通过清单文件配置监听,只能通过代码动态的创建监听。

    创建一个类继承BroadcastReceiver 并且重写onReceive 方法 ,这样每隔一分钟 onReceive方法就会执行一次,在onReceive方法中判断service是否已经在运行,如果没有在运行就去开启service,否则就上面操作都不需要做。

     

    public class WidgetBroadcastReceiver extends BroadcastReceiver {
    
        public static final String SERVICE_NAME = "com.ppdai.widgetdemo.WidgetService";
    
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (action.equals(Intent.ACTION_TIME_TICK)) {
                if (!isServiceWork(context, SERVICE_NAME)) {
                    context.startService(new Intent(context, WidgetService.class));
                }
            }
        }
    
        /**
         * 判断service是否在运行
         * @param mContext
         * @param serviceName
         * @return
         */
        public boolean isServiceWork(Context mContext, String serviceName) {
            boolean isWork = false;
            ActivityManager myAM = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
            List<ActivityManager.RunningServiceInfo> myList = myAM.getRunningServices(100);
            if (myList.size() <= 0) {
                return false;
            }
            for (int i = 0; i < myList.size(); i++) {
                String mName = myList.get(i).service.getClassName().toString();
                if (mName.equals(serviceName)) {
                    isWork = true;
                    break;
                }
            }
            return isWork;
        }
    }


    然后在需要的地方 动态的注册此广播:

     

     

            WidgetBroadcastReceiver mReceiver = new WidgetBroadcastReceiver();
            IntentFilter filter = new IntentFilter();
            filter.addAction(Intent.ACTION_TIME_TICK);
            registerReceiver(mReceiver, filter);


    这样 整个widget的功能就基本完善了。如有不足 请指正! 谢谢

     

    我是源码

    扫描下方二维码关注公众号,及时获取文章推送

     

     

    展开全文
  • [UE4]Widget一些用法

    千次阅读 2018-10-11 14:33:01
    ChildSlot  [  SNew(SVerticalBox)  //-----------------------------//  + SVerticalBox::Slot()  [  SNew(SHorizontalBox)  + SHorizontalBox::Slot()  ...

    ChildSlot
        [
            SNew(SVerticalBox)
            //-----------------------------//
            + SVerticalBox::Slot()
            [
                SNew(SHorizontalBox)
                + SHorizontalBox::Slot()
                [
                    SNew(SBox)
                    .HeightOverride(20.0f)
                    .WidthOverride(60.0f)
                    [
                        SNew(STextBlock)
                        .Text(LOCTEXT("TextDefaultValue0", "test:"))
                    ]
                ]

                + SHorizontalBox::Slot()
                [
                    SNew(SBox)
                    .HeightOverride(30.0f)
                    .WidthOverride(150.0f)
                    [
                        SAssignNew(SplitMapBtn, SButton)
                        .OnClicked(this, &SEventTest::OnButtonClicked)
                        .Text(LOCTEXT("Split", "SplitMap"))
                    ]
                    
                ]

                + SHorizontalBox::Slot()
                    [
                        SNew(SBox)
                        .AutoWidth()
                    [
                        SNew(SCheckBox)
                    .OnCheckStateChanged(this, &SEventTest::OnCheckBoxChanged)
                    .ToolTipText(FText::FromString(TEXT("Sprays the blueprints when checked and mouse down.")))
                    .IsChecked(this, &SEventTest::OnCheckBoxActive)

                    ]

                    ]

            ]

    ];

     

     


    //
    void SEventTest::OnCheckBoxChanged(ECheckBoxState NewState)
    {

    }

    FReply SEventTest::OnButtonClicked()
    {
        return FReply::Handled();
    }

     


        ECheckBoxState OnCheckBoxActive() const
        {
            return ECheckBoxState::Checked;
        }

     

     

     

    參考

    https://forums.unrealengine.com/development-discussion/c-gameplay-programming/29278-how-to-make-a-dockable-tab-in-a-plugin-also-hamad-s-plugin-corrected-unreal-4-7-0

    展开全文
  • 中山大学数据科学与计算机学院本科生实验报告 ...在第七周任务的基础上,实现静态广播、动态广播两种改变widget内容的方法。 要求 widget初始情况如下: 点击widget可以启动应用,并在widget随机...
  • 文章目录1.Flutter 自定义 Widget 的方式2 Widget 的继承实现自定义3.Widget 的组合实现自定义4.CustomPaint 绘制 Widget5.Flutter方法的封装 在使用 Flutter 开发的过程中,有时候现有的 Widget 不能满足需求,所以...
  • widget和子widget进行通讯的难点就是不能获取到父widget的对象,因此要借助其他的方法,比如借助InheritedWidget或是通过Notification 在主页面 在子widget中 很难理解的就是key的使用,这样统一的使用一个key...
  • 本文实例讲述了CI框架整合widget(页面格局)的方法。分享给大家供大家参考,具体如下: 在WEB开发过程中,我们免不了要...* 如果$name存在则调用widget类及widget方法 *@param string $name */ protected function wid
  • 主要介绍了yii2框架中使用下拉菜单的自动搜索yii-widget-select2的方法,介绍了yii-widget-select2的下载,安装及具体使用技巧,需要的朋友可以参考下
  • 最近需要用到Tree Widget树形控件,现将自己的一些理解记录下来。 Tree Widget在项目控件组(Item Widgets)里面可以找到。这种控件其实有时还是很有用处的,我主要利用的是带有复选框的树形控件。结果如图所示; ...
  • iOS-OC-widget使用教程

    千次阅读 2016-09-29 13:13:48
    widget从iOS8发布到现在已经很久了,刚出来的时候我也了解过,但是一直没有用,最近我的一个APP要用到,在这里我就整理一下,详细说明一下,希望大家喜欢! 说明 1.app extension extension是iOS8新开放的一种对几个...
  • 在flutter里面,我们可以定制自己的widget,那么,问题来了,我是如何定制自己的widget的呢?如何轻松访问自定义部件中的属性以及方法。 效果图 接下来,我将会以自定义button组件进行讲解。 页面分析,在这个页面...
  • QT5.7中的opengl使用方法

    千次阅读 多人点赞 2017-01-10 17:54:39
    本文目的是记录一下自己搜索相关机制的结果qt5.7实现opengl机制主要包含两类一种是提供QtGui实现,这个库主要是通过QWindow结合qt封装的opengl库进行实现,官方有案例,一个旋转的三角形,使用opengl es2.0,而且这...
  • 使用AndroidStudio开发环境实现单击Widget打开Activity
  • Widget小部件的使用方法介绍 TP5

    千次阅读 2018-02-24 10:43:54
    现在Widget叫分层控制器了,很官方了,熟悉YII框架的朋友都习惯叫它小部件,我也是一直叫它小部件,它真的是非常好用的一个东西,今天就简单的分享一下它的使用方法吧。Thinkphp3.2版本使用方法从这进入:...
  • 一个帮助开发者加深了解 Flutter 的项目,提供了 N 多个常用 Widget 和自定义 Widget使用及实现方法,涵盖了系统 Widget 、布局容器、动画、高阶功能、自定义 Widget 等内容,即包含如下几个大分类: widget ...
  • Flutter常用Widget详解(三)

    千次阅读 2019-03-27 13:37:10
    前面两篇文章给大家介绍了Widget中对应原生开发中的一些常用基础控件,Text、TextField、Button、Dialog、Picker等,本篇我们将和大家一起学习ListView、GridView等列表网格布局控件和其他常用的用于布局的Widget,...
  • 1.在主界面点击按钮的时候,在按钮中的onTap()方法中控制父widget的...2.创建自定义的InheritedWidget类,主要是of()方法,在子widget中需要这个方法获取父widget的对象。 3.在这里用InkWell实现水波纹的效果,但...
  • 专栏:Python基础教程目录 专栏:使用PyQt开发图形界面Python应用 专栏:PyQt入门学习 老猿Python博文目录 QDockWidget对象由一个标题栏和内容区域组成。...方法widget和setWidget就是用于访问QDockWidget的内...
  • 此外,框架还将向处理前端输出的函数或方法传递两个附加参数: $ form_fields和$ widget_id 。 在上查看有关它们的更多详细信息。 特征 Widget Bulder完全基于 。 窗口小部件admin是从自动创建的。 前端渲染功能...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 223,407
精华内容 89,362
关键字:

widget使用方法