I want to create a table that the columns'text depends on spinner. Later to add the row, i can color the specified cell. It looks like this : http://tinypic.com/view.php?pic=2j639xf&s=8#.U-mRRpD-Lcs
That example is landscape because i develop it on dekstop, so i want a table like that as portait in android.
The problem is :
1. when i run it on device, the spinner is gone
2. I don't know yet how to color each cell in the table. Or should I make a new question?
Here's my code:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_reservation_schedule);
Spinner spinnerFacility = (Spinner)findViewById(R.id.spinnerFacility);
ArrayList<String> alTop = getTimeTableColumnTop((int)spinnerFacility.getSelectedItemId());
String[] column = alTop.toArray(new String[alTop.size()]);
ArrayList<String> alLeft = getTimeTableColumnLeft();
String[] row = alLeft.toArray(new String[alLeft.size()]);
int rl=row.length+1; int cl=column.length+1;
Log.d("--", "R-Lenght--"+rl+" "+"C-Lenght--"+cl);
ScrollView sv = new ScrollView(this);
TableLayout tableLayout = createTableLayout(row, column,rl, cl);
HorizontalScrollView hsv = new HorizontalScrollView(this);
hsv.addView(tableLayout);
sv.addView(hsv);
setContentView(sv);
}
private ArrayList<String> getTimeTableColumnTop(int facilitySelectedIndex)
{
ArrayList<String> timeTableColumnTop = new ArrayList<String>();
if(facilitySelectedIndex == 0)
{
timeTableColumnTop.add("Discuss Room 1");
timeTableColumnTop.add("Discuss Room 2");
timeTableColumnTop.add("Discuss Room 3");
}else
{
timeTableColumnTop.add("Pri-View 1");
timeTableColumnTop.add("Pri-View 2");
timeTableColumnTop.add("Pri-View 3");
timeTableColumnTop.add("Pri-View 4");
timeTableColumnTop.add("Pri-View 5");
}
return timeTableColumnTop;
}
private ArrayList<String> getTimeTableColumnLeft()
{
ArrayList<String> timeTableColumnLeft = new ArrayList<String>();
for(int i = 8 ; i<17; i++)
{
timeTableColumnLeft.add(i+":00");
}
return timeTableColumnLeft;
}
For the function createTableLayout(row,column,rl,cl); i use the code from http://www.prandroid.com/2014/05/creating-table-layout-dynamically-in.html
The activity_reservation_schedule.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="#string/reservation_spinner_facility_prompt"/>
<Spinner
android:id="#+id/spinnerFacility"
android:prompt="#string/reservation_spinner_facility_prompt"
android:entries="#array/reservation_facility_entries"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
Here is strings.xml:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ReservationTab(Schedule)</string>
<string name="reservation_spinner_facility_prompt">Pick a facility</string>
<string-array name="reservation_facility_entries">
<item>Discussion Room</item>
<item>Private Viewing</item>
</string-array>
</resources>
Note : i'm new on Android, i'm using eclipse. This is my first post here, please excuse my english. Any suggestion is appreciated, thanks.
Few points:
If i understood you correctly,
You need to "add" the scroll view to your root view linearlayout.
Add a Custom Item Selected listener for Spinner and change layout depending on selection
e.g
Sample Code:
#Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_main);
ll = (LinearLayout)findViewById(R.id.ll);
Spinner spinnerFacility = (Spinner)findViewById(R.id.spinnerFacility);
spinnerFacility.setOnItemSelectedListener(new CustomOnItemSelectedListener());
// more of your code.....
ll.addView(sv) // instead of setContentView(sv)
public class CustomOnItemSelectedListener implements OnItemSelectedListener {
public void onItemSelected(AdapterView<?> parent, View view, int pos,long id) {
Toast.makeText(parent.getContext(),
"OnItemSelectedListener : " + parent.getItemAtPosition(pos).toString(),
Toast.LENGTH_SHORT).show();
ll.removeView(sv);
ArrayList<String> alTop = getTimeTableColumnTop(pos);
String[] column = alTop.toArray(new String[alTop.size()]);
ArrayList<String> alLeft = getTimeTableColumnLeft();
String[] row = alLeft.toArray(new String[alLeft.size()]);
int rl=row.length+1; int cl=column.length+1;
Log.d("--", "R-Lenght--"+rl+" "+"C-Lenght--"+cl);
sv = new ScrollView(getApplicationContext());
TableLayout tableLayout = createTableLayout(row, column,rl, cl);
HorizontalScrollView hsv = new HorizontalScrollView(getApplicationContext());
hsv.addView(tableLayout);
sv.addView(hsv);
ll.addView(sv);
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
}
}
Related
I'm currently trying to add a user-defined number of TextViews and EditText to an activity, but can't seem to do it other than hard-coding it by creating a variety of different activities.
The objective of this activity is to take the names of the players, the number of which is relayed by the intent extra from the preceding activity.
I'm trying to add both a TextView saying "Player X: " and an EditText to type the name of the player for each player
I know from this post: How to create a variable number of textviews in android that I have to do this programmatically, however, it does not seem to work for me (the activity remains blank when tested)
I have tried creating a temp LinearLayout to which I add the two views in a for(), still nothing.
Any ideas? Am I on the right track?
Best regards
[EDIT] Code is here :
public class players extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_players);
Bundle extras = new Bundle();
final int numPlayers = extras.getInt("num");
final LinearLayout myLayout = findViewById(R.id.lin_Re);
final ArrayList<Player> players = new ArrayList<>();
int size = numPlayers; // total number of TextViews to add
TextView[] tv = new TextView[size];
TextView temp;
EditText[] et = new EditText[size];
EditText temp2;
LinearLayout temp3;
for (int i = 0; i < size; i++)
{
temp = new TextView(this);
temp2 = new EditText(this);
temp3 = new LinearLayout(this);
temp.setText("Player " + i + " : "); //arbitrary task
// add the textview to the linearlayout
temp3.addView(temp);
temp3.addView(temp2);
tv[i] = temp;
et[i] = temp2;
myLayout.addView(temp3);
}
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
android:id="#+id/lin_Re">
</LinearLayout>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/b_send"/>
</LinearLayout>
There is 2 way to achieve this:
1. Use a RecyclerView [Recommended]
2. Add TextView and EditText ( which is nested in a Horizontal LinearLayout) into a Vertical LinearLayout nested in a ScrollView programmatically
The first solution I describe below is quite simple if you're familiar with RecyclerView or ListView, the second solution (your current track) is a bit tricky but still achievable.
Solution 1:
MainActivity
public class MainActivity extends AppCompatActivity {
RecyclerView mPlayerList;
List<String> mPlayerNames;
PlayerAdapter mAdapter;
EditText mInput;
Button mCreateButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mPlayerNames = new ArrayList<>();
// setup recycler view
mPlayerList = findViewById(R.id.player_list);
mPlayerList.setLayoutManager(new LinearLayoutManager(this));
mAdapter = new PlayerAdapter();
mPlayerList.setAdapter(mAdapter);
// setup input EditText
mInput = findViewById(R.id.input);
// setup Create button
mCreateButton = findViewById(R.id.create_button);
mCreateButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// clear old player names
mPlayerNames.clear();
// read user input: number of player:
String input = mInput.getText().toString();
int numberOfPlayer;
try {
numberOfPlayer = Integer.parseInt(input);
} catch (NumberFormatException e) {
Toast.makeText(MainActivity.this, "Invalid input!!!", Toast.LENGTH_SHORT).show();
return;
}
for (int i = 0; i < numberOfPlayer; ++i) {
mPlayerNames.add("Player #" + (i + 1));
}
// make change on recycler view
mAdapter.notifyDataSetChanged();
// dismiss keyboard
InputMethodManager imm = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mInput.getWindowToken(), 0);
}
});
}
private class PlayerAdapter extends RecyclerView.Adapter<PlayerAdapter.PlayerHolder> {
#Override
public PlayerHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(MainActivity.this).inflate(R.layout.item_layout, parent, false);
return new PlayerHolder(v);
}
#Override
public void onBindViewHolder(PlayerHolder holder, int position) {
holder.bind(mPlayerNames.get(position));
}
#Override
public int getItemCount() {
return mPlayerNames.size();
}
public class PlayerHolder extends RecyclerView.ViewHolder {
TextView mPlayerLabel;
EditText mPlayerName;
public PlayerHolder(View itemView) {
super(itemView);
mPlayerLabel = itemView.findViewById(R.id.player_label);
mPlayerName = itemView.findViewById(R.id.player_name);
}
public void bind(String playerName) {
mPlayerLabel.setText(playerName);
mPlayerName.setHint("Name of " + playerName);
}
}
}
}
The sample project can be found here:
https://github.com/raiytu4/stackcase004
I am fetching some content from an API which I need to show in android app. The content comes in JSON format, which looks something like this:
{
"items": [
{
"catalog_items": [
{
"date": "23-01-2015",
"content": "Trimmer 1 description",
"name": "Trimmer 1"
},
{
"date": "25-01-2015",
"content": "Trimmer 2 description",
"name": "Trimmer 2"
}
.....
.....
],
"item_category": "Trimmer"
},
{
"catalog_items": [
{
"date": "13-08-2014",
"content": "Shirt description here",
"name": "John Player Shirt"
}
],
"item_category": "Shirts"
},
{
"item_category": "Woolen"
}
],
"pages": [
{
"date": "24-01-2015",
"content": "This is some content about page 1",
"name": "Sample Page title 1"
},
{
"date": "26-01-2015",
"content": "This is some content about page 2",
"name": "Sample Page title 2"
}
]
}
I have to create a dashboard in app which is built up in following manner, based upon above JSON data:
Top Menu
=====================
Trimmers (Gridview)
Trimmer1 Trimmer2
Trimmer3 Trimmer4
======================
Shirts (Gridview)
John Players
======================
Pages (Listview)
Page1
Page2
My Dashboard Fragment fetches this JSON. My Dashboard layout is:
fragment_home.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
</RelativeLayout>
and My Dashboard Activity looks like this:
public class HomeFragment extends Fragment {
.....
.....
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
try {
JSONObject obj = new JSONObject(loadJSONFromAsset("input.json"));
if(obj.has("catagories")) {
JSONArray catag = obj.getJSONArray("items");
for(int i=0; i< catag.length();i++){
JSONObject catitem = catag.getJSONObject(i);
JSONArray posts = catitem.getJSONArray("catalog_items");
for(int j=0;j<posts.length();j++){
JSONObject postitem = posts.getJSONObject(j);
catList.add(postitem.getString("name"));
}
addGridtoLayout(catitem.getString("item_category"),catList);
}
}
} catch (JSONException e){
e.printStackTrace();
}
return rootView;
}
public void addGridtoLayout(String title, ArrayList<String> itemList)
{
RelativeLayout ll = new RelativeLayout(getActivity());
RelativeLayout.LayoutParams parambs = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
ll.setLayoutParams(parambs);
TextView tv = new TextView(getActivity());
tv.setText(title);
tv.setId(R.id.layout1);
RelativeLayout.LayoutParams lay = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
ll.addView(tv, lay);
GridView gridView= new GridView(getActivity());
gridView.setLayoutParams(new GridView.LayoutParams(GridLayout.LayoutParams.MATCH_PARENT, GridLayout.LayoutParams.MATCH_PARENT));
gridView.setNumColumns(GRID_COL_NUM);
gridView.setAdapter(new HomeGridAdapter(getActivity(), itemList));
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.addRule(RelativeLayout.BELOW, tv.getId());
ll.addView(gridView, params);
mainLayout.addView(ll);
}
This is the code only for items (Gridview).
What I am going is basically wrapping each gridview and the title in a relativelayout. And the relative layouts would appear below the former one, starting from first item.
But gridviews are getting stacked over each other and all items are being shown in a single row.
Is there any method so I can define the relativelayouts of each gridview to appear below the previous one? Also, is there any better approach to achieve this? I mean the basic requirement is to generate dynamic number of gridviews. So is generating layout on the fly is only way to do this?
Thanks for reading this long post.
Well, as I mentioned in comment, I made slightly modified code and that works really awesome. So I am going to elaborate what I did. Maybe it could help someone out.
Since I have to generate multiple sectioned Gridviews, I initially thought of generating tables using TableLayout and adding TableRows to it. Each Tablerow would be holding a RelativeView consiting of:
Item's image (from JSON)
Item's name (from JSON)
So, I initially created this code:
HomeFragment.java
public class HomeFragment extends Fragment {
.....
.....
ArrayList<String> itemList;
private JsonHelper jsonHelper;
private static final int GRID_COL_NUM = 3;
TableRow tbh;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container,false);
TableLayout table = (TableLayout) rootView.findViewById(R.id.tableLayout);
table.setStretchAllColumns(true);
table.setShrinkAllColumns(true);
try {
JSONObject obj = new JSONObject(loadJSONFromAsset("input.json"));
if(obj.has("catagories")) {
JSONArray catag = obj.getJSONArray("items");
for(int i=0; i< catag.length();i++){
JSONObject catitem = catag.getJSONObject(i);
JSONArray items = catitem.getJSONArray("catalog_items");
if(items.length() > 0) {
//Add a Grid Title for this category (span=6, full width)
TableRow tbr = addRowTitle(catitem.getString("cat_name"));
table.addView(tbr); //Add this title row to the table
itemList = new ArrayList<>(); //Hold all items for each category
for(int j=0;j<items.length();j++){
JSONObject singleItem = items.getJSONObject(j);
//I am trying to show only 3 items in a row, so add new row after 3
if(j % 3 == 0){
tbh = addRowGrid(); //add new row and repeat so after 3
table.addView(tbh); //Add this to the table, we will fill items below
}
LinearLayout lnr = new LinearLayout(getActivity());
TableRow.LayoutParams params = new TableRow.LayoutParams(TableRow.LayoutParams.MATCH_PARENT,TableRow.LayoutParams.WRAP_CONTENT);
params.gravity = Gravity.CENTER; //Center the items
lnr.setLayoutParams(params);
lnr.setOrientation(LinearLayout.VERTICAL); //As per your need. worked for me
//Item's Image
ImageView itemImg = new ImageView(getActivity()); itemImg.setImageResource(R.drawable.ic_communities); //Default icon for item
TextView itemLabel = new TextView(getActivity());
itemLabel.setText(singleItem.getString("name"));
itemLabel.setTypeface(Typeface.SERIF, Typeface.BOLD);
lnr.addView(postImg,params);
lnr.addView(postLabel,params);
tbh.addView(lnr); //Now we have image and content, wrap in linear layout and add to the row.
itemList.add(singleItem.getString("name")); //This step is not needed for now. I just wrote this to use this array for other purposes.
}
//I am all confused at this point if I have really closed all of curly braces. Please confirm
}
}
}
} catch (JSONException e){
e.printStackTrace();
}
return rootView;
}
public TableRow addRowGrid()
{
return new TableRow(getActivity());
}
public TableRow addRowTitle(String titleb)
{
TableRow rowTitle = new TableRow(getActivity());
rowTitle.setGravity(Gravity.CENTER_HORIZONTAL);
// title column/row
TextView title = new TextView(getActivity());
title.setText(titleb);
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
title.setGravity(Gravity.CENTER);
title.setTypeface(Typeface.SERIF, Typeface.BOLD);
TableRow.LayoutParams params = new TableRow.LayoutParams();
params.span = 6;
rowTitle.addView(title, params);
return rowTitle;
}
...
...
}
This whole code works for a single Table layout defined in layout:
fragment_home:
<?xml version="1.0" encoding="utf-8"?>
<ScrollView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/card_scrollview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentTop="true">
<RelativeLayout
android:id="#+id/relativeLayout1"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TableLayout
android:id="#+id/tableLayout"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"></TableLayout>
</RelativeLayout>
</ScrollView>
So the whole table is generated on the fly. Worked pretty well. I can attach a click handler to each row to listen, and I might have to set tag for each views to get the clicked item. Its then I thought to more feasible and flexible approach. What if I add the gridview to each row itself, instead of appending LinearLayouts to each TableRows? So, I ended up on modifying my code on this approach:
1. A single TableRow will hold each category title and a second Tablerow will be appended to it, which will hold the gridview.
2. I can now use a Custom Grid Adapter by which I could change layout of each item better, i.e via XML instead of tingling here "on-the-fly" approach.
3. Above point also gained me a clicklistener. So no setting of tag required.
NOTE: The above approach was working as well as below approach is working too (as same). So you can use both
Hence, I create a function that would add title to each category of item and a function to add items to grid, and grid to a row:
HomeFragment.java (gridview version)
public class HomeFragment extends Fragment {
private static final int GRID_COL_NUM = 3;
TableRow tbh;
public HomeFragment(){}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_home, container, false);
TableLayout table = (TableLayout) rootView.findViewById(R.id.tableLayout);
table.setStretchAllColumns(true);
table.setShrinkAllColumns(true);
try {
JSONObject obj = new JSONObject(loadJSONFromAsset("input.json"));
if(obj.has("catagories")) {
JSONArray catag = obj.getJSONArray("catagories");
for(int i=0; i< catag.length();i++) {
JSONObject catitem = catag.getJSONObject(i);
if (catitem.has("items")) {
JSONArray items = catitem.getJSONArray("catalog_items");
if (items.length() > 0) {
//Add row with title catname
TableRow tbr = addRowTitle(catitem.getString("cat_name")); //Add category Name as title
table.addView(tbr); //Same I did previously
ArrayList<String> itemList = new ArrayList<>();
for (int j = 0; j < items.length(); j++) {
JSONObject singleItem = posts.getJSONObject(j);
itemList.add(singleItem.getString("name"));
}
tbh = addGridRow(itemList); //Create Grid of collections and add it to a tablerow
table.addView(tbh); //Add this tablerow to table
}
}
}
}
if(obj.has("pages")) {
JSONArray pages = obj.getJSONArray("pages");
if(pages.length() > 0) {
TableRow tbr = addRowTitle("Pages");
table.addView(tbr);
ArrayList<String> pageList = new ArrayList<>();
for (int i = 0; i < pages.length(); i++) {
JSONObject page = pages.getJSONObject(i);
pageList.add(page.getString("name"));
}
tbh = addGridRow(pageList);
table.addView(tbh);
}
}
} catch (JSONException e){
e.printStackTrace();
}
return rootView;
}
/**
* Now this is a life saver. Gridviews aren't friendly with scrollviews (I might be wrong, but happens with me everytime), especially if generated dynamically. Hence this function calculates height of each item of gridview dynamically and hence sets the total view height adapted from https://stackoverflow.com/a/22555947/1136491
**/
public void setGridViewHeightBasedOnChildren(GridView gridView, int columns) {
ListAdapter listAdapter = gridView.getAdapter();
if (listAdapter == null) {
// pre-condition
return;
}
int totalHeight = 0;
int items = listAdapter.getCount();
int rows = 0;
View listItem = listAdapter.getView(0, null, gridView);
listItem.measure(0, 0);
totalHeight = listItem.getMeasuredHeight();
float x = 1;
if( items > columns ){
x = items/columns;
rows = (int) (x + 1);
totalHeight *= rows;
}
ViewGroup.LayoutParams params = gridView.getLayoutParams();
params.height = totalHeight;
gridView.setLayoutParams(params);
}
public TableRow addGridRow(ArrayList gridItemList)
{
TableRow gridrow = new TableRow(getActivity());
GridView gv = new GridView(getActivity());
TableRow.LayoutParams params = new TableRow.LayoutParams(
TableRow.LayoutParams.WRAP_CONTENT, TableRow.LayoutParams.WRAP_CONTENT);
gv.setLayoutParams(params);
gv.setNumColumns(GRID_COL_NUM); //3 columns grid
gv.setAdapter(new HomeGridAdapter(getActivity(), gridItemList)); //Custom grid adapter I was talking about. See Below
gridrow.addView(gv);
//Thanks for not messing up my gridview inside scrollview
setGridViewHeightBasedOnChildren(gv,GRID_COL_NUM); //3 Columns
return gridrow;
}
//Simply add title above the gridview
public TableRow addRowTitle(String titleb)
{
TableRow rowTitle = new TableRow(getActivity());
rowTitle.setGravity(Gravity.CENTER_HORIZONTAL);
// title column/row
TextView title = new TextView(getActivity());
title.setText(titleb);
title.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 18);
title.setGravity(Gravity.CENTER);
title.setTypeface(Typeface.SERIF, Typeface.BOLD);
TableRow.LayoutParams params = new TableRow.LayoutParams();
params.span = 6;
rowTitle.addView(title, params);
return rowTitle;
}
....
}
Now my custom Adapter
HomeGridAdapter.java
public class HomeGridAdapter extends BaseAdapter {
ArrayList<String> result;
Context context;
private static LayoutInflater inflater=null;
public HomeGridAdapter(Context context, ArrayList<String> itemList) {
// TODO Auto-generated constructor stub
this.result=itemList;
this.context=context;
inflater = ( LayoutInflater )context.
getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
#Override
public int getCount() {
// TODO Auto-generated method stub
return result.size();
}
#Override
public Object getItem(int position) {
// TODO Auto-generated method stub
return position;
}
#Override
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public class Holder
{
TextView tv;
ImageView img;
}
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
Holder holder=new Holder();
View rowView;
//Layout mentioned below
rowView = inflater.inflate(R.layout.home_grid_layout, null);
holder.tv=(TextView) rowView.findViewById(R.id.textView1);
holder.img=(ImageView) rowView.findViewById(R.id.imageView1);
//Item's Text
holder.tv.setText(result.get(position));
//Item's Image
holder.img.setImageResource(R.drawable.ic_launcher);
//A click listener to each gid item
rowView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// TODO Auto-generated method stub
Toast.makeText(context, "You Clicked "+result.get(position), Toast.LENGTH_SHORT).show();
}
});
return rowView;
}
}
home_grid_layout.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="#+id/imageView1"
android:layout_gravity="center"
android:layout_width="88dp"
android:layout_height="88dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:src="#drawable/ic_launcher" />
<TextView
android:id="#+id/textView1"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="15dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:text="TextView" />
</LinearLayout>
So I am currently using Gridview version of the TableLayout. I might have achieved what I wanted, but I would really welcome any suggestions here. Hope this answer serves someone a great help.
Thanks for bearing this long.
I have a TableLayout that has it's rows populated dinamically via database. On each row, I'm trying to make a OnLongClickListener() to show a ListView from a different .xml than my activity_product.xml. Here is relevant part of code from my activity_product.xml:
<TableLayout
android:id="#+id/productsTable"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingLeft="3dip"
android:paddingRight="3dip"
android:shrinkColumns="1"
android:weightSum="1"
android:stretchColumns="*">
</TableLayout>
And here is my edit_or_delete_menu.xml with the ListView
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ListView
android:id="#+id/edirOrDeleteMenu"
android:layout_height="wrap_content"
android:layout_width="match_parent">
</ListView>
</LinearLayout>
And here is the relevant part of the code I use to populate the rows and attempt to show the ListView:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_product);
new LoadProductsTableContent().execute();
}
private class LoadProductsTableContent extends AsyncTask<Void, Void, Integer> {
private TableLayout productsTable = (TableLayout) findViewById(R.id.productsTable);
private TableRow labelRow = (TableRow) findViewById(R.id.productLabelsRow);
#Override
protected Integer doInBackground(Void... params)
{
int result=1;
// Usado para acessarmos as views da thread pai
// http://stackoverflow.com/questions/5161951/android-only-the-original-thread-that-created-a-view-hierarchy-can-touch-its-vi
runOnUiThread(new Runnable() {
#Override
public void run() {
// Create a new row to be added
TableRow tr = new TableRow(ProductActivity.this);
/* CODE TO SET ROW PROPERTIES AND CONTENT */
// Row click listener
tr.setOnLongClickListener(new OnLongClickListener() {
#Override
public boolean onLongClick(View v) {
// TODO Auto-generated method stub
onClickRow(v);
return false;
}
});
// Add row to TableLayout
productsTable.addView(tr);
}
});
return result;
}
private void onClickRow(View v) {
String editText = getResources().getString(R.string.menuEditOption);
String deleteText = getResources().getString(R.string.menuDeleteOption);
// Inflating to display ListView
LayoutInflater inflater = (LayoutInflater) ProductActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.edir_or_delete_menu, null);
edirOrDeleteMenu = (ListView) v.findViewById(R.id.edirOrDeleteMenu);
String[] options = new String[]{editText, deleteText};
ArrayAdapter<String> adapter = new ArrayAdapter<String>(ProductActivity.this, android.R.layout.simple_list_item_1, android.R.id.text1, options);
edirOrDeleteMenu.setAdapter(adapter);
}
The code compiles and no error happens when executing this code, but my ListView doesn't show up. What am I missing here?
Thanks in advance.
I guess the problem is here:
LayoutInflater inflater = (LayoutInflater) ProductActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
v = inflater.inflate(R.layout.edir_or_delete_menu, null);
You inflated a view, but didn't add it anywhere. Add it as a child view to the view which is supposed to be its parent.
Also you need to declare and assign the inflater.inflate(...) result to another variable instead of v. The v is the view, which is clicked. Create a new variable and then add it as a child, as I wrote above.
Something like this:
LayoutInflater inflater = (LayoutInflater) ProductActivity.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.edir_or_delete_menu, null);
v.addView(view);
I have spinner which populates from database:
catSpinner = (Spinner) findViewById(R.id.spinner1);
cursor = dataAdapter.getAllCategory();
startManagingCursor(cursor);
String[] from = new String[] { DataAdapter.CATEGORY_COL_NAME };
int[] to = new int[] { android.R.id.text1 };
SimpleCursorAdapter catAdapter = new SimpleCursorAdapter(this,
android.R.layout.simple_spinner_dropdown_item, cursor, from,to, 0);
catAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
catAdapter.notifyDataSetChanged();
catSpinner.setAdapter(catAdapter);
And I want to call AlertDialog when I select last item(Add new category...).
After I added new category I want that "item(Add new category...)" was the last again.
How I can do this?
You SHOULD NOT call OnItemClickListener on a spinner. A Spinner does not support item click events. Calling this method will raise an Exception. Check this.
You can apply OnItemSelectedListener instead.
Edit :
spinner.setOnItemSelectedListener(new OnItemSelectedListener()
{
public void onItemSelected(AdapterView<?> parent, View view, int position, long id)
{
String selectedItem = parent.getItemAtPosition(position).toString();
if(selectedItem.equals("Add new category"))
{
// do your stuff
}
} // to close the onItemSelected
public void onNothingSelected(AdapterView<?> parent)
{
}
});
As far as adding "Add new category" to the end of the list is concerned, I think you should better go for custom adapter in which after adding all your items, you can add that constant ("Add new category") to end of array so that it should come last always.
Hook to OnItemClickListener of Spinner. Then check whether the selected item is "Add new category".
If yes, show the dialog to add the new item.
While adding the new item,
Remove the last item "Add new category".
Add the new category entered.
Then Add the item "Add new category" again.
This will make the "Add new category" item as last one.
Code Sample :
layout main.xml :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="10" >
<Spinner
android:id="#+id/cmbNames"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
layout spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Activity class :
public class MainActivity extends Activity {
private static final String NAME = "name";
private static final String ADD_NEW_ITEM = "Add New Item";
private SimpleAdapter adapter;
private Spinner cmbNames;
private List<HashMap<String, String>> lstNames;
private int counter;
private OnItemSelectedListener itemSelectedListener = new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
HashMap<String, String> map = lstNames.get(arg2);
String name = map.get(NAME);
if (name.equalsIgnoreCase(ADD_NEW_ITEM)) {
lstNames.remove(map);
counter++;
addNewName(String.valueOf(counter));
addNewName(ADD_NEW_ITEM);
adapter.notifyDataSetChanged();
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
populateList();
cmbNames = (Spinner) findViewById(R.id.cmbNames);
adapter = new SimpleAdapter(this, lstNames, R.layout.spinner_item,
new String[] { NAME }, new int[] { R.id.tvName });
cmbNames.setAdapter(adapter);
cmbNames.setOnItemSelectedListener(itemSelectedListener);
}
private void populateList() {
lstNames = new ArrayList<HashMap<String, String>>();
addNewName("abc");
addNewName("pqr");
addNewName("xyz");
addNewName(ADD_NEW_ITEM);
}
private void addNewName(String name) {
HashMap<String, String> map = new HashMap<String, String>();
map.put(NAME, name);
lstNames.add(map);
}
}
I have created a Spinner that is populated with an ArrayList. I want to dynamically add values to the ArrayList, so the the Spinner populates dynamically. However, when I try to add values to my ArrayList, I get a NullPointerException.
What am I missing? Do I have to reset the adapter before amending the ArrayList?
Here is my code:
My spinner, arraylist, and adapter:
deleteselection = (Spinner)view.findViewById(R.id.deletespinner);
portfoliosdelete = new ArrayList<String>();
portfoliosdelete.add("Select Portfolio");
adapterdeletetype = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item,portfoliosdelete){
#Override
public View getDropDownView(int position, View convertView, ViewGroup parent)
{
View v = null;
// If this is the initial dummy entry, make it hidden
if (position == 0) {
TextView tv = new TextView(getContext());
tv.setHeight(0);
tv.setVisibility(View.GONE);
v = tv;
}
else {
// Pass convertView as null to prevent reuse of special case views
v = super.getDropDownView(position, null, parent);
}
// Hide scroll bar because it appears sometimes unnecessarily, this does not prevent scrolling
parent.setVerticalScrollBarEnabled(false);
return v;
}
};
adapterdeletetype.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
deleteselection.setAdapter(adapterdeletetype);
My code to dynamically update spinner:
else if(users.contains(usernull)){
pn1 = enterportfolioname.getText().toString();
user1 = new PortfolioRecord(pn1, "someemail#gmail.com");
users.remove(usernull);
users.add(user1);
portfoliosdelete.add(pn1); // <-- This causes a null pointer exception
adapterdeletetype.notifyDataSetChanged();
portfoliolist.invalidateViews();
Use the code below. This code will add a new item when the user selects and add a new item from the spinner.
Code sample:
layout main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:weightSum="10" >
<Spinner
android:id="#+id/cmbNames"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
layout spinner_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/tvName"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
Activity class:
public class MainActivity extends Activity {
private static final String NAME = "name";
private static final String ADD_NEW_ITEM = "Add New Item";
private SimpleAdapter adapter;
private Spinner cmbNames;
private List<HashMap<String, String>> lstNames;
private int counter;
private OnItemSelectedListener itemSelectedListener = new OnItemSelectedListener() {
#Override
public void onItemSelected(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
HashMap<String, String> map = lstNames.get(arg2);
String name = map.get(NAME);
if (name.equalsIgnoreCase(ADD_NEW_ITEM)) {
lstNames.remove(map);
counter++;
addNewName(String.valueOf(counter));
addNewName(ADD_NEW_ITEM);
adapter.notifyDataSetChanged();
}
}
#Override
public void onNothingSelected(AdapterView<?> arg0) {
// TODO Auto-generated method stub
}
};
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
populateList();
cmbNames = (Spinner) findViewById(R.id.cmbNames);
adapter = new SimpleAdapter(this, lstNames, R.layout.spinner_item,
new String[] { NAME }, new int[] { R.id.tvName });
cmbNames.setAdapter(adapter);
cmbNames.setOnItemSelectedListener(itemSelectedListener);
}
private void populateList() {
lstNames = new ArrayList<HashMap<String, String>>();
addNewName("abc");
addNewName("pqr");
addNewName("xyz");
addNewName(ADD_NEW_ITEM);
}
private void addNewName(String name) {
HashMap<String, String> map = new HashMap<String, String>();
map.put(NAME, name);
lstNames.add(map);
}
}
Try to call delete on adapterdeletetype instead of the arraylist. If it fails, then please post your logcat output.