ano*_*nim 21 android custom-view
我做了如下
1)创建一个风格
<declare-styleable name="Viewee">
<attr name="linkedView" format="reference"/>
</declare-styleable>
Run Code Online (Sandbox Code Playgroud)
2)定义自定义视图布局
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#ffc0">
<TextView
android:id="@+id/custom_text"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="[text]"
/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
3)创建所需的类
public class Viewee extends LinearLayout
{
public Viewee(Context context, AttributeSet attributeSet)
{
super(context, attributeSet);
View.inflate(context, R.layout.viewee, this);
TextView textView = (TextView) findViewById(R.id.custom_text);
TypedArray typedArray = context.obtainStyledAttributes(attributeSet, R.styleable.Viewee);
int id = typedArray.getResourceId(R.styleable.Viewee_linkedView, 0);
if (id != 0)
{
View view = findViewById(id);
textView.setText(((TextView) view).getText().toString());
}
typedArray.recycle();
}
}
Run Code Online (Sandbox Code Playgroud)
最后是在下面的活动中
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res/com.ns"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<TextView
android:id="@+id/tvTest"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="android"/>
<com.ns.Viewee
android:layout_width="fill_parent"
android:layout_height="fill_parent"
app:linkedView="@+id/tvTest"
/>
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)
现在虽然我id在Viewee约束器中收到非零,但是findViewById(id)返回null并NullPointerException发生.
我错过了什么?
ano*_*nim 21
我找到了答案!
问题出findViewById(id)在我所说的地方.findViewById如文档所述,只查找子视图而不是高层次级别的视图.因此,我必须调用类似的东西,getRootView().findViewById(id)但也会返回null因为我称之为不正确的地方.
在Viewee约束器Viewee本身还没有连接到它的根,所以调用原因NullPointerException.
所以,如果我打电话给getRootView().findViewById(id)施工中的后别的地方,它工作正常,都"@+id/tvTest"和"@id/tvTest"正确.我测试过了!
答案如下
public class Viewee extends LinearLayout
{
public Viewee(Context context, AttributeSet a)
{
super(context, attributeSet);
View.inflate(context, R.layout.main6, this);
TextView textView = (TextView) findViewById(R.id.custom_text);
TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);
int id = t.getResourceId(R.styleable.Viewee_linkedView, 0);
if (id != 0)
{
_id = id;
}
t.recycle();
}
private int _id;
public void Foo()
{
TextView textView = (TextView) findViewById(R.id.custom_text);
View view = getRootView().findViewById(_id);
textView.setText(((TextView) view).getText().toString());
}
}
Run Code Online (Sandbox Code Playgroud)
并且Foo当需要通过其活动中的其他位置的引用ID处理附加视图时调用.
信用完全归功于在这篇文章中贡献的那些人.在提交问题之前我没有看过那个帖子.
Dar*_*ind 11
我知道这是一个老问题,但我想我会添加另一种方法,因为我想将所有内容封装到我的自定义视图中.
我不是从外面打电话,而是在层次结构中获得更高层次的另一种方式,onAttachedToWindow()而是我迷上了:
public class MyCustomView extends LinearLayout {
private int siblingResourceId;
private View siblingView;
public MyCustomView(Context context, AttributeSet a) {
super(context, attributeSet);
inflate(context, R.layout.main6, this);
TextView textView = (TextView) findViewById(R.id.custom_text);
TypedArray t = context.obtainStyledAttributes(a, R.styleable.Viewee);
siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, NO_ID);
t.recycle();
}
@Override
public void onAttachedToWindow() {
super.onAttachedToWindow();
if (siblingResourceId != NO_ID) {
siblingView = ((View) getParent()).findViewById(siblingResourceId);
}
}
}
Run Code Online (Sandbox Code Playgroud)
onAttachedToWindow被称为很早,但显然已经足够晚,整个视图层次结构已经解决.它至少可以完美地满足我的需求并且更加受控制,不需要从外部到工作的互动;-)
编辑: Kotlin代码添加
class MyCustomView(context: Context, attributeSet: AttributeSet) : LinearLayout(context, attributeSet) {
private val siblingResourceId: Int
private lateinit var siblingView: View
// All other constructors left out for brevity.
init {
inflate(context, R.layout.main6, this)
val textView = findViewById<TextView>(R.id.custom_text)
val t = context.obtainStyledAttributes(a, R.styleable.Viewee)
siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, NO_ID)
t.recycle()
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
if (siblingResourceId != NO_ID) {
siblingView = (parent as View).findViewById(siblingResourceId)
}
}
}
Run Code Online (Sandbox Code Playgroud)
注意:我们假设parent这个习惯View是View自己的.
| 归档时间: |
|
| 查看次数: |
16972 次 |
| 最近记录: |