SOLVED and contents edited for clarity.
Relevant References:
Android ADT version 22, R.java files not generated
Developing for Android in Eclipse: R.java not regenerating
Create a NinePatch/NinePatchDrawable in runtime
https://code.google.com/p/android-apktool/wiki/9PatchImages
Question: How do I programmatically (i.e. runtime and not via an XML define) get a reference of my nine-patch into R.java so that I can call it from EmployeeAdapter::getView()?
Answer:
- To runtime/programmatically set the nine patch background identically for ALL View objects, execute
view.setBackgroundResource(R.drawable.blue_fill)inside ofAdapter::getView(...)before returning the object- To runtime/programmatically set the nine patch background individually for EACH View object, execute
setBackgroundResource(R.drawable.blue_fill)inside ofView::onDraw(...).- Be sure that your implementation of your
View::onDraw(Canvas c)does NOT draw over your 9.png, e.g.c.drawColor(color).- Place your file (blue_fill.9.png) in the correct
/res/drawable-*/folder (to be safe!)- I have read that nine patch files need to be all lowercase. (be safe, and do it!)
- There is syntax to define a nine patch inside an XML file (I am unsure of exactly how to leverage this and is beyond this scope) but I can assure you that I did NOT need it. In fact, I strongly suspect that my workspace woes ensued after I created
/res/drawable-mdpi/blue_fill.xmland then linked it to my/res/drawable-mdpi/blue_fill.9.pngwith XML syntax. This is probably wrong!- Feel free to borrow my working code below.
- Because errors with /res/, /layout/ will cause all sorts of problems and possibly a hosed workspace, be careful when editing XML or other non-.java files. (1) ALWAYS check LogCat, Problems, Console output, (2) look in Eclipse's error log, and finally (3) exhaustively look through your build config to see if problem persists (double check the new in ADT v22 "Project>Properties>Java Build Path>Order and Export" and make sure that your source code does not shadow an existing library higher up the Order!
Answer to my problem:
Due to a reason completely independent of ADT 22, My workspace was no longer regenerating
R.java. I suspect that my messing around with/res/drawable-*/folders caused my problems. I removed all files exceptic_launcher.pngfrom/res/drawable-*/to try to bring my workspace back to a virgin state. I also suspect that I imported the incorrect R library (The ONLY one you should import isimport com.example.yourproject.R)
Original Problem:
I am able to use bl_fill.9.png with my XML-defined GridView. However, when I try to programmatically assign the same bl_fill.9.png to my View object inside of EmployeeAdapter::getView(...) I get a compile-time error that bl_fill cannot be resolved or is not a field.
I have spent many days trying to fix this. Any help is much appreciated!
Environment:
- ADT: v22
- Android SDK Tools: rev22
- Android SDK Platform-tools: rev17
- Android SDK Build-tools: rev17
- Target API: Android 4.1 Jelly Bean (API level 16)
- Highest API: Android 4.2 Jelly Bean (API level 17)
Attempts:
- Wrong /res/drawable-*/ folder?
I tried all pictures in one folder. I tried all pictures in all folders. The pictures seems to be sourced just fine wherever they are because GridView never hiccups about not locating a picture resource.
- Bad nine-patch?
To debunk that it may be a poorly formatted *.9.png, I have tried several of them (all of which I downloaded) and every one works on my XML-defined GridView.
- Successful Code:
/res/layout/activity_main.xml : GridView is defined in XML here, and I am successful in assigning the 9 patch bl_fill
<?xml version="1.0" encoding="utf-8"?>
<GridView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/gridview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:numColumns="5"
android:columnWidth="90dp"
android:verticalSpacing="10dp"
android:horizontalSpacing="10dp"
android:stretchMode="columnWidth"
android:gravity="center"
android:background="@drawable/bl_fill"
/>
/res/drawable-xxhdpi/xxhdpi-9p.xml: I understand that this file is needed by the compiler to transform a "sourced" nine-patch (contains 1px border of control pixels) into a "compiled" nine-patch (adds a "chunk" metadata and strips all control pixels). But more importantly, I understand that int R.java.drawable.bl_fill should be generated from this file definition
<?xml version="1.0" encoding="utf-8"?>
<nine-patch
xmlns:android="http://schemas.android.com/apk/res/android"
android:src="@drawable/bl_fill"/>
- Unsuccessful Code (has been updated and now works):
However, it appears that R.java is generating int references for other resources, but just stubbornly won't generate one for bl_fill.
EmployeeAdapter.java
package com.stackoverflow.signinboard;
import java.util.List;
import android.R;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.NinePatchDrawable;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
// useful "Good Practices" for Adapters referenced at
// http://www.piwai.info/android-adapter-good-practices/
//
// also
// http://androidadapternotifiydatasetchanged.blogspot.in/
/**
* An adapter that abstracts the structure of a database and safely exposes
* information to consumers.
*
* {@link GridView} uses this to obtain self-draw information for itself and
* {@link EmployeeView} children
*/
public class EmployeeAdapter extends BaseAdapter {
private Context mContext;
private List<Employee> mEmployees;
public EmployeeAdapter(Context c, List<Employee> employees) {
mContext = c;
mEmployees = employees;
}
@Override
/**
* Returns the total number of employees
*/
public int getCount() {
return mEmployees.size();
}
/**
* Returns the specified employee
*
* @param arg0
* Index of the employee in database
*/
@Override
public Object getItem(int arg0) {
return mEmployees.get(arg0);
}
/**
* Not implemented.
*/
@Override
public long getItemId(int arg0) {
return 0;
}
/**
* Gets the EmployeeView specified by 'index'.
*
* @param index
* Index of this employee in the database
* @param convertView
* Reference to a View that may or may not be initialized
* @param parent
* Viewgroup that this View is associated with
* @return An initialized EmployeeView at the specified index
*/
@Override
public View getView(int index, View convertView, ViewGroup parent) {
EmployeeView employeeView;
// Recylce reference if possible, else instantiate a new EmployeeView
if (convertView == null) {
// Instantiate an Employeeview with the ID and state
// and define its parameters
employeeView = new EmployeeView(mContext, mEmployees.get(index)
.getmEmployeeId(), mEmployees.get(index).getState());
employeeView.setLayoutParams(new GridView.LayoutParams(150, 85));
employeeView.setPadding(8, 8, 8, 8);
employeeView.setBackgroundResource(R.drawable.bl_fill);
} else {
// Set new values for the ID and state of this EmployeeView
employeeView = (EmployeeView) convertView;
employeeView.initEmployee(mEmployees.get(index).getmEmployeeId(),
mEmployees.get(index).getState());
}
return employeeView;
}
}