Add TextViews programmatically - android

I have an empty LinearLayout, and I need to add a dynamic number of TextViews to it. However when I use the code below, only the first TextView is shown:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] listofnumbers = new String[1000];
for ( int i = 0 ; i < 1000 ; ++i ) {
listofnumbers[i] = "null";
}
Context context = getBaseContext();
String text = null;
Uri uri = Uri.parse("content://sms");
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
String[] columnNames = cursor.getColumnNames();
LinearLayout lv = new LinearLayout(context);
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, dip(48));
boolean v = true;
while (cursor.moveToNext())
{
String numberString = (cursor.getString( cursor.getColumnIndexOrThrow("address") ) ).replace(" ", "");
int i = 0;
boolean numberNotPresent = true;
for ( ; listofnumbers[i] != "null" ; ++i ) {
if ( numberString.equals(listofnumbers[i]) ) {
numberNotPresent = false;
}
}
if ( numberNotPresent == true ) {
text = (CharSequence) "From: " + cursor.getString(cursor.getColumnIndexOrThrow("address")) + ": " + cursor.getString(cursor.getColumnIndexOrThrow("body"));
listofnumbers[i] = numberString;
TextView tv = new TextView(this);
tv.setText(text);
tv.setLayoutParams(textViewParams);
lv.addView( tv );
}
}
setContentView(lv);
}
Where have I gone wrong?

try to change these two lines:
LinearLayout lv = new LinearLayout(context);
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, dip(48));
with these:
LinearLayout lv = new LinearLayout(context);
lv.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams textViewParams = new LinearLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
basically you need to set the orientation for the lv LinearLayout to vertical as the default one is horizontal.

I am not sure, but may be for each textView you set fill_parent param? The 1st textView shows on all your layout.

Related

How to fetch text in Textview field through JSON in android?

I am developing android application in which i have 12 Dynamic Frame layout in which Frame layout having Text view,video,and play/pause button over it .I want to fetch text in the Text view field by JSON. But my problem is that when i fetch text in Text view field using JSON text will appear in 12th frame and rest of 11 frame are empty.I don't know how to resolve this .kindly help me .
public class MainActivity extends Activity {
String moviename;
private ProgressDialog pDialog;
VideoView vv;
TextView showingat, movie;
FrameLayout frame;
ArrayList<String> abc;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.navigationbar);
abc = new ArrayList<>();
new Theaterflow().execute();
//Main Relative layout.
final RelativeLayout rl = (RelativeLayout)findViewById(R.id.MainRelativeLayout);
//Main Scrollview.
final ScrollView sv = (ScrollView) findViewById(R.id.scrollView);
//Main Linearlayout.
final LinearLayout ll = (LinearLayout) findViewById(R.id.LinearLayout1);
//Dynamically creation of Layouts.
FrameLayout.LayoutParams playpausebtn = new FrameLayout.LayoutParams(70, 70);
FrameLayout.LayoutParams sound = new FrameLayout.LayoutParams(55, 35);
FrameLayout.LayoutParams nowshwingat = new FrameLayout.LayoutParams(200, 60);
FrameLayout.LayoutParams movie_name = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 60);
//Defining array for framelayout.
ArrayList fHolder = new ArrayList();
int l = 12;
for (int i = 0; i<=l; i++) {
//Dynamically frameslayout for video
fHolder.add(frame);
frame = new FrameLayout(this);
FrameLayout.LayoutParams frameparams = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, 350);
frameparams.setMargins(0, 2, 0, 0);
frame.setId(i + 1);
frame.setMinimumHeight(350);
ll.addView(frame);
// Video over frames
vv = new VideoView(this);
vv.setId(i + 1);
vv.setLayoutParams(frameparams);
vv.setMinimumHeight(350);
frame.addView(vv);
//Pause btn over video
Button pausebtn = new Button(this);
pausebtn.setId(i + 1);
pausebtn.setBackgroundResource(R.drawable.pause);
pausebtn.setLayoutParams(playpausebtn);
playpausebtn.gravity = Gravity.CENTER;
frame.addView(pausebtn);
//Play btn over video
Button playbtn = new Button(this);
playbtn.setLayoutParams(playpausebtn);
playbtn.setId(i + 1);
playbtn.setBackgroundResource(R.drawable.playy);
playpausebtn.gravity = Gravity.CENTER;
frame.addView(playbtn);
//Sound btn over video
Button soundbtn = new Button(this);
soundbtn.setLayoutParams(sound);
soundbtn.setId(i + 1);
soundbtn.setBackgroundResource(R.drawable.sound);
sound.setMargins(0, 15, 5, 0);
sound.gravity = Gravity.RIGHT;
frame.addView(soundbtn);
//now showing at over video
showingat = new TextView(this);
showingat.setLayoutParams(nowshwingat);
showingat.setText("Now showing at ");
showingat.setTextSize(15);
showingat.setTextColor(getResources().getColor(R.color.white));
nowshwingat.setMargins(10, 0, 0, 0);
nowshwingat.gravity = Gravity.LEFT | Gravity.BOTTOM;
frame.addView(showingat);
movie = new TextView(MainActivity.this);
movie.setLayoutParams(movie_name);
movie.setId(i+1);
movie.setText(" ");
movie.setTextSize(15);
movie.setTextColor(getResources().getColor(R.color.white));
movie_name.setMargins(10, 10, 0, 0);
movie_name.gravity = Gravity.TOP | Gravity.LEFT;
frame.addView(movie);
}
}
private class Theaterflow extends AsyncTask<String, Void, String> {
// URL to get contents JSON
String url = "http://filfest.in/demo/theater/first-theater-data.php";
JSONArray contents = null;
protected void onPreExecute() {
super.onPreExecute();
pDialog = new ProgressDialog(MainActivity.this);
pDialog.setMessage("Loading Data ...");
pDialog.setIndeterminate(false);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String...urls){
ArrayList arraylist = new ArrayList<HashMap<String, String>>();
ServiceHandler sh = new ServiceHandler();
// Making a request to url and getting response
String jsonstr = sh.makeServiceCall(url, null);
if (jsonstr != null) {
try {
JSONObject jObject1 = new JSONObject(jsonstr);
contents = jObject1.optJSONArray("contents");
for (int i = 0; i < contents.length(); i++) {
JSONObject c1 = contents.getJSONObject(i);
moviename = c1.getString("movie_name");
abc.add(moviename);
}
} catch (JSONException e) {
e.printStackTrace();
}
}
return null;
}
public void onPostExecute(String result) {
if (pDialog.isShowing())
pDialog.dismiss();
for (int i=0;i<abc.size();i++)
{
movie.setText(moviename);
}
}
}
}
Add view Programatically in LinearLayout:
layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/llParent"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
Activity.java:
LinearLayout llParent = (LinearLayout)findViewById(R.id.llParent);
onPostExecute() of AsyncTask:
for (int i=0;i<Your_ArrayList.size(); i++){
TextView txtView = new TextView(this);
txtView.setText(Your_ArrayList.get(i).getMovieName());
llParent.addView(txtView);
}
Edit:
llParent.invalidate();
Hope this will help you.
inside your for loop
movie = new TextView(MainActivity.this);
movie.setTag(i);
insid your onPost() for loop
final int childCount = ll.getChildCount();
for (int y = 0; y < childCount; y++) {
final View child = ll.getChildAt(y);
if (child instanceof FrameLayout) {
int childs = ((FrameLayout) child).getChildCount();
for (int j = 0; j < childs; j++) {
final View childViews = ((ViewGroup) child)
.getChildAt(j);
if (childViews instanceof TextView) {
final Object tagObj = childViews.getTag();
if (tagObj != null && tagObj.equals(i)) {
((TextView) childViews).setText("Movie "
+ i);
}
}
}
}
}

working with canvas : The specified child already has a parent. You must call removeView() on the child's parent first

I visit so many solutions regarding this issue but can't catch it clearly .When ever I run the project first time it works perfectly but when I run it second time then it fire this error in logCat
The specified child already has a parent. You must call removeView() on the child's parent first
where is the error in that code segment ?where should I change in code. any suggestion is acceptable .Thanks in advance ..
Main.java
public class MainActivity extends Activity {
List<PieDetailsItem> piedata = new ArrayList<PieDetailsItem>(0);
EditText edt3;
Button btnChart;
public String s15;
public String[] strArray;
public ImageView mImageView ;
public LinearLayout finalLayout ;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
finalLayout = (LinearLayout) findViewById(R.id.pie_container);
mImageView = new ImageView(this);
edt3 = (EditText) this.findViewById(R.id.editText1);
btnChart = (Button) findViewById(R.id.button1);
btnChart.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
/*if(mImageView != null) {
finalLayout.removeView(mImageView);
}
else {*/
s15 = edt3.getText().toString();
/*System.out.println("value 1 is --->"+s10);
System.out.println("value 2 is --->"+s12);*/
System.out.println("value 3 is --->"+s15);
String domain = s15;
strArray = domain.split("\\,");
for (String str : strArray) {
System.out.println(str);
}
// }
openChart();
}
});
}
private void openChart(){
Integer[] items = new Integer[strArray.length];
//double[] distribution = new double[strArray.length];
for (int i = 0; i < items.length; i++) {
items[i] = Integer.parseInt(strArray[i]);
System.out.println("xxxxxx"+items[i]);
}
PieDetailsItem item;
int maxCount = 0;
int itemCount = 0;
// int items[] = { 20, 40, 10, 15, 5 };
int colors[] = { -6777216, -16776961, -16711681, -12303292, -7829368 };
// String itemslabel[] = { " vauesr ur 100", " vauesr ur 200",
// " vauesr ur 300", " vauesr ur 400", " vauesr ur 500" };
for (int i = 0; i < items.length; i++) {
itemCount = items[i];
item = new PieDetailsItem();
item.count = itemCount;
// item.label = itemslabel[i];
item.color = colors[i];
piedata.add(item);
maxCount = maxCount + itemCount;
}
int size = 200;
int BgColor = 0xffa11b1;
Bitmap mBaggroundImage = Bitmap.createBitmap(size, size,
Bitmap.Config.ARGB_8888);
View_PieChart piechart = new View_PieChart(this);
piechart.setLayoutParams(new LayoutParams(size, size));
piechart.setGeometry(size, size, 2, 2, 2, 2, 2130837504);
piechart.setSkinparams(BgColor);
piechart.setData(piedata, maxCount);
piechart.invalidate();
piechart.draw(new Canvas(mBaggroundImage));
piechart = null;
//ImageView mImageView = new ImageView(this);
mImageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT));
mImageView.setBackgroundColor(BgColor);
mImageView.setImageBitmap(mBaggroundImage);
//LinearLayout finalLayout = (LinearLayout) findViewById(R.id.pie_container);
finalLayout.addView(mImageView);
}
}
You're adding mImageView to the layout multiple times. A view can only be part of 1 ViewGroup. You need to either add it only once, or create a second ImageView if you really want 2 of them in the layout.

converting from a string separated by commas to an array

I have been working on saving 4 String arrays to sharedpreference. Currently I am breaking the array down in to a string separating the pieces by a comma. When I go to the string, it does save the pieces accurately as it should; however, when I "load" the data and convert it back to an array, it's coming up empty (not null). I am unable to determine how I should fix this to pull my array back. Below is my Activity:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.debtlist);
String[] debtName = new String[10];
String[] debtAmount = new String[10];
String[] debtRate = new String[10];
String[] debtPayment = new String[10];
int counter = 0;
SharedPreferences sharedPref= getSharedPreferences("chaosdatasnowball", 0);
String tempDebtNames = sharedPref.getString("debtNames", "");
debtName = convertStringToArray(tempDebtNames);
Bundle extras = getIntent().getExtras();
int trigger = 0;
for (int i=0;i<counter || i==counter;i++)
{
if (debtName[i] == null && extras != null && trigger == 0)
{
debtName[i] = extras.getString("debtName");
debtAmount[i] = extras.getString("debtAmount");
debtRate[i] = extras.getString("debtRate");
debtPayment[i] = extras.getString("debtPayment");
trigger = 1;
counter++ ;
}
}
TableLayout tl = (TableLayout) findViewById(R.id.debtListTableView);
for (int i=0;i<counter || i==counter;i++)
{
if (debtName[i] != null)
{
TableRow tr = new TableRow(this);
TextView tv0 = new TextView(this);
TextView tv1 = new TextView(this);
TextView tv2 = new TextView(this);
TextView tv3 = new TextView(this);
TableRow.LayoutParams trlp = new TableRow.LayoutParams();
tv0.setLayoutParams(new LayoutParams(0, LayoutParams.MATCH_PARENT, 0.25f));
tv1.setLayoutParams(new LayoutParams(0, LayoutParams.MATCH_PARENT, 0.25f));
tv2.setLayoutParams(new LayoutParams(0, LayoutParams.MATCH_PARENT, 0.25f));
tv3.setLayoutParams(new LayoutParams(0, LayoutParams.MATCH_PARENT, 0.25f));
trlp.span = 3;
tr.setLayoutParams(trlp);
tv0.setText("" + debtName[i]);
tv1.setText("" + debtAmount[i]);
tv2.setText("" + debtPayment[i]);
tv3.setText("" + i);
tr.addView(tv0);
tr.addView(tv1);
tr.addView(tv2);
tr.addView(tv3);
tl.addView(tr);
}
}
SharedPreferences.Editor editor= sharedPref.edit();
String debtNames = convertArrayToString(debtName, counter);
editor.putString("debtNames", debtNames).commit();
TextView disp = (TextView) findViewById(R.id.dispAdditionalAmount);
disp.setText("" + debtNames); //This is how I confirm that the convertArrayToString is functioning properly
}
public static String convertArrayToString(String[] array, int stop){
String str = "";
for (int i = 0;i<stop; i++) {
str = str+array[i];
// Do not append comma at the end of last element
if(i<stop-1){
str = str+",";
}
}
return str;
}
public static String[] convertStringToArray(String str){
String[] arr = str.split(",");
return arr;
}
You do:
String tempDebtNames = sharedPref.getString("debtNames", "");
debtName = convertStringToArray(tempDebtNames);
It is possible that "debtNames" key does not exist. (It returns "" in this case).
Think about first time the app is run. The key will not exist. Therefore, you should convertStringToArray only if !tempDebtNames.equals(""). If key doesn't exist then proceed with empty values..

Why getView() of BaseAdapter showing image multiple times?

I'm using the following code to make a custom listview. I have to show image dynamically, so all the images are added to this in Linearlayout. The problem is that these dynamic images add multiple times. Below is the code of my getView().
LinearLayout fbpiclayout = null;
if (convertView == null)
vi = inflater.inflate(R.layout.popular_event_list, null);
fbpiclayout = (LinearLayout) vi
.findViewById(R.id.fbpic_layout);
ArrayList<String> list= mDbManager
.getAllValuesComingSoonFriendList(facebookEventList
.get(position).getEventId());
int height = 0;
for(int i=0;i<list.size();i++)
{
if(i<3)
{
String friendPics = "http://graph.facebook.com/"
+ list.get(i)
+ "/picture?type=large";
Log.d("Friends","list no "+i+" "+mDbManager
.getFacebookFriendName(list.get(i)));
ImageView fbFriendimage = new ImageView(getActivity());
LinearLayout.LayoutParams vp = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
vp.setMargins(3, 0, 3, 3);
fbFriendimage.setLayoutParams(vp);
fbFriendimage.setAdjustViewBounds(true);
fbFriendimage.getLayoutParams().height = height;
fbFriendimage.getLayoutParams().width = width_iv;
fbFriendimage.setScaleType(ImageView.ScaleType.CENTER_CROP);
// image.setImageBitmap(bm);
imageLoader.DisplayImage(friendPics, fbFriendimage);
fbpiclayout.addView(fbFriendimage, vp);
}
}
Kindly suggest me on that issue.
Thanks in Advance.
Try the following code:
LinearLayout fbpiclayout = null;
if (convertView == null)
vi = inflater.inflate(R.layout.popular_event_list, null);
fbpiclayout = (LinearLayout) vi
.findViewById(R.id.fbpic_layout);
//if the convertView was not null it would have the child view you added the
// last time liner layout was used. So remove the added child view.
fbpiclayout.removeAllViews();
ArrayList<String> list= mDbManager
.getAllValuesComingSoonFriendList(facebookEventList
.get(position).getEventId());
int height = 0;
for(int i=0;i<list.size();i++)
{
if(i<3)
{
String friendPics = "http://graph.facebook.com/"
+ list.get(i)
+ "/picture?type=large";
Log.d("Friends","list no "+i+" "+mDbManager
.getFacebookFriendName(list.get(i)));
ImageView fbFriendimage = new ImageView(getActivity());
LinearLayout.LayoutParams vp = new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
vp.setMargins(3, 0, 3, 3);
fbFriendimage.setLayoutParams(vp);
fbFriendimage.setAdjustViewBounds(true);
fbFriendimage.getLayoutParams().height = height;
fbFriendimage.getLayoutParams().width = width_iv;
fbFriendimage.setScaleType(ImageView.ScaleType.CENTER_CROP);
// image.setImageBitmap(bm);
imageLoader.DisplayImage(friendPics, fbFriendimage);
fbpiclayout.addView(fbFriendimage, vp);
}
}
EDIT1: Try to use smart image view http://loopj.com/android-smart-image-view/ to improve performance....
don't use that loop. Put that list's size in getCount(). It will work properly

Dynamically created TableRow and then RelativeLayout not showing

I am iterating through the results of a query creating RelativeLayouts in TableRows. If I try to set the LayoutParams for the RelativeLayout then nothing appears and get no errors. If I don't then everything appears but with the layout being set to WRAP_CONTENT. I have tried several example and can not get it to work. Below is my code:
TableLayout tblItems = (TableLayout) findViewById(R.id.tblItems);
// Fields from the database (projection)
String[] projection = new String[] { ItemsTable.ITEM_ID,
ItemsTable.ITEM_NAME,
ItemsTable.ITEM_PRICE,
ItemsTable.ITEM_PICTURE };
Cursor cursor = getContentResolver().query(ItemsTable.CONTENT_URI, projection, null, null, null);
startManagingCursor(cursor);
// Establish the item mapping
// String[] columns = new String[] {"name", "price"};
// int[] to = new int[] {R.id.tv_description, R.id.tv_price};
// adapter = new SimpleCursorAdapter(this, R.layout.item_list_select, cursor, columns, to, 0);
// lvSelectItems.setAdapter(adapter);
/*
adapter.setViewBinder(new SimpleCursorAdapter.ViewBinder() {
public boolean setViewValue(View view, Cursor cursor, int columnIndex) {
if(columnIndex == cursor.getColumnIndexOrThrow(OrderDetailTable.ORDERDETAIL_PRICE)) {
// String createDate = aCursor.getString(aColumnIndex);
// TextView textView = (TextView) aView;
// textView.setText("Create date: " + MyFormatterHelper.formatDate(getApplicationContext(), createDate));
double total = cursor.getDouble(columnIndex);
TextView textView = (TextView) view;
textView.setText("$" + String.format("%.2f",dRound(total, 2)));
return true;
}
return false;
}
});
*/
// tblItems
int totalRows = 0;
int tcolumn = 1;
int numItems = cursor.getCount();
double tempRow = numItems / 2;
if (numItems > 0) {
itemsFound = true;
} else {
itemsFound = false;
}
long iPart; // Integer part
double fPart; // Fractional part
boolean ifFirst = true;
// Get user input
iPart = (long) tempRow;
fPart = tempRow - iPart;
if (fPart > 0) {
totalRows = (int) (iPart + 1);
} else {
totalRows = (int) iPart;
}
TableRow row = null;
cursor.moveToFirst();
while (cursor.isAfterLast() == false)
{
// tblItems // TableLayout
// TableRow
// RelativeLayout
// ImageView
// TextView
// TextView
if (ifFirst) {
// create a new TableRow
row = new TableRow(this);
ifFirst = false;
}
// Creating a new RelativeLayout
RelativeLayout relativeLayout = new RelativeLayout(this);
// Defining the RelativeLayout layout parameters.
// In this case I want to fill its parent
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rlp.setMargins(5, 5, 5, 5);
relativeLayout.setPadding(5, 5, 5, 5);
relativeLayout.setBackgroundResource(R.drawable.grpbx_item);
row.addView(relativeLayout, rlp);
// add text view
ImageView imgPic = new ImageView(this);
imgPic.setBackgroundResource(R.drawable.takepic);
imgPic.setPadding(0, 0, 0, 0);
relativeLayout.addView(imgPic);
// add text view
TextView tvName = new TextView(this);
String name = cursor.getString(cursor.getColumnIndexOrThrow(ItemsTable.ITEM_NAME));
tvName.setText("" + name);
// Defining the layout parameters of the TextView
RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
lp.addRule(RelativeLayout.CENTER_IN_PARENT);
// RelativeLayout.
// Setting the parameters on the TextView
tvName.setLayoutParams(lp);
relativeLayout.addView(tvName);
// add text view
double iPrice = cursor.getDouble(cursor.getColumnIndexOrThrow(ItemsTable.ITEM_PRICE));
TextView tvPrice = new TextView(this);
tvPrice.setText("$" + String.format("%.2f",dRound(iPrice, 2)));
relativeLayout.addView(tvPrice);
tcolumn++;
numItems--;
if (tcolumn == 3) {
// add the TableRow to the TableLayout
tblItems.addView(row,new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
// create a new TableRow
row = new TableRow(this);
tcolumn = 1;
} else {
if (numItems == 0) {
// add the TableRow to the TableLayout
tblItems.addView(row,new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
}
}
// Move to the next record
cursor.moveToNext();
}
}
If I try to set the layout params for the relativeLayout then nothing
appears and get no errors. If I don't then everything appears but with
the layout being set to wrapcontent.
You use the wrong LayoutParams for the RelativeLayout. You use:
RelativeLayout.LayoutParams rlp = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
row.addView(relativeLayout, rlp);
but as the parent of that RelativeLayout is a TableRow you must use TableRow.LayoutParams:
TableRow.LayoutParams rlp = new TableRow.LayoutParams(
TableRow.LayoutParams.FILL_PARENT,
TableRow.LayoutParams.WRAP_CONTENT);
row.addView(relativeLayout, rlp);

Categories

Resources