I have a custom adapter for a listview and here is the getView method;
#Override
public View getView(int i, View view, ViewGroup viewGroup) {
LayoutInflater inflater = (LayoutInflater) JourneyPlannerActivity.this
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View rowView = inflater.inflate(R.layout.journey_planner_route_detail, viewGroup, false);
LinearLayout layout = (LinearLayout) rowView.findViewById(R.id.journey_planner_detail_detail_main_id);
JourneyPlannerRoute r = m_Routes.get(i);
String directions = "";
for(int j=0 ; j < r.getRoutes().size() ; j++){
ImageView image = new ImageView(JourneyPlannerActivity.this);
String transportMethod = r.getRoutes().get(j).getMeansOfTransport();
if(transportMethod.equals("Train"))
image.setImageResource(R.drawable.network_rail_logo);
else if(transportMethod.equals("Subway"))
image.setBackgroundResource(R.drawable.roundel_tube);
else if(transportMethod.equals("Bus"))
image.setBackgroundResource(R.drawable.bus);
else if(transportMethod.equals("Walk"))
image.setBackgroundResource(R.drawable.walking);
image.setVisibility(View.VISIBLE);
layout.addView(image);
//directions += r.getRoutes().get(j).getMeansOfTransport()+",";
}
directions += " "+r.getDuration();
TextView tv = (TextView) rowView.findViewById(R.id.journey_planner_detail_main_text_view);
tv.setText(directions);
return rowView;
After going through the debug it seems the imageviews are being added to the layout but they're just not appearing on the screen;
I had a feeling it was due to not picking up the correct layout but it seems as though it is?!
Here is the xml file for the row;
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:id="#+id/journey_planner_detail_detail_main_id">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#drawable/bus_small"/>
<TextView
android:id="#+id/journey_planner_detail_main_text_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
Instead of creating new Image view just call rowView.findViewById(R.id.image_id); (you'll have to add id to the xml).
The actual bug is with the TextView. It is set to fill_parent causing the newly added ImageView to appear to the right of the visible screen. You can change this by changind the TextView width to wrap_content. However, using the ImageView defined in xml layout is better.
Related
I have a GridView adapter(For gallery used).
What i want is to put Image(Check Image) when the photo is clicked.
But I am unable to do that with this code.
#Override
public View getView(final int position, View convertView, ViewGroup parent) {
cbClicked = false;
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Activity.LAYOUT_INFLATER_SERVICE);
View view = inflater.inflate(R.layout.imagelayout, parent, false);
final CheckBox cb = (CheckBox) view.findViewById(R.id.name);
final ImageView img = (ImageView) view.findViewById(R.id.img);
final LinearLayout imgTop = (LinearLayout) view.findViewById(R.id.imgTop);
ImageView img2 = new ImageView(ActivityReviewUpload.this);
img2.setImageResource(R.drawable.ic_my_loc);
imgTop.addView(text);
return view;
}
And for my XML is this.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/imgTop"
android:layout_width="match_parent"
android:layout_height="120dp">
<ImageView
android:id="#+id/img"
android:layout_width="match_parent"
android:layout_height="120dip"
android:background="#color/colorBlack"
android:padding="2dp" />
</LinearLayout>
<CheckBox
android:id="#+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
This is an example of what I'm doing.
In this example it's number,
what I'm doing is i will put just CHECK in the selected images.
The image is not showing.
what am i doing wrong in this part?
thanks
There's some problem with your BaseAdapter:
You should use ViewHolder or ReyclerView with GridLayoutManager to avoid laggy when scrolling your ListView.
Look at this block of code:
ImageView img2 = new ImageView(ActivityReviewUpload.this);
img2.setImageResource(R.drawable.ic_my_loc);
imgTop.addView(text);
Above code will be called everytime you sroll your ListView. Therefore, you always add new ImageView to each row when scrolling. You should remove it.
How to achieve what you want? Do it as below:
// declare selectedPosition = -1 in your `Adapter`
// in your get view added below code:
img.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
selectedPosition = position;
notifyDataSetChanged();
}
});
cb.setChecked(selectedPosition == position? true: false);
Those code will change checkbox state every time you click to your image.
I want to make my own custom "progress bar". I do this by drawing to linear layouts, each with a different color. After that I want to assign a width to each of them to make it look as a progress bar. The thing I am having right now:
XML file of an item of my CustomAdapter (in Gridview):
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#33c2bd" >
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lineScore"
android:layout_width="20dp"
android:layout_height="2dp"
android:background="#eef05e"
android:paddingLeft="20dp"
android:paddingTop="0dp"
android:paddingBottom="20dp"
android:layout_below="#+id/tvLevelScore"/>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/lineScoreTotal"
android:layout_width="20dp"
android:layout_height="2dp"
android:background="#0d7975"
android:paddingRight="20dp"
android:paddingTop="0dp"
android:paddingBottom="20dp"
android:layout_below="#+id/tvLevelScore"
android:layout_toRightOf="#+id/lineScore"/>
</RelativeLayout>
Then in the CustomAdapter class under the getView method I am trying to set the lineScoreTotal to 80% of the width of the item:
double viewWidth = (double) mView.getWidth();
int widthScoreBar = (int) (viewWidth * 0.8);
LinearLayout ln = (LinearLayout) mView.findViewById(R.id.lineScoreTotal);
ln.layout(0, 2, widthScoreBar, -1);
However, it is doing nothing... Am I applying the wrong code to set the width? Or is my idea of using LinearLayout to draw those "bars" maybe the wrong thing to do?
EDIT getView method:
#Override
public View getView(int position, View v, ViewGroup parent) {
View mView = v;
if (mView == null) {
LayoutInflater vi = (LayoutInflater) getContext().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
mView = vi.inflate(R.layout.levelselector_item, null);
}
TextView level = (TextView) mView.findViewById(R.id.tvLevel);
TextView levelScore = (TextView) mView.findViewById(R.id.tvLevelScore);
if (mView != null) {
level.setText(Integer.toString(getItem(position).getLevel()));
loadDataBase();
int correctAnswers = myDbHelper.getCorrectAnswers(getItem(position).getLevel());
correctAnswersPrev = 0;
correctAnswersPrev = myDbHelper.getCorrectAnswersPrev(getItem(position).getLevel());
String correct = Integer.toString(correctAnswers);
levelScore.setText(correct + "/60");
level.setTypeface(font);
levelScore.setTypeface(font);
LinearLayout ln = (LinearLayout) mView.findViewById(R.id.lineScoreTotal);
ln.setLayoutParams(new FrameLayout.LayoutParams(10, 10));
}
return mView;
}
Try either way
Without Gravity
ln.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT));
Or with gravity
ln.setLayoutParams(new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.FILL_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT,1f));
ln.setLayoutParams(new
LayoutParams(widthScoreBar,LayoutParams.WRAP_CONTENT));
Try setting using LayoutParams.
<?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" >
<ImageView
android:id="#+id/venueImage"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>
I have an ordinary listview and a custom adapter using the xml above for the row.
I will only have 3 rows, but I want those 3 rows to have equal heights to fit the height of the screen's resolution. At the moment I don't even know how to set the height of the rows because setting the LinearLayout's height doesnt do anything.
You can set the height of your ImageView to get what you want. To set it programmatically, you can do this on the getView() of your custom adapter:
public View getView(int position, View convertView, ViewGroup parent) {
View cv = convertView;
if (convertView == null) {
cv = inflater.inflate(R.layout.listview_item, null);
}
ImageView venueImage = (ImageView) cv.findViewById(R.id.venueImage);
LinearLayout.LayoutParams vi_params = new LinearLayout.LayoutParams(LayoutParams.FILL_PARENT, (int)(screenHeight*0.33);
venueImage.setLayoutParams(vi_params);
return cv;
}
You can get the screen height by adding this code on your main activity:
int screenHeight = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getHeight();
I have a layout for a view -
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0px"
android:orientation="vertical">
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/items_header"
style="#style/Home.ListHeader" />
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/items_none"
android:visibility="gone"
style="#style/TextBlock"
android:paddingLeft="6px" />
<ListView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/items_list" />
</LinearLayout>
What I want to do, is in my main activity with a layout like this
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:padding="0px"
android:id="#+id/item_wrapper">
</LinearLayout>
I want to loop through my data model and inject multiple views consisting of the first layout into the main layout. I know I can do this by building the controls completely within the code, but I was wondering if there was a way to dynamically build the views so that I can continue using a layout instead of putting everything in code.
Use the LayoutInflater to create a view based on your layout template, and then inject it into the view where you need it.
LayoutInflater vi = (LayoutInflater) getApplicationContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View v = vi.inflate(R.layout.your_layout, null);
// fill in any details dynamically here
TextView textView = (TextView) v.findViewById(R.id.a_text_view);
textView.setText("your text");
// insert into main view
ViewGroup insertPoint = (ViewGroup) findViewById(R.id.insert_point);
insertPoint.addView(v, 0, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
You may have to adjust the index where you want to insert the view.
Additionally, set the LayoutParams according to how you would like it to fit in the parent view. e.g. with FILL_PARENT, or MATCH_PARENT, etc.
See the LayoutInflater class.
LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
ViewGroup parent = (ViewGroup)findViewById(R.id.where_you_want_to_insert);
inflater.inflate(R.layout.the_child_view, parent);
It looks like what you really want a ListView with a custom adapter to inflate the specified layout. Using an ArrayAdapter and the method notifyDataSetChanged() you have full control of the Views generation and rendering.
Take a look at these tutorials
http://www.softwarepassion.com/android-series-custom-listview-items-and-adapters/
http://developerlife.com/tutorials/?p=327
http://www.androidguys.com/2008/07/14/fancy-listviews-part-one/
To make #Mark Fisher's answer more clear, the inserted view being inflated should be a xml file under layout folder but without a layout (ViewGroup) like LinearLayout etc. inside. My example:
res/layout/my_view.xml
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/i_am_id"
android:text="my name"
android:textSize="17sp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
Then, the insertion point should be a layout like LinearLayout:
res/layout/activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/aaa"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/insert_point"
android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
</RelativeLayout>
Then the code should be
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_shopping_cart);
LayoutInflater inflater = getLayoutInflater();
View view = inflater.inflate(R.layout.my_view, null);
ViewGroup main = (ViewGroup) findViewById(R.id.insert_point);
main.addView(view, 0);
}
The reason I post this very similar answer is that when I tried to implement Mark's solution, I got stuck on what xml file should I use for insert_point and the child view. I used layout in the child view firstly and it was totally not working, which took me several hours to figure out. So hope my exploration can save others' time.
// Parent layout
LinearLayout parentLayout = (LinearLayout)findViewById(R.id.layout);
// Layout inflater
LayoutInflater layoutInflater = getLayoutInflater();
View view;
for (int i = 1; i < 101; i++){
// Add the text layout to the parent layout
view = layoutInflater.inflate(R.layout.text_layout, parentLayout, false);
// In order to get the view we have to use the new view with text_layout in it
TextView textView = (TextView)view.findViewById(R.id.text);
textView.setText("Row " + i);
// Add the text view to the parent layout
parentLayout.addView(textView);
}
i have a complex xml layout which has list views..a row in the list view contains several text fields which are spaced evenly. i am using textview to store the text and then finally add all the items to the row...its working perfectly fine.
but now i have case where in i am not sure, how many text fields i might get from a webservice. therefore i need to create the textview dynamically on run time, populate them and then insert into the list..
is there anyway to declare,add and populate new textview fields on runtime?
or is there is anyway to implement the spacing between the two fields?
result of first call
__________________________
|_____|_____|_____|______|
result of second call
________________________________
|_____|_____|_____|______|______|
I tried implementing the solution that was provided below (Kenny), but for some reason I am unable to add views into the list.. below is my code
public class HeaderAdapter extends ArrayAdapter<Header> {
final Header[] listSymbols;
private TextView textView;
private LinearLayout row;
public HeaderAdapter(Context context, int symResourceID,
Header[] objects) {
super(context, symResourceID, objects);
listSymbols = objects;
}
#Override
public View getView(int position, View convertView, ViewGroup parent) {
LayoutInflater inflater = (LayoutInflater) getContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View row = inflater.inflate(R.layout.header_view, parent, false);
Header headerRec = listSymbols[position];
for(int i = 0 ; i < listSymbols.length;i++){
textView = new TextView(getContext());
textView.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, //Width of the view
ViewGroup.LayoutParams.WRAP_CONTENT));//Height of the view
textView.setId(i);
row.add??
}
}
The main activity that calls this
setContentView(R.layout.main);
headerList.add(new Header("Symbol","Quantity","Price","Price Yesterday","52 Week High","52 Week Low","Change","Days Gain","Days Gain %","Returns"));
Header[] tmpHeaderList = headerList.toArray(new Header[headerList.size()]);
ArrayAdapter<Header> headerAdapter = new HeaderAdapter(this,R.layout.twoway_header_view,tmpHeaderList);
headerListView.setAdapter(headerAdapter);
xml layout file..the main file
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:orientation="vertical">
<HorizontalScrollView android:layout_width="wrap_content"
android:layout_height="wrap_content" android:scrollbars="none"
android:id="#+id/headerHv">
<ListView android:id="#+id/header_listView1"
android:layout_width="fill_parent" android:layout_height="wrap_content"
android:background="#color/white" android:cacheColorHint="#00000000"
android:smoothScrollbar="true" android:scrollbars="none" />
</HorizontalScrollView>
</LinearLayout>
the file in which the template for the row is defined
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"
>
<TextView android:id="#+id/headerList" android:layout_width="80dp"
android:layout_height="wrap_content" android:textColor="#000000"
android:typeface="sans" android:textStyle="normal" />
</LinearLayout>
Here is the way i dynamically generate custom buttons from a list, you could do the same thing with textViews:
//Setup Buttons
layout = (LinearLayout)findViewById(R.id.layoutBars);
int count = lBars.size();
for(int i = 0; i< count;i++){
final Bar b = lBars.get(i);
BarButton button = new BarButton(DDTBars.this, R.drawable.barsmall , b.getName().toUpperCase());
button.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.FILL_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT));
button.setId(i);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
//Run activity passing name of the bar to retrieve data
Intent i = new Intent(DDTBars.this, DDTBar.class);
i.putExtra("name", b.getName());
startActivity(i);
}
});
layout.addView(button);
}
So you could try:
//Setup TextViews
layout = (LinearLayout)findViewById(R.id.mylayout);
int count = myTextList.size();
for(int i = 0; i< count;i++){
TextView txtView = new TextView(this);
txtView.setLayoutParams(new LayoutParams(
ViewGroup.LayoutParams.WRAP_CONTENT, //Width of the view
ViewGroup.LayoutParams.WRAP_CONTENT));//Height of the view
txtView.setId(i);
layout.addView(txtView);
}
You could do it in code. Declare TextView 's in a loop and use RelativeLayout to position them wrt each other.