findViewById() returns null for custom component in layout XML, not for other components

前端 未结 18 1539
情歌与酒
情歌与酒 2020-11-28 10:36

I have a res/layout/main.xml including these elements and others:



        
18条回答
  •  广开言路
    2020-11-28 11:30

    I ran into the same issue a while back when I added a custom View via the layout XML and then tried to attached a callback elsewhere in the application ...

    I created a custom view and added it to my "layout_main.xml"

    public class MUIComponent extends SurfaceView implements SurfaceHolder.Callback {
        public MUIComponent (Context context, AttributeSet attrs ) {
            super ( context, attrs );
        }
        // ..
    }
    

    And in the main Activity I wanted to attach some callbacks and get references to the UI elements from the XML.

    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
    
            // ...
    
            MUIInitializer muiInit = new MUIInitializer();
            muiInit.setupCallbacks(this);
            muiInit.intializeFields(this);
        }       
    }
    

    The initilizer wasn't doing anything fancy but any changes it tried to make to the custom view (MUIComponent) or other non-custom UI elements simply were not appearing in the application.

    public class MUIInitializer {
    
        // ...
    
        public void setupCallbacks ( Activity mainAct ) {
    
    
            // This does NOT work properly
            // - The object instance returned is technically an instance of my "MUICompnent" view
            //   but it is a *different* instance than the instance created and shown in the UI screen
            // - Callbacks never get triggered, changes don't appear on UI, etc.
            MUIComponent badInst = (MUIComponent) mainAct.findViewById(R.id.MUIComponent_TESTSURF);
    
    
            // ...
            // This works properly
    
            LayoutInflater inflater = (LayoutInflater) mainAct.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            View inflatedLayout = inflater.inflate ( R.layout.activity_main, null );
    
            MUIComponent goodInst = (MUIComponent) inflatedLayout.findViewById(R.id.MUIComponent_TESTSURF);
    
    
            // Add callbacks
            // ...
        }
    
    }
    

    The difference between the "badInst" and "goodInst" is:

    • badInst uses the Activity's findViewByID
    • goodInst inflates the layout and uses the inflated layout to do the lookup

提交回复
热议问题