目录
摘要:
如何给TextView控件动态设置权重?权重属于LinearLayout布局子控件的一个属性,想要动态添加一个TextView控件的权重,调用setLayoutParams()方法,传入LinearLayout.LayoutParams对象,并在LinearLayout.LayoutParams构造方法中指定控件的宽,高和权重。
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f);
- TextView tv=new TextView(this);
- tv.setLayoutParams(lp);
关于TextView动态添加到LinearLayout父控件中出现“The specified child already has a parent”异常,动态设置setCompoundDrawables(drawable, null, null, null)没有效果和TextView的android:textColor属性添加颜色选择器没有改变颜色。
一.The specified child already has a parent异常
这句话的意思“当前子控件已经拥有一个父控件”,言外之意:一个子控件只允许有一个父控件,这就像现实生活:一个儿子有且仅有一个亲爸,出现这种异常的两个原因:一是拥有父控件的子控件被添加到另一个父控件中;二是同一个子控件被重复添加到一个父控件中
第一种提示:“The specified child already has a parent”的原因演示,设置布局文件activity_text_view
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/activity_text_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- tools:context="com.sinolvc.zspg.view.TextViewActivity">
- <TextView
- android:id="@+id/child_widget_tv"
- android:layout_width="wrap_content"
- android:text="子控件"
- android:textSize="@dimen/dp_018"
- android:layout_height="wrap_content" />
- </LinearLayout>
在MainActivity中使用LayoutInflater来解析布局文件activity_text_view,然后调用setContentView()方法,将布局初始化后的View添加到窗体中
- LinearLayout ll=(LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_text_view,null);
- setContentView(ll);
上述代码实现的效果和直接调用setContentView(R.layout.activity_text_view)一样,然后可以正常运行,没有报“The specified child already has a parent”的异常。这个时候,如果获取到LinearLayout父控件内的TextView子控件,最后调用setContentView()方法,即
- TextView tv=(TextView) ll.findViewById(R.id.child_widget_tv);
- setContentView(tv);
运行异常,Caused by: java.lang.IllegalStateException: The specified child already has a parent. You must call removeView() on the child's parent first.
调用父控件的removeView()方法“断绝父子关系”,之后才能添加被另一个父控件中,然后运行不再报错,即
- LinearLayout ll=(LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_text_view,null);
- TextView tv= (TextView) ll.findViewById(R.id.child_widget_tv);
- ll.removeView(tv);
- setContentView(tv);
第二种提示:“The specified child already has a parent”原因演示,设置布局文件activity_text_view_second
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/activity_text_view"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:gravity="center"
- tools:context="com.sinolvc.zspg.view.TextViewActivity">
- </LinearLayout>
在MainActivity类中动态添加多个TextView控件,设置TextView的图标和颜色选择,然后添加到父控件LinearLayout中,正确的做法即
- LinearLayout ll=(LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_text_view,null);
- TextView tv=null;
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f)
- for(int i=0;i<3;i++){
- tv=new TextView(this);
- tv.setLayoutParams(lp);
- tv.setText("子控件:"+i);
- ll.addView(tv);
- }
- setContentView(ll);
报异常的原因:同一个TextView对象被重复添加到LinearLayout父控件中(解析一个布局文件时需要注意)如下
- LinearLayout ll=(LinearLayout) LayoutInflater.from(this).inflate(R.layout.activity_text_view,null);
- TextView tv=new TextView(this);
- LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f)
- for(int i=0;i<3;i++){
- tv.setLayoutParams(lp);
- tv.setText("子控件:"+i);
- ll.addView(tv);
- }
- setContentView(ll);
二.动态设置setCompoundDrawables(drawable, null, null, null)没有效果
TextView可以在其左边、上边、右边和下边添加Drawable对象,开发可以调用setCompoundDrawables(drawable,null,null,null)添加,在获取drawable对象后,还需要设置drawable的setBound()方法设置限制,否则没有效果,即
- Drawable drawable=getResources().getDrawable(R.drawable.ic_launcher);
- drawable.setBounds(0, 0, drawable.getMinimumWidth(),drawable.getMinimumHeight());
- tv.setCompoundDrawables(drawable,null,null,null);
也可以调用setCompoundDrawablesWithIntrinsicBounds(int,int,int,int)或setCompoundDrawablesWithIntrinsicBounds(Drawable, Drawable, Drawable, Drawable)方法,,不需要设置Drawable的setBound()方法。
- tv.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_launcher,0,0,0);
或者
- Drawable drawable=getResources().getDrawable(R.drawable.ic_launcher);
- tv.setCompoundDrawablesWithIntrinsicBounds(drawable,null,null,null);
PS:需要注意区别setCompoundDrawablesRelativeWithIntrinsicBounds(int,int,int,int)和setCompoundDrawablesRelativeWithIntrinsicBounds(Drawable,Drawable,Drawable,Drawable)
三.TextView的android:textColor属性添加颜色选择器没有改变颜色
选择器分为:color和drawable,在res文件夹下手动创建color或drawable文件夹,然后存放selector根标签声明的item文件,系统会根据View当前的状态从selector中选择对应的item,每个item对应着一个具体的Drawable,系统按照从上到下的顺序查找,直到查找到第一条匹配的item。一般来说,默认的item都应该放在selector的最后一条并且不附带任何的状态,这样当上面的item都无法匹配View的当前状态时,系统就会选择默认的item(上述文字来源《Android开发艺术探索》)。
- <?xml version="1.0" encoding="utf-8"?>
- <selector xmlns:android="http://schemas.android.com/apk/res/android">
- <item android:color="@android:color/holo_blue_dark" android:state_selected="true"/>
- <item android:color="@android:color/holo_purple" android:state_focused="true"/>
- <item android:color="@android:color/holo_red_dark" android:state_checkable="true"/>
- <item android:color="@android:color/holo_red_light" android:state_enabled="true"/>
- <item android:color="@android:color/holo_blue_bright" android:state_single="true"/>
- <item android:color="@android:color/holo_green_light" android:state_activated="true"/>
- <item android:color="@android:color/holo_green_dark" android:state_accelerated="true"/>
- <item android:color="@android:color/holo_orange_light" android:state_pressed="true"/>
- <item android:color="@android:color/holo_orange_dark" android:state_window_focused="true"/>
- <item android:color="@android:color/black"/>
- </selector>
在TextView的android:textColor属性中,可以将上面代码(text_view_color_selector.xml)存放在color或drawable文件夹下,经过测试都可以正常引用,即
- android:textColor="@color/text_view_color_selector"
或者
- android:textColor="@drawable/text_view_color_selector"
默认情况下,TextView无法获取点击事件,即android:clickable="false",如果在xml文件设置了android:onClick=""属性,必须设置clickable为非false。如果TextView调用setOnClickListener()方法,同样会先判断clickable是否为非false,否则设置为true,这一步在源码执行,不需要手动设置。TextView源码提供setTextIsSelectable()方法获取焦点状态,setSelected()方法设置当前View是否选择状态,在同时调用上述两个方法时,根据color或drawable选择器item状态的先后顺序,优先改变android:textColor属性的颜色,调用了其中一种item状态就不会在执行另一种状态,所有状态都不符合才会调用最后的item。这就是为什么TextView在添加了上述选择/选中/按下等状态没有效果的原因。
你可能感兴趣的文章
转载请注明出处: https://www.teachcourse.cn/2059.html ,谢谢支持!