17

How do I debug a Custom View in the Graphical Preview of a Layout XML using the ADT Eclipse plugin?


I wrote a custom view, put it in a layout XML, and I can preview it in the ADT Graphical Layout Editor. I can view my custom view like how the Google guys did in Google I/O 2011: Android Development Tools. However, my custom view behaves wrongly in the preview (no problem on emulators/devices, but I'm not using View.isInEditMode()). I think a variable has a wrong value, but I can't confirm. I've tried:

Pang
  • 9,564
  • 146
  • 81
  • 122

2 Answers2

6

Good question! I am wondering the same. Having a good preview in layout editor is really really difficult and it seems to be quite little documentation about what you can and you can't do when "isineditmode" is true (for example, analise custom XML attributes in the incoming AttributeSet on the constructor of the views doesn't seem to work, etc, etc.).

I even have problems with finding views by ID in a custom view. A simple thing like

mTextView = (TextView)myLayout.findViewById(R.id.view_id);

after inflating my custom view layout returns null only when running the layout from the editor (i.e. isineditmode() == true). When running the app on a phone it works.

I leave you here what helped me when trying to better preview my layouts in the layout editor:

1- Finding the views: I use the TAG property, as the findViewWithTag() function does work when in edit mode. So I use the Id for the TAG

<TextView
    android:id="@+id/myTextViewId"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    ...
    android:tag="mytextViewId" />

and then find the views using the tag:

if(isineditmode()){
    ((TextView)myLayout.findViewWithTag("myTextViewId")).setText("Test text");
}

2- Checking some values to know why sometimes my custom view cannot be instantiated in edit mode, or checking if some proerties can be queried in edit mode and know their value. I use a especial textview in the parent layout in which my custom view will be placed, and I leave it hidden and with a special tag:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > 

    ...

    <com.example.myCustomView ... />

    ...

    <TextView
        android:id="@+id/DebugView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" 
        android:tag="debug"
        android:textSize="16sp"
        android:textColor="#FFFFFF"
        android:visibility="gone"
     />

</LinearLayout>

This linear layout would be the parent of my custom view, and the one I need to open in the layout editor in order to preview my custom view. The "debug" textview visibilty is "gone" so I won't disturb if no needed. Then, when I need to check something I do the following in the java code of my custom view:

if(isineditmode()){
    TextView wDebugView = (TextView)this.getRootView().findViewWithTag("debug");
    wDebugView.setVisibility(View.VISIBLE);
    wDebugView.setText(Integer.valueOf(getPaddingTop()).toString());
}

In this example I check a property of the view, like the top padding.

Important note: you need to manually convert to String the value to show in the "debug" view, otherwise it will crash and give you an error.

Hope it helps.

And if anyone has some idea of why finding views by id doesn't work, any help would be appreciated.

Pek Ifly
  • 89
  • 3
3

I agree this is frustrating. For me findViewWithTag() does not work, it always returns null in ADT preview mode. But I was able to set up a simple log to a local (non-Android) file and tail it debug my custom views, e.g. as below (this checks isEditMode to ensure it's a no-op if accidentally run in Android):

/** ONLY FOR ECLIPSE: enables us to do some basic logging to a file to debug our custom views in Eclipse preview mode */ 
public static void eclipseEditModeLog(View view, String s) {
    if (view.isInEditMode()) {
        try {
            // Open our hack log file in append mode
            if (eclipseLogOut == null) {
                File eclipseLogFile = new File("/home/mwk/tmp/eclipse.log");
                eclipseLogOut = new BufferedWriter(new FileWriter(eclipseLogFile, true));
            }
            eclipseLogOut.write(new Date().toLocaleString() + ": " + s + "\n");
            eclipseLogOut.flush();
        } catch (IOException e) {}
    }
}
private static BufferedWriter eclipseLogOut = null;
mwk
  • 1,959
  • 1
  • 14
  • 22
  • A great solution in theory, however I get an error "Write access not allowed during rendering" in the Eclipse Log. See https://code.google.com/p/android/issues/detail?id=67140 I've tried playing with directory/file permissions and running ADT as an Administrator but no luck. – Atorian May 10 '14 at 12:09
  • This one worked for me, which was a relief. Unfortunately, it only worked once, and I don't know why ! (I mean : really once ! It wrote one line in the log file, and that's all) Searching... – Orabîg Jul 16 '14 at 03:16
  • This works if the output path is a temp folder. If it's not a temp folder, it throws the "Write access not allowed during rendering" error. In Android Studio's designer Issues window, it will show "Failed path" and "Normal temp dir", where "Failed path" is the bad path. If the "Normal temp dir" is used as the output path, the file will be generate successfully there – Eliott Sep 29 '19 at 04:58