2012-06-14 47 views
17

tôi đã làm như sauLàm cách nào để chuyển tham chiếu chế độ xem sang chế độ xem tùy chỉnh của Android?

1) Tạo một styleable

<declare-styleable name="Viewee"> 
    <attr name="linkedView" format="reference"/> 
</declare-styleable> 

2) xác định xem tùy chỉnh bố trí

<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> 

3) Tạo yêu cầu lớp

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(); 
} 
} 

và cuối cùng trong hoạt động như bên dưới

<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> 

nay mặc dù tôi nhận được một tổ chức phi zero id trong Viewee constractor, findViewById(id) retuns null và NullPointerException occures.

Tôi đang thiếu gì?

I did it as described here

Trả lời

17

Tôi đã tìm thấy câu trả lời!

Sự cố xảy ra với findViewById(id) và nơi tôi gọi nó. findViewById chỉ tìm kiếm chế độ xem con không phải chế độ xem tồn tại ở cấp phân cấp cao hơn là documentation nói. Vì vậy, tôi phải gọi một cái gì đó như getRootView().findViewById(id) nhưng điều đó cũng trả về null bởi vì nơi tôi gọi nó không phải là corrent.

Trong số Viewee constractor Viewee chính nó chưa được gắn vào thư mục gốc của nó để các nguyên nhân gọi NullPointerException.

Vì vậy, nếu tôi gọi đến getRootView().findViewById(id) ở một nơi khác sau khi kết thúc, nó hoạt động tốt và cả hai "@+id/tvTest""@id/tvTest" là chính xác. Tôi đã thử nghiệm nó!

câu trả lời là như sau

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()); 
    } 
} 

Foo được gọi khi nó là cần thiết để xử lý các điểm gắn qua id tham chiếu của nó ở một nơi khác trong hoạt động của bạn và những thứ tương tự.

Khoản tín dụng hoàn toàn được chuyển đến những người đã đóng góp trong số this post. Tôi chưa thấy bài đăng đó trước khi gửi câu hỏi.

+0

KHÔNG đặt nó trong 'onDraw' nhưng trong' onAttachedToWindow'. Đặt nó trong onDraw sẽ được gọi là X lần trên giây, phương pháp, có thể là 60 lần mỗi giây. @DanielWilson bạn có thể xóa nhận xét của mình không? –

2

bạn mô tả android:id được thiết lập để app:linkedView="@+id/tvTest. Tuy nhiên, @+id/tvTest được sử dụng để tạo id mới có tên "tvTest". Những gì bạn muốn làm là sử dụng app:linkedView="@id/tvTest.

+0

Tôi đã áp dụng câu trả lời của bạn mặc dù 'View view = findViewById (id);' vẫn trả về null! – anonim

+0

Tại sao bạn sử dụng 'id' để giữ id của Chế độ xem? Sẽ khá đơn giản khi sử dụng 'R.id.foo' thay vì tạo một biến khác. Ngoài ra, tôi không thể nói qua nhận xét của bạn cho dù bạn đã thay đổi thuộc tính 'app: linkedView' của phần tử' 'thành' "@ id/tvTest'. –

+0

Tôi phải giữ' id 'vì' Viewee' là một khung nhìn tùy chỉnh đề cập đến một chế độ xem khác cho một âm vang. Tôi không thể tham chiếu đến dạng xem được liên kết dưới dạng 'R.id.foo' như bạn đã nói, nếu tôi sử dụng' Viewee' trong một layout khác ở đó 'R .id.foo' không tồn tại? Tôi cũng đã làm như bạn đã đề xuất và thay đổi '" @ + id/tvTest "' thành '" @ id/tvTest "' nhưng không thành công. – anonim

8

Tôi biết đây là một câu hỏi cũ, nhưng tôi nghĩ tôi sẽ thêm một cách khác để làm điều này vì tôi muốn đóng gói mọi thứ vào chế độ xem tùy chỉnh của mình.

Thay vì gọi từ bên ngoài, một cách khác để nhận được một cái nhìn cao hơn trong hệ thống phân cấp, tôi đã nối vào onAttachedToWindow() thay vì:

public class MyCustomView extends LinearLayout { 
    private int siblingResourceId; 
    private View siblingView; 

    public MyCustomView(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); 
     siblingResourceId = t.getResourceId(R.styleable.MyCustomView_siblingResourceId, 0); 
     t.recycle(); 
    } 

    @Override 
    public void onAttachedToWindow() { 
     super.onAttachedToWindow(); 
     if (siblingResourceId != 0) { 
      siblingView = getRootView().findViewById(siblingId); 
     } 
    } 
} 

onAttachedToWindow được gọi là khá sớm, nhưng dường như cuối năm đủ cho toàn bộ hệ thống phân cấp xem đã được giải quyết.Nó hoạt động hoàn hảo cho nhu cầu của tôi ít nhất và được kiểm soát một chút và không cần sự tương tác từ bên ngoài để làm việc ;-)

Các vấn đề liên quan