addview_addview指定位置 - CSDN
精华内容
参与话题
  • android addView的使用

    万次阅读 2018-03-22 08:26:52
    addView动态的添加控件到界面上。 这个其实很简单,之前我使用时发生了一些问题,所以在网上查找了资料,最终解决了问题。这里记录一下。 一、说明 添加视图文件的时候有两种方式:1、通过在xml文件定义...


    今天,简单讲讲android里如何使用
    

    addView动态的添加控件到界面上。


    这个其实很简单,之前我使用时发生了一些问题,所以在网上查找了资料,最终解决了问题。这里记录一下。


    一、说明

    添加视图文件的时候有两种方式:1、通过在xml文件定义layout;2、java代码编写

    这里只介绍代码添加视图文件。


     在项目开发中,我们经常需要进行动态添加组件,其中可添加的部分有两项:布局和组件

     其中:

                添加的布局主要有RelativeLayout型(相对布局)的和LinearLayout(线性布局)

                添加的组件主要有文本显示框,编辑框,按钮等组件。

    首先我们创建一个新的项目,删除MainActivity.class中没有用的代码,仅留下protected void onCreate(Bundle savedInstanceState)函数

    往布局文件中添加一个新的组件:


     1. addView方法简介

           在Android中,addView(ViewGroup view, index)在指定的index处添加一个view。addView是继承viewGroup的方法,

    void android.view.ViewGroup.addView(View child);
    void android.view.ViewGroup.addView(View child, LayoutParams params);
    void android.view.ViewGroup.addView(View child,int index, LayoutParams params);


    其中需要注意的是 index ,在linearlayout中使用addView的时候,如果linearlayout方向是vertical 垂直, index代表添加的child的view在linearlayout的行数,index是0,表示添加的child在linearlayout顶部,-1为底部,可以利用排版View的 addView 函数,将动态产生的View 组件加入到排版View 中。

    2、示例:

          (1)首先我们往布局文件中添加一个组件,比如一个文本,两个按钮,此时我们需要在布局文件中添加一个布局项<LinearLayout>,定义其id为linearlay_1,用于在添加组件时识别,布局文件代码如下所示:

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="动态添加组件示例" 
            android:id="@+id/textview"/>
        <LinearLayout 
            android:layout_below="@+id/textview"
            android:id="@+id/linearlay_1"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:orientation="vertical"
            ></LinearLayout>


     然后我们在Activity类里边进行添加组件,代码如下所示:

       /**  

          * 代码中,布局的位置,是垂直顺序排列的因为界面代码Linerlayout的orientation设置的是
          * vertical的,但是为了美观,需要设置添加的View的位置和样式。在添加View的时候分
          * 为两类来介绍,一种是布局(例如:Linearlayout和RelativeLayout等,对于RelativeLayout属于相对布局)

          *注意,对于LinearLayout布局来说,设置横向还是纵向是必须的!否则就看不到效果了。

      */

    public class MainActivity extends Activity {
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		
    		//绑定activity_main布局文件中的布局项,其中R.id.lenearlay_1为布局文件中设置的id
    		LinearLayout linear=(LinearLayout) findViewById(R.id.linearlay_1);
    		//添加文本,this代表当前项目
    		TextView tv=new TextView(this);
    		tv.setText("示例文本框");
    		tv.setId(1);//设置ID,可有可无,也可以在R文件中添加字符串,然后在这里使用引用的方式使用
    		linear.addView(tv);
    		
    	     // 将Button 加入到LinearLayout 中
    	      Button b1 = new Button(this);
    	      b1.setText("取消");
    	      linear.addView(b1);
    	 
    	      // 将Button 2 加入到LinearLayout 中
    	      Button b2 = new Button(this);
    	      b2.setText("确定");
    	      linear. addView ( b2 );
    	 
    	      // 从LinearLayout 中移除Button 1
    	     // linear. removeView ( b1 );
    
    	       
    	}
    
    }

    效果如下图所示:


    图 1 动态添加组件-LinearLayout


    (2) 动态添加布局:

    /* 下面的例子将介绍如何动态添加布局,基本内容和上面的代码一致,主要注重如何控制添加的布局的位置
    * 在控制布局的位置的时候使用LayoutParam类来实现。
     * 注意:控制位置和样式的时候,布局和控件使用的方法是一样的。

    */这次只是在MainActivity中进行操作,不涉及布局文件(.xml),其代码如下所示:

    public class MainActivity extends Activity {
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    	      //
    	      //创建一个相对布局relative
    		RelativeLayout relative = new RelativeLayout(this);
    		relative.setBackgroundColor(Color.YELLOW);
    		// 将Button1 加入到RelativeLayout 中
    	      Button btn_r1 = new Button(this);
    	      btn_r1.setText("取消");//设置显示的字符
    	      btn_r1.setId(24);
    	      relative.addView(btn_r1);
    	      
    	      // 将Button2 加入到RelativeLayout 中
    	      Button btn_r2 = new Button(this);
    	      btn_r2.setText("确定");//设置显示的字符	    
    	      btn_r2.setId(25);
    	      relative.addView(btn_r2); 
    	                                                                                                                                                                  // 设置RelativeLayout布局的宽高 
    	        RelativeLayout.LayoutParams lp=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
    	        lp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, RelativeLayout.TRUE); 
    	        lp.addRule(RelativeLayout.ALIGN_PARENT_TOP, RelativeLayout.TRUE); 
    	        btn_r1.setLayoutParams(lp);   设置按钮的布局属性 
    	        lp=new RelativeLayout.LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);
    	        lp.addRule(RelativeLayout.RIGHT_OF, btn_r1.getId()); 
    	        btn_r2.setLayoutParams(lp);   设置按钮的布局属性 
    	        setContentView(relative);
    	}
    
    }
    


    效果如下所示:


    图 2 动态添加布局-RelativeLayout



    这里简单讲讲,如果是使用void android.view.ViewGroup.addView(View child,int index, LayoutParams params);  时,需要注意index的值需要从0开始,每次顺序增加1,否则会抛出异常。自己查看了addView的源码,发现addView里面每次添加控件时有一个包含控件的计数的变量,如果addView(ViewGroup view, index)的index与计数变量不同,就会抛出异常。


    android addView的使用就讲完了。


    就这么简单。

    展开全文
  • 浮窗中addView()不显示 分析思路

    千次阅读 2018-08-23 20:07:35
    看得到的真相往往可能是骗人的,但是代码不会. 如果程序中出现了”灵异”事件,一定是问题没有分析到位,亦或是分析问题的方向出错 最近在项目中,我需要在一个独立进程的不死服务中打开一个浮窗,但是浮窗不显示....

    看得到的真相往往可能是骗人的,但是代码不会. 如果程序中出现了”灵异”事件,一定是问题没有分析到位,亦或是分析问题的方向出错

    最近在项目中,我需要在一个独立进程的不死服务中打开一个浮窗,但是浮窗不显示.但是在Activity中可以打开浮窗.这是问题的表现,其中不同点是创建WindowManager的Context不同,使用Activity的Context可以,使用Service和Application的Context都不可以.通过Log日志可以发现,addView()方法是执行了,但是View并没有显示出来.接下来,我就进行了各方位的尝试

    一.分析中…

    1.是否存在浮窗创建之后又被移除了?

    屏蔽浮窗移除代码浮窗还是没有显示

    2.参考网上提供方案把浮窗的创建过程放到服务中,即重启一个服务用于开启浮窗

    代码如下,浮窗还是没有出现

    class FloatWindowService : Service() {
    
        companion object {
            private const val TAG = "DaemonService"
            const val NOTICE_ID = 100
    
    
            fun openFloatWindowService(mContext: Context) {
                val intent = Intent(mContext, FloatWindowService::class.java)
                intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK
                mContext.startService(intent)
    
            }
        }
    
        private val TAG = "FloatWindowManager"
        /**
         * 小悬浮窗View的实例
         */
        @SuppressLint("StaticFieldLeak")
        private var smallWindow: FloatWindowSmallView? = null
    
        /**
         * 小悬浮窗View的参数
         */
        private var smallWindowParams: WindowManager.LayoutParams? = null
    
        /**
         * 用于控制在屏幕上添加或移除悬浮窗
         */
        private var mWindowManager: WindowManager? = null
    
        /**
         * 是否有悬浮窗(包括小悬浮窗和大悬浮窗)显示在屏幕上。
         *
         * @return 有悬浮窗显示在桌面上返回true,没有的话返回false。
         */
        var isWindowShowing: Boolean = false
    
    
        override fun onCreate() {
            super.onCreate()
            smallWindow = FloatWindowSmallView(applicationContext)
            smallWindowParams = WindowManager.LayoutParams()
            mWindowManager = getWindowManager(applicationContext)
            setSmallWindowParams(mWindowManager!!, smallWindowParams!!)
    
        }
    
        private fun setSmallWindowParams(windowManager: WindowManager,smallWindowParams: WindowManager.LayoutParams) {
            val outMetrics = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(outMetrics)
            val screenWidth = outMetrics.widthPixels
            val screenHeight = outMetrics.heightPixels
                smallWindowParams!!.type = WindowManager.LayoutParams.TYPE_PHONE
    //        smallWindowParams!!.format = PixelFormat.RGBA_8888
            smallWindowParams.format = PixelFormat.TRANSPARENT
            smallWindowParams!!.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            smallWindowParams!!.gravity = Gravity.LEFT or Gravity.TOP
            smallWindowParams!!.width = 600
            smallWindowParams!!.height = 600
            smallWindowParams!!.x = 0
            smallWindowParams!!.y = 0
        }
    
        override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
            smallWindow!!.setParams(smallWindowParams!!)
            mWindowManager!!.addView(smallWindow, smallWindowParams)
            return super.onStartCommand(intent, flags, startId)
        }
    
        /**
         * 如果WindowManager还未创建,则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。
         *
         * @param context 必须为应用程序的Context.
         * @return WindowManager的实例,用于控制在屏幕上添加或移除悬浮窗。
         */
        private fun getWindowManager(context: Context): WindowManager {
            if (mWindowManager == null) {
                mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
            }
            return mWindowManager!!
        }
    
        override fun onBind(intent: Intent?): IBinder {
            TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
        }
    }

    3.WindowManager问题

    在我们平时写代码的时候,经常要用到windowmanager这个类,一般是通过addview的方式,把一个view添加到一个窗口中,在系统中,比如toast,悬浮框,状态栏,通知栏,锁屏界面他们都不是平常的activity中的window,因此通过windowmanager 直接addview的方式来呈现给用户

    WindowManager是一个接口,并继承了ViewManager接口.ViewManager有三个方法,
    addView,updateViewLayout,removeView,分别用于添加View,更新View的布局和移除View,由于WindowManager继承ViewManager,可见WindowManager也是对View进行管理,其中WindowManager有多了一个removeViewImmediate()用于立刻移除View,用于Activity中,防止Activity销毁之后造成窗口溢出

    public interface ViewManager
    {
    
        public void addView(View view, ViewGroup.LayoutParams params);
        public void updateViewLayout(View view, ViewGroup.LayoutParams params);
        public void removeView(View view);
    }

    而从打印的Log信息来看,addView()是执行成功,没有异常的,所以浮窗是添加成功的.但是在创建浮窗和移除浮窗的时候,一定要先确认浮窗addView.如果浮窗已经添加了,再次添加会报异常;如果浮窗没有添加,在执行removeView(View view)会报异常

    4.浮窗不显示是因为浮窗的宽高为0

    (1)将浮窗layout中的宽高赋值,而不是wrap_content

    (2)将addView(View view, ViewGroup.LayoutParams params)浮窗params的宽高写死为200,但是还是没有显示.但是点击浮窗所在的位置,会执行updateViewLayout方法和浮窗的点击事件,由此更加确认浮窗已经存在

    5.在浮窗的构造方法中添加setBackgroundColor(Color.GREEN)

    这个时候出现了一个绿色的方块儿区域,但是图片还是没有显示出来

    6.在layout中的布局中添加背景

    背景显示出来了,图片未显示

    7.将app:srcCompat换为android:src

    图片显示出来了,本来直接给出结果就可以了,但是我还是梳理了整个分析的流程.

    接下来就是揭晓原因的时候了

    使用 app:srcCompat 的时候 引入的图片显示不出来的解决方案
    首先查看的你的Activity 继承的是那个Activity 如果是继承AppcompatActivity 使用 ImageView的 app:srcCompat 是没有问题的
    如果你的Activity不是继承的AppcompatActivity, 需要用到 android.support.v7.widget.AppCompatImageView 代替 ImageView。

    这样就可以解释为什么我可以通过Activity打开浮窗,而Service和Application的Context都不可以,当然我的Activity是继承AppcompatActivity.这里有两种修改方式,如下

    方法一:修改ImageViewAppCompatImageView

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical">
    
        <androidx.appcompat.widget.AppCompatImageView
            android:id="@+id/athanasy_float_window"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            app:srcCompat="@mipmap/ic_launcher_round"
            />
    
    </LinearLayout>

    方法二:修改 app:srcCompat为“““

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:orientation="vertical">
    
         <ImageView
            android:id="@+id/athanasy_float_window"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@mipmap/ic_launcher_round"
            />
    
    </LinearLayout>

    二.浮窗源码:

    1. FloatWindowSmallView

    package com.hp.athanasyservice.xiaoqi.floatwindow
    
    import android.content.Context
    import android.view.LayoutInflater
    import android.view.MotionEvent
    import android.view.WindowManager
    import android.widget.LinearLayout
    import com.billy.cc.core.component.CC
    import com.blankj.utilcode.util.ReflectUtils
    import com.hp.athanasyservice.R
    import com.hp.baseres.base.BaseApplication.Companion.mContext
    import com.hp.baseres.utils.LogUtils
    import com.hp.business.AppCCConstants
    import kotlinx.android.synthetic.main.athanasy_small_float_window.view.*
    
    /**
     * Created by tangdekun on 2017/6/2.
     */
    
    class FloatWindowSmallView(mContext: Context) : LinearLayout(mContext) {
    
        /**
         * 用于更新小悬浮窗的位置
         */
        private val windowManager: WindowManager = mContext.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    
        /**
         * 小悬浮窗的参数
         */
        private var mParams: WindowManager.LayoutParams? = null
    
        /**
         * 记录当前手指位置在屏幕上的横坐标值
         */
        private var xInScreen: Float = 0.toFloat()
    
        /**
         * 记录当前手指位置在屏幕上的纵坐标值
         */
        private var yInScreen: Float = 0.toFloat()
    
        /**
         * 记录手指按下时在屏幕上的横坐标的值
         */
        private var xDownInScreen: Float = 0.toFloat()
    
        /**
         * 记录手指按下时在屏幕上的纵坐标的值
         */
        private var yDownInScreen: Float = 0.toFloat()
    
        /**
         * 记录手指按下时在小悬浮窗的View上的横坐标的值
         */
        private var xInView: Float = 0.toFloat()
    
        /**
         * 记录手指按下时在小悬浮窗的View上的纵坐标的值
         */
        private var yInView: Float = 0.toFloat()
        private var screenWidth: Float = 0.toFloat()
        private var screenHeight: Float = 0.toFloat()
    
    
        init {
            LayoutInflater.from(mContext).inflate(R.layout.athanasy_small_float_window, this)
            viewWidth = athanasy_float_window.layoutParams.width
            viewHeight = athanasy_float_window.layoutParams.height
        }
    
    
        override fun onTouchEvent(event: MotionEvent): Boolean {
            when (event.action) {
                MotionEvent.ACTION_DOWN -> {
                    // 手指按下时记录必要数据,纵坐标的值都需要减去状态栏高度
                    xInView = event.x
                    yInView = event.y
                    xDownInScreen = event.rawX
                    yDownInScreen = event.rawY - getStatusBarHeight()
                    xInScreen = event.rawX
                    yInScreen = event.rawY - getStatusBarHeight()
                }
                MotionEvent.ACTION_MOVE -> {
                    xInScreen = event.rawX
                    yInScreen = event.rawY - getStatusBarHeight()
                    // 手指移动的时候更新小悬浮窗的位置
                    updateViewPosition()
                }
                MotionEvent.ACTION_UP -> {
                    val t = System.currentTimeMillis().toFloat()
                    // 如果手指离开屏幕时,xDownInScreen和xInScreen相等,且yDownInScreen和yInScreen相等,则视为触发了单击事件。
                    updateViewPositionFinish()
                    LogUtils.d(TAG, "updateViewPositionFinish():" + (System.currentTimeMillis() - t))
                    if (xDownInScreen == xInScreen && yDownInScreen == yInScreen) {
                        openBigWindow()
                    }
                    LogUtils.d(TAG, "openBigWindow():" + (System.currentTimeMillis() - t))
                }
    
            }
            return true
        }
    
        /**
         * 更新浮窗移动完毕的位置
         */
        private fun updateViewPositionFinish() {
            mParams!!.y = (yInScreen - yInView).toInt()
            screenWidth = windowManager.defaultDisplay.width.toFloat()
            screenHeight = windowManager.defaultDisplay.height.toFloat()
            if (xInScreen <= screenWidth / 2) {
                mParams!!.x = 0
            } else {
                mParams!!.x = screenWidth.toInt()
            }
            windowManager.updateViewLayout(this, mParams)
            mXProportion = mParams!!.x / screenWidth
            mYProportion = mParams!!.y / screenHeight
        }
    
        /**
         * 将小悬浮窗的参数传入,用于更新小悬浮窗的位置。
         *
         * @param params 小悬浮窗的参数
         */
        fun setParams(params: WindowManager.LayoutParams) {
            mParams = params
        }
    
        /**
         * 更新小悬浮窗在屏幕中的位置。
         */
        private fun updateViewPosition() {
            mParams!!.x = (xInScreen - xInView).toInt()
            mParams!!.y = (yInScreen - yInView).toInt()
            windowManager.updateViewLayout(this, mParams)
        }
    
        /**
         * 打开Activity
         */
        private fun openBigWindow() {
            CC.obtainBuilder(AppCCConstants.COMPONENT_NAME)
                    .setActionName(AppCCConstants.ACTION_OPEN_MAINACTIVITY)
                    .setContext(mContext)
                    .build()
                    .call()
        }
    
        /**
         * 用于获取状态栏的高度。
         *
         * @return 返回状态栏高度的像素值。
         */
        private fun getStatusBarHeight(): Int {
    
            if (statusBarHeight == 0) {
                try {
                    val x = ReflectUtils.reflect("com.android.internal.R\$dimen").field("status_bar_height").get<Int>()
                    statusBarHeight = resources.getDimensionPixelSize(x)
                } catch (e: Exception) {
                    e.printStackTrace()
                }
    
            }
            return statusBarHeight
        }
    
        companion object {
    
            val TAG = FloatWindowSmallView::class.java.name!!
            /**
             * 记录每次浮窗当前的位置  --每次切换旋转屏幕按比例跳转位置
             */
            var mXProportion = 1f
            var mYProportion = 0.5f
            /**
             * 记录小悬浮窗的宽度
             */
            var viewWidth: Int = 0
    
            /**
             * 记录小悬浮窗的高度
             */
            var viewHeight: Int = 0
    
            /**
             * 记录系统状态栏的高度
             */
            private var statusBarHeight: Int = 0
        }
    }
    

    2. FloatWindowManager

    package com.hp.athanasyservice.xiaoqi.floatwindow
    
    import android.annotation.SuppressLint
    import android.content.Context
    import android.graphics.PixelFormat
    import android.util.DisplayMetrics
    import android.view.Gravity
    import android.view.WindowManager
    import android.view.WindowManager.LayoutParams
    import com.hp.baseres.utils.LogUtils
    
    
    /**
     * Created by tangdekun on 2017/6/2.
     */
    
    object FloatWindowManager {
    
        private val TAG = "FloatWindowManager"
        /**
         * 小悬浮窗View的实例
         */
        @SuppressLint("StaticFieldLeak")
        private var smallWindow: FloatWindowSmallView? = null
    
        /**
         * 小悬浮窗View的参数
         */
        private var smallWindowParams: LayoutParams? = null
    
        /**
         * 用于控制在屏幕上添加或移除悬浮窗
         */
        private var mWindowManager: WindowManager? = null
    
        /**
         * 是否有悬浮窗(包括小悬浮窗和大悬浮窗)显示在屏幕上。
         *
         * @return 有悬浮窗显示在桌面上返回true,没有的话返回false。
         */
        var isWindowShowing: Boolean = false
    
        /**
         * 创建一个小悬浮窗。初始位置为屏幕的右部中间位置。
         *
         * @param context 必须为应用程序的Context.
         */
        fun createSmallWindow(context: Context) {
            val windowManager = getWindowManager(context)
    
            fun addView(context: Context, windowManager: WindowManager) {
                LogUtils.dTag(TAG, "创建浮窗$context")
                if (smallWindow == null) {
                    smallWindow = FloatWindowSmallView(context)
                    if (smallWindowParams == null) {
                        setSmallWindowParams(context)
                    }
                    smallWindow!!.setParams(smallWindowParams!!)
                    LogUtils.dTag(TAG, smallWindowParams.toString())
                }
                windowManager.addView(smallWindow, smallWindowParams)
                isWindowShowing = true
            }
            if (!isWindowShowing) {
                addView(context, windowManager)
            } else {
                LogUtils.dTag(TAG, "浮窗已存在$context")
            }
    
        }
    
    
        /**
         * 重置小浮窗位置
         *
         * @param context
         */
        fun resetSmallWindowPosition(context: Context) {
            LogUtils.dTag(TAG, "resetSmallWindowPosition")
            if (smallWindowParams != null) {
                val windowManager = getWindowManager(context)
                val outMetrics = DisplayMetrics()
                windowManager.defaultDisplay.getMetrics(outMetrics)
                val screenWidth = outMetrics.widthPixels
                val screenHeight = outMetrics.heightPixels
                smallWindowParams!!.x = (FloatWindowSmallView.mXProportion * screenWidth).toInt()
                smallWindowParams!!.y = (FloatWindowSmallView.mYProportion * screenHeight).toInt()
                if (smallWindow != null) {
                    getWindowManager(context).updateViewLayout(smallWindow, smallWindowParams)
                }
            }
    
        }
    
        private fun setSmallWindowParams(context: Context) {
            val windowManager = getWindowManager(context)
            val outMetrics = DisplayMetrics()
            windowManager.defaultDisplay.getMetrics(outMetrics)
            val screenWidth = outMetrics.widthPixels
            val screenHeight = outMetrics.heightPixels
            smallWindowParams = LayoutParams()
            smallWindowParams!!.type = WindowManager.LayoutParams.TYPE_PHONE
            smallWindowParams!!.format = PixelFormat.RGBA_8888
            smallWindowParams!!.flags = WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            smallWindowParams!!.gravity = Gravity.LEFT or Gravity.TOP
            smallWindowParams!!.width = FloatWindowSmallView.viewWidth
            smallWindowParams!!.height = FloatWindowSmallView.viewHeight
            smallWindowParams!!.x = screenWidth
            smallWindowParams!!.y = screenHeight / 2
        }
    
        /**
         * 将小悬浮窗从屏幕上移除。
         *
         * @param context 必须为应用程序的Context.
         */
        fun removeSmallWindow(context: Context) {
            if (smallWindow != null && isWindowShowing) {
                LogUtils.dTag(TAG, "删除浮窗$context")
                val windowManager = getWindowManager(context)
                windowManager.removeView(smallWindow)
                isWindowShowing = false
                smallWindow = null
                smallWindowParams = null
            } else {
                LogUtils.dTag(TAG, "$context 浮窗不存在,无法删除")
            }
    
        }
    
        /**
         * 如果WindowManager还未创建,则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。
         *
         * @param context 必须为应用程序的Context.
         * @return WindowManager的实例,用于控制在屏幕上添加或移除悬浮窗。
         */
        private fun getWindowManager(context: Context): WindowManager {
            if (mWindowManager == null) {
                mWindowManager = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
            }
            return mWindowManager!!
        }
    
    
    }
    
    展开全文
  • addView 层级关系

    2017-11-28 10:56:29
    1. addview(view, 0); // 加在最底层 2. 依次加入addview(view1, 0); addview(view2, 2); //此时会报错,加这个view时,父窗口只有一个view,所以参数2会越界 addview(view3, 1); 3. 依次加入addview(view1, 0)...
    1. addview(view, 0); // 加在最底层
    2. 依次加入addview(view1, 0);
    addview(view2, 2); //此时会报错,加这个view时,父窗口只有一个view,所以参数2会越界
    addview(view3, 1);
    3. 依次加入addview(view1, 0);
    addview(view2, 1);
    addview(view3, 1);
    // 此时最上次会显示view2,
    // view3 的顺序号并不比view2大,排在view2后面
    展开全文
  • Android addView()方法简述(一)

    千次阅读 2019-09-27 20:52:18
    大家都知道addView()一般用来动态添加View,LinearLayout、RelativeLayout添加子控件都可以用addView()。去看Android官方文档:ViewGroup里有addView的相关介绍。大概如下: 方法 解释 addView (View child,...

    Android addView()方法分为以下几个部分
    addView()方法简述(一)
    addView()方法实际使用和面试手册(二)

    简介

    大家都知道addView()一般用来动态添加View,LinearLayout、RelativeLayout添加子控件都可以用addView()。去看Android官方文档:ViewGroup里有addView的相关介绍。大概如下:

    方法 解释
    addView (View child, ViewGroup.LayoutParams params) Adds a child view with the specified layout parameters.
    - 添加具有指定布局参数的子视图。默认往ViewGroup最后添加。
    addView (View child, int index) Adds a child view. If no layout parameters are already set on the child, the default parameters for this ViewGroup are set on the child.
    - 添加子视图。如果没有在子视图上设置布局参数,则此ViewGroup的默认参数将在子视图上设置。看完这个就知道和上一个的区别了。添加到指定的位置。
    addView (View child, int index,ViewGroup.LayoutParams params) Adds a child view with the specified layout parameters.
    - 添加具有指定布局参数的子视图。添加到指定的位置。
    addView (View child) Adds a child view. If no layout parameters are already set on the child, the default parameters for this ViewGroup are set on the child.
    - 添加子视图。如果没有在子视图上设置布局参数,则此ViewGroup的默认参数将在子视图上设置。
    addView (View child, int width, int height) Adds a child view with this ViewGroup’s default layout parameters and the specified width and height.
    - 使用此ViewGroup的默认布局参数和指定的宽度和高度添加子视图。

    看完这个表格,其实对addView方法的不同参数已经有了大致的了解了。这里要说明的是ViewGroup才有addView方法,View是没有的。但是参数中的View可以是一个ViewGroup。

    各个参数的具体说明

    注意:不要从
    View.draw(android.graphics.Canvas)、View.onDraw(android.graphics.Canvas)、dispatchDraw(android.graphics.Canvas)
    或任何相关方法调用此方法。

    1.addView (View child, ViewGroup.LayoutParams params)

    这个方法是将第二个参数指定的布局给第一个参数传入的子视图中。

    2.addView (View child, int index)

    这个方法是将传入的子视图放在父布局的指定位置。
    一个竖向的LinearLayout,如果你把index指定为-1则每次都会把子视图放在最后一个,也就是一个一个向下叠加,新加入的会放在最后;如果把Index指定为0,新加入的将会在头部把先加入的子视图挤下去,达到在顶部插入视图的效果。以此类推,别的数字和布局都差不多,大家多思考就能想出效果。

    3.addView (View child, int index,ViewGroup.LayoutParams params)

    这个就是前两个的一个结合,不多说了。

    4.addView (View child)

    需要注意的是,这个会吧父布局的布局信息添加给这个子视图。所以,如果你想这个子视图有自己的布局信息,就要先通过setLayoutParams设置好布局信息再addView。

    5.addView (View child, int width, int height)

    这个看上去就很容易,通过width和height来指定子视图的宽高。

    总结

    其实好多公司的APP都是没有Activity布局的,他们的布局其实就是一个空的LinearLayout指定id,然后通过findViewById找到这个根布局后添加头部等信息,这样就可以复用布局文件,写起来也容易。

    展开全文
  • addView

    2017-04-27 21:28:17
    addView就是动态添加子控件到父控件中去 情况一: 如果父控件是LinearLayout,子控件可以是TextView或Button等 LinearLayout ll = (LinearLayout)findViewById(R.id.ll); // 将TextView 加入到LinearLayout 中 ...
  • addview() 后数据不显示

    2016-02-24 07:21:47
    !...用addview后出来的效果图 很明显 日历没有...然后日历出来了 没有addview能看到是一个日历加了Addview后就看不到数据 这是怎么回事呢 ![图片说明](https://img-ask.csdn.net/upload/201602/23/1456220870_444155.jpg)
  • Android 获取View的位置参数:x,y和相对父容器的偏移量以及中心点坐标Android 利用代码动态添加Viw关于代码中的屏幕适配最后,奉上工具类感谢观看 你好! Android 利用代码动态添加Viw ...addView(...
  • Android使用addView动态添加组件

    万次阅读 2017-10-27 22:07:57
    在项目开发中,我们经常需要进行动态添加组件,其中可添加的部分有两项:布局和组件  其中,添加的布局主要有RelativeLayout型(相对布局)的和LinearLayout(线性布局)  添加的组件主要有文本显示框,编辑框,...
  • 这时就会用到LinearLayout的addView(View v)和addView(View v, int p)。  addView(View v)是直接依次加在线性布局中。当我们想要将子控件加在线性布局某个控件前后时,就可以使用addView(View v, int p),参数p...
  • ``` //首页按钮 ImageView home=new ImageView(context);...时候会报错,然后我试了一下其他的,结果是只要是第二次addView的参数对象之前已经addView过一次,就会报错,请问是因为什么?有什么解决办法?
  • 动态添加布局时,addView容引发的错误:java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first。原因是:实例化的一个布局(start)...
  • 通过addView进行添加子View却发现,居然在不同的系统版本下显示不一样呀。 android4.4的view出现在上层; ![图片说明](https://img-ask.csdn.net/upload/201704/01/1491048772_921741.png) android6.6的view出现在...
  • Android ViewGroup中addView方法使用

    千次阅读 2018-05-21 19:41:43
    Android 中ViewGroup 中的添加子控件的方法addVIew方法 //child:要添加的view public void addView(View child) ; //child:要添加的View index:view在父布局中位于第几个 public void addView(View child, int ...
  • Android addView()方法分为以下几个部分 addView()方法简述(一) 本章简介 本章将针对上文提到的addView()的方法进行实例操作,并就可能出现的问题以面试题的方式进行解答。 1 .addView (View child, ViewGroup....
  • AddView和layoutParams总结

    2020-08-10 17:08:15
    一、AddVIew addview方法可以用于动态地向布局内添加view addview重载了五个方法,如下所示 addView(View child) // child-被添加的View addView(View child, int index) // index-被添加的View的索引 addView(View ...
  • android View addView 笔记

    2019-03-20 17:28:37
    addView 主要有这几个方法 addView(View child) // child-被添加的View addView(View child, int index) // index-被添加的View的索引 addView(View child, int width, int height) // width,height被添加的View...
  • 子view就是一个桌子,通过调用父布局的addview加入到父布局中 遇到这个问题的时候去查过源码,源码中addview(View view)最后会调用 ``` public void addView(View child, int index, LayoutParams params) ...
  • addView是继承viewGroup的方法, void android.view.ViewGroup.addView(View child); void android.view.ViewGroup.addView(View child, LayoutParams params); void android.view.ViewGroup.addView(View child...
  • 天天记录 - Android addView源码分析

    千次阅读 2017-07-12 11:46:28
    Android把视图显示到屏幕上,从代码角度最终都是调用ViewGroup.addView方法,可以分为两类,一是初始化时添加视图,二是动态添加视图。 1. 从源码角度分析添加视图的流程,以下列出其中4个addView方法 public void...
  • 看完需求后,想都不用想直接使用recyclerview,item的根布局为Relativelayout,通过LayoutParams和后台给的数据确定位置和大小,最后addView添加到viewGroup中:效果和预想的一样 但是最后滑动多张后,发现点击空白处,...
1 2 3 4 5 ... 20
收藏数 60,034
精华内容 24,013
关键字:

addview