我试图通过XML引用兄弟控件。
声明属性以引用MyTextView中的id:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MyTextView">
<attr name="valueTextViewId" format="reference" />
</declare-styleable>
</resources>
fragment_example.xml - 如何使用自定义属性:
<!-- Declare a "Title" text view that references a "Value" -->
<com.example.MyTextView
android:id="@+id/foo"
example:valueTextViewId="@id/bar"
... />
<!-- Depending on the "text" attribute of this "Value" textview -->
<!-- Do something within "Title" textview -->
<com.example.MyTextView android:id="@+id/bar" />
MyFragment.java - 对控件进行充气
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// calls MyTextView Ctor
View v = inflater.inflate(R.layout.fragment_example, container, false);
}
MyTextView类构造函数 - 在通货膨胀期间使用引用的textview执行某些操作:
public TextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = ctx.obtainStyledAttributes(attrs, R.styleable.MyTextView);
int refId = a.getResourceId(R.styleable.MyTextView_valueTextViewId);
// Updated to use context
if (refId > -1 && context instanceof Activity) {
Activity a = (Activity)context;
View v = a.findViewById(refId);
// THE PROBLEM: v is null
if (v != null) {
// In my case, I want to check if the "Value" textview
// is empty. If so I will set "this" textColor to gray
}
}
}
在此示例中, v
始终为null
。我假设因为在布局通胀期间,控件尚未添加。另一件需要注意的是,这是Fragment
,因此这可能是我无法在父活动中找到视图的原因。
是否可以像这样引用另一个控件?
答案 0 :(得分:2)
是否可以像这样引用另一个控件?
可以从View
引用另一个View
。
但是不建议在View
的构造函数中进行属性检查。
在View inflation期间,无法保证任何特定View
在任何其他first_layout.xml
之前被实例化。
比较这两种布局:
<com.example.MyTextView
...
android:id="@+id/foo"
example:valueTextViewId="@+id/bar" />
<com.example.MyTextView
...
android:id="@+id/bar" />
second_layout.xml
<com.example.MyTextView
...
android:id="@+id/bar" />
<com.example.MyTextView
...
android:id="@+id/foo"
example:valueTextViewId="@+id/bar" />
View
在此示例中,很明显,从构造函数检查属性将无法在其中一个布局中工作。
我同意可以将引用存储到View
中的其他public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MyTextView);
mReferenceId = a.getResourceId(R.styleable.MyTextView_valueTextViewId);
...
}
private int mReferenceId;
public View getReferenceViewFromActivity() {
if (getContext() instanceof Activity) {
return ((Activity)getContext()).findViewById(mReferenceId);
return null;
}
public View getReferenceView(View view) {
return view.findViewById(mReferenceId);
}
:
Activity
但你绝对应该在Fragment
或@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
MyTextView myTextView = (MyTextView)view.findViewById(R.id.foo);
MyReferenceView refView = (MyReferenceView)myTextView.getReferenceView(view);
//
// do property checking
//
}
内进行任何及所有财产检查:
{{1}}
答案 1 :(得分:1)
如果bar的id中有id为bar的textview,你可以这样做。
<com.example.MyTextView
android:id="@+id/foo"
...
android:tag="bar" />
<com.example.MyTextView android:id="@+id/bar" />
和
public TextView(Context context, AttributeSet attrs) {
super(context, attrs);
int barId = getResources().getIdentifier(getTag(), "id", packageName);
TextView bar = mActivity.findViewById(barId);
if (bar.getText() == "") {
// Gray out this "title" textview
setColor(android.R.color.gray);
}
// maybe set a text change listener to bar to make it future-proof
}
我只是将id作为MyTextView上的标记传递,因此您不需要创建新属性。
答案 2 :(得分:1)
将引用保存在构造函数中的私有字段中。在您的情况下,将refId保存在私有字段中。然后在onMeasure
函数中使用它们。
我建议你不要使用获取引用视图的方法。如果你看一下通常情况,例如RelativeView的孩子的layout_toLeftOf
,你会发现id始终是RelativeView的一个子节点,因此,它的兄弟姐妹目前来看。在这种情况下,通过使用getParent()
获取父级,将其转换为ViewGroup(不一定),并使用findViewById
查找带引用的视图,可以轻松获取视图。如果你可以做这种限制(id应该是兄弟姐妹),你可以摆脱对上下文的这种依赖,这最终会使你的视图无法使用。您可能最好使用setBla()而不是使用自己的属性来设置视图(如果未调用此setter,则可能会在onMeasure中抛出运行时错误。)
答案 3 :(得分:1)
据我所知,无法保证在Activity's
Fragment's
方法中完成onCreateView()
布局。
您可以尝试这种方法:
@Override
public void onActivityCreated(Bundle savedInstanceState){
mView.customMethodToSetTextColor(...)
}
在活动创建完成时以及onActivityCreated()
lifecycle中的onCreateView()
之后调用 Fragment
。