Custom View not appearing

15,981

Solution 1

Your custom layout view is not appearing because you're not putting anything into it. In your onFinishInflate you have the line inflatedView = li.inflate(R.layout.provider_view, null); But you don't add that to your view. You have two options to add the views to your custom layout view.

Change your custom view to extend RelativeLayout, change the enclosing RelativeLayout to <merge> in your provider_view.xml, and fix your findViewId lines in to this.findViewId(...) since the views will be inflated into your layout.

In your layout xml do:

<com.bookcessed.booksearch.SearchProviderButton
android:id="@+id/csp_spb_1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_below="@+id/csp_tv_title"
rs:providerName="BOOKP">
    <!-- include this so it's added to your custom layout view -->
    <include layout="@layout/provider_view" />
</com.bookcessed.booksearch.SearchProviderButton>

provider_view becomes:

<?xml version="1.0" encoding="utf-8"?>
<merge
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:rs="http://schemas.android.com/apk/res/com.bookcessed.booksearch"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content" >
  <RelativeLayout
    android:id="@+id/pv_rl_strings"
  .
  .
  .
</merge>

SearchProviderButton:

public class SearchProviderButton extends RelativeLayout{
 .
 .
 .

 @Override
 protected void onFinishInflate() {
  super.onFinishInflate();

  //the <include> in the layout file has added these views to this 
  //so search this for the views
  ImageView logo = this.findViewById(R.id.pv_logo);
  logo.setImageResource(connector.getLogoDrawableID());


  TextView searchTV = (TextView)this.findViewById(R.id.pv_tv_search);
  TextView andTV = (TextView)this.findViewById(R.id.pv_tv_and);
  if(!connector.isSearchSupported()){
   andTV.setText("");
   searchTV.setVisibility(GONE);
  }

  setgenreIcons();
 }
 .
 .
 .

Or you could properly inflate the view in onCreate by layoutInflater.inflate(R.layout.provider_view, this, true). That call will inflate the referenced layout into the passed ViewGroup, in this case your custom view, and add the inflated Views to it. Then you can fix up the findViewId calls in your onFinishInflate.

Solution 2

TC... Sometimes it wont show in the preview unless you run it.

Solution 3

For wrap_content to work, you need to properly implement the measure and layout functions for your custom View. See How Android Draws Views for details on what these methods mean.

My guess would be that getMeasureWidth() and getMeasureHeight() functions for your view are always returning 0.

Share:
15,981

Related videos on Youtube

Aymon Fournier
Author by

Aymon Fournier

I am an ENTP

Updated on April 27, 2022

Comments

  • Aymon Fournier
    Aymon Fournier about 2 years

    Here is the XML for the layout in which I want my custom view to appear.

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:rs="http://schemas.android.com/apk/res/com.bookcessed.booksearch"
        android:id="@+id/widget273"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent" >
    
        <TextView
            android:id="@+id/csp_tv_title"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Choose Your Source"
            android:textSize="40sp"
            android:textColor="#ffc83200"
            android:gravity="center"
            android:paddingTop="15dip"
            android:paddingBottom="75dip"
            android:layout_alignParentTop="true"
            android:layout_centerHorizontal="true" />
    
        <com.bookcessed.booksearch.SearchProviderButton
            android:id="@+id/csp_spb_1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:layout_below="@+id/csp_tv_title"
            rs:providerName="BOOKP" />
    
    </RelativeLayout>
    

    Here is the custom view's XML:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:rs="http://schemas.android.com/apk/res/com.bookcessed.booksearch"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content" >
    
        <RelativeLayout
            android:id="@+id/pv_rl_strings"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:gravity="center"
            android:layout_alignParentTop="true" >
    
            <TextView
                android:id="@+id/pv_tv_search"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Search"
                android:layout_toRightOf="@+id/pv_tv_and"
                android:textSize="18sp"
                android:textColor="#ff11ab37"
                android:layout_alignParentTop="true" />
    
            <TextView
                android:id="@+id/pv_tv_and"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text=" and "
                android:textSize="18sp"
                android:paddingLeft="6dip"
                android:paddingRight="6dip"
                android:textColor="#ff000000"
                android:layout_centerHorizontal="true" />
    
            <TextView
                android:id="@+id/pv_tv_browse"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Browse"
                android:textSize="18sp"
                android:textColor="#ff0077bb"
                android:layout_alignParentTop="true"
                android:layout_toLeftOf="@+id/pv_tv_and" />
    
            <ImageView
                android:id="@+id/pv_logo"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/pv_tv_search"
                android:layout_centerInParent="true"
                android:layout_alignTop="@+id/pv_tv_and"
                android:src="@drawable/bookp_logo" />
    
        </RelativeLayout>
    
        <RelativeLayout
            android:id="@+id/pv_rl_genres"
            android:layout_width="wrap_content"
            android:layout_below="@+id/pv_rl_strings"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true" >
    
            <ImageView
                android:id="@+id/pv_genre1"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_alignParentLeft="true" />
    
            <ImageView
                android:id="@+id/pv_genre2"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre1" />
    
            <ImageView
                android:id="@+id/pv_genre3"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre2" />
    
            <ImageView
                android:id="@+id/pv_genre4"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre3" />
    
            <ImageView
                android:id="@+id/pv_genre5"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre4" />
    
            <ImageView
                android:id="@+id/pv_genre6"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre5" />
    
            <ImageView
                android:id="@+id/pv_genre7"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre6" />
    
            <ImageView
                android:id="@+id/pv_genre8"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre7" />
    
            <ImageView
                android:id="@+id/pv_genre9"
                android:layout_width="30dip"
                android:layout_height="30dip"
                android:layout_alignParentTop="true"
                android:layout_toRightOf="@+id/pv_genre8" />
    
        </RelativeLayout>
    
    </RelativeLayout>
    

    Here is the class SearchProviderButton:

    public class SearchProviderButton extends LinearLayout {
    
     private Connector connector;
     private Context context;
     private View inflatedView;
    
     public SearchProviderButton(Context context, AttributeSet attrs) {
       super(context, attrs);
    
      TypedArray a = getContext().obtainStyledAttributes(attrs,R.styleable.SearchProviderButton);
      connector = SearchProvider.valueOf(a.getString(R.styleable.SearchProviderButton_providerName)).getConnector();
    
      this.context = context;
      setFocusable(true);
      setBackgroundColor(Color.WHITE);
      setVisibility(VISIBLE);
    
      //setOnClickListener(listenerAdapter);
      setClickable(true);
    
     }
    
    
    
     @Override
     protected void onFinishInflate() {
      super.onFinishInflate();
    
      LayoutInflater li = LayoutInflater.from(context);
      inflatedView = li.inflate(R.layout.provider_view, null);
    
    
      ImageView logo = (ImageView)inflatedView.findViewById(R.id.pv_logo);
      logo.setImageResource(connector.getLogoDrawableID());
    
    
      TextView searchTV = (TextView)inflatedView.findViewById(R.id.pv_tv_search);
      TextView andTV = (TextView)inflatedView.findViewById(R.id.pv_tv_and);
      if(!connector.isSearchSupported()){
       andTV.setText("");
       searchTV.setVisibility(GONE);
      }
    
      setgenreIcons();
     }
    
    
    
     public Connector getConnector(){
      return connector;
     }
    
     public void setConnector(Connector connector){
      this.connector = connector;
     }
    
    
     private void setgenreIcons(){
      int[] genreIconDrawables = {R.id.pv_genre1,R.id.pv_genre2, R.id.pv_genre3,
        R.id.pv_genre4, R.id.pv_genre5, R.id.pv_genre6, R.id.pv_genre7, 
        R.id.pv_genre8, R.id.pv_genre9};  
    
      ArrayList<Genre> availgenre = connector.getAvailablegenres();
      availgenre.remove(Genre.ALL);
    
      int counter = 0;
      for(int genreIVid : genreIconDrawables){
       ImageView curgenreImageView = (ImageView)inflatedView.findViewById(genreIVid);
       if(counter < availgenre.size() - 1){
        curgenreImageView.setImageResource(availgenre.get(counter).getDrawable());
       } else {
        curgenreImageView.setVisibility(GONE);
       }
       counter++; 
      }
     }
    
     protected void onFocusChanged(boolean gainFocus, int direction, Rect previouslyFocusedRect) {
      if (gainFocus == true){
       this.setBackgroundColor(Color.rgb(255, 165, 0));
      } else {
       this.setBackgroundColor(Color.WHITE);
      }
     }
    
    
    }
    

    Here is the code for the class loading the xml that contains my custom component:

    bookPServiceProviderButton = (SearchProviderButton)findViewById(R.id.csp_spb_1);
    bookPServiceProviderButton.setOnClickListener(SPBOnClickListener);
    bookPServiceProviderButton.setConnector(new bookPConnector());
    bookPServiceProviderButton.setVisibility(View.VISIBLE);
    

    EDIT: After the first comment, I added this code:

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          super.onMeasure(widthMeasureSpec, heightMeasureSpec);
            int widthSpec = MeasureSpec.getMode(widthMeasureSpec);
            int width = MeasureSpec.getSize(widthMeasureSpec);
            int heightSpec = MeasureSpec.getMode(heightMeasureSpec);
            int height = MeasureSpec.getSize(heightMeasureSpec);
    
        setMeasuredDimension(width, height);
    
    }
    

    Now it has a width and a height, but nothing is showing up inside of it!

  • Aymon Fournier
    Aymon Fournier almost 14 years
    I think I've tried both ways of doing it, but probably not doing it correctly. I can't get it.
  • Jonathan O'Neil
    Jonathan O'Neil almost 14 years
    I've updated the answer to include examples of the necessary changes for the first method.
  • Aymon Fournier
    Aymon Fournier almost 14 years
    THANK YOU! I hope that someone might help you as much as you just helped me! Thank you soooo much. I would never have been able to put 2 and 2 together myself. Thanks again!
  • Aymon Fournier
    Aymon Fournier almost 14 years
    Do you know why my custom view is extremely tall? could have something to do with onMeasure? I tried to fit one more underneath the first, but its offscreen
  • Jonathan O'Neil
    Jonathan O'Neil almost 14 years
    Try removing your onMeasure that you added since it wasn't the actual problem. I haven't actually tried running your layout so I'm not sure how tall it should be. It looks like it should not be too much more than 30px.
  • arthur0304
    arthur0304 over 4 years
    exactly!! I had a correct xml structure, but nothing showed up until the first run. Must be an Android Studio bug