Setting width of LinearLayout dynamically? - android

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.

Related

Inflate layout and use its child items

I have a layout where I want to imitate a listview by adding items programmatically one below the other. So I created an .xml for the layout of these items that are something like this:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ll_lista"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="1dp"
android:layout_marginTop="5dp"
android:layout_toLeftOf="#+id/rellay_btn"
android:orientation="vertical" >
<TextView
android:id="#+id/tv_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="1dp"
android:text="Some name"
android:textColor="#3F3F3F"
android:textSize="17sp"
android:textStyle="bold" />
<TextView
android:id="#+id/tv_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/iv_follow"
android:text="Some text"
android:textColor="#3F3F3F"
android:textSize="13sp" />
</LinearLayout>
In the activity I would like to generate n of this layout, fill the textviews with text and also I would like to set an onClickListener on them. n is the size of an array. Please help
Note: Once the activity loads, the number of layouts will not change, nor can a layout be removed.
This is what I have now but the layout is displayed on top of the activity instead of below a Textview:
LayoutInflater inflater = LayoutInflater.from(BucketProfileActivity.this);
for (int i = 0; i < 3; i++) {
View view = inflater.inflate(R.layout.bucketprofile_tips, null);
view.setId(i);
TextView tv_username = (TextView) view.findViewById(R.id.tv_username);
tv_username.setText(String.valueOf(i));
RelativeLayout.LayoutParams rl = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT);
rl.addRule(RelativeLayout.BELOW, R.id.tv_nemkell);
addContentView(view, rl);
}
If your posted xml file is bucketprofile_tips.xml then you need to change here from
TextView tv_username = (TextView) view.findViewById(R.id.tv_title);
to
TextView tv_username = (TextView) view.findViewById(R.id.tv_username);
Because in bucketprofile_tips.xml tv_title id not found for your TextView. So you are getting Null Pointer Exception.
Not sure why you would want to do this but you can just use a LayoutInflater to inflate x of this view and add them to a designated ViewGroup. For example:
LayoutInflater inflater = LayoutInflater.from(context);
for (int i = 0; i < numberOfViews; i++) {
View v = inflater.inflate(R.layout.view_to_add, parentView, false);
setup(v);
parentView.addView(v);
}
Where setup() is a function you define that does the setup work such as setting the text of a TextView etc.
For instance, in your setup function might look something like this:
private void setup(View v) {
TextView tv = (TextView) v.findViewById(R.id.name);
// set the text of the text view
tv.setText("Hello!");
// set the click listener for the view...
v.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
// do stuff here...
}
});
}
LinearLayout parentLayout=findViewById(R.id.parentLayout);
LayoutInflater inflater = LayoutInflater.from(BucketProfileActivity.this);
View view = inflater.inflate(R.layout.bucketprofile_tips, null);
parentLayout.addView(view);
LinearLayout textList=(LinearLayout) parentLayout.getChildAt(0);
for(int i=0; i<textList.getChildCount(); i++){
TextView tv_username=(TextView) textList.getChildAt(i);
textView.setOnClickListener(new View.OnClickListener(){
#Override
public void onClick(View view){
tv_username.setText(String.valueOf(i));
}
}
}

Dynammically create ImageViews not showing the image

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.

layout_margin is ignored when add the view in the view group

I am trying to use HorizontalScrollView with a child LinearLayout view.
I want an item fill the screen with margins, and the next item be able to be seen after scrolling. To make you understand, I will tell you everything I tried with codes.
First, I fixed the width, height, and margins of the items.
<com.example.kanbanboard.TaskListView xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="360dp"
android:layout_height="360dp"
android:layout_margin="10dp"
android:background="#drawable/container">
<TextView
android:id="#+id/category"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:textSize="20sp"
android:layout_margin="10dp"/>
<ListView
android:id="#+id/list"
android:layout_margin="10dp"
android:layout_height="fill_parent"
android:layout_width="fill_parent" />
</com.example.kanbanboard.TaskListView>
The layout of this parent is
<com.example.kanbanboard.MyHorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/container"
android:layout_width="1dp" // It seems that whether 1dp or fill_parent does not matter
android:layout_height="1dp"
tools:context=".MainActivity"
tools:ignore="MergeRootFrame">
<LinearLayout
android:id="#+id/list_container"
android:orientation="horizontal"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:background="#000000">
</LinearLayout>
</com.example.kanbanboard.MyHorizontalScrollView>
and Here is the code which add View in the Linear Layout
public void init(){
LayoutInflater inflater = LayoutInflater.from(getContext());
ViewGroup parent = (ViewGroup) getChildAt(0);
//CategoryView is almost same with TaskListView
CategoryView categoryList = (CategoryView) inflater.inflate(R.layout.category_layout, parent, false);
TaskListView taskList = (TaskListView) inflater.inflate(R.layout.task_list_layout,
parent, false);
categoryList.init(taskList);
taskList.init();
View[] children = new View[]{categoryList, taskList};
ViewTreeObserver.OnGlobalLayoutListener listener = new MainLayoutListener(parent, children);
getViewTreeObserver().addOnGlobalLayoutListener(listener);
}
class MainLayoutListener implements ViewTreeObserver.OnGlobalLayoutListener{
ViewGroup parent;
View[] children;
public MainLayoutListener(ViewGroup parent, View[] children){
this.parent = parent;
this.children = children;
}
#Override
public void onGlobalLayout(){
ScrollView me = ScrollView.this;
me.getViewTreeObserver().removeGlobalOnLayoutListener(this);
parent.addView(children[0]);
parent.addView(children[1]);
}
}
result: http://i.imgur.com/zIe1gTN.png?1
The margin was not ignored, but the item does not fit to the screen.
So I tried to use fill_parent in layout_width and layout_height, but the result was
http://imgur.com/y2yNWmz&zIe1gTN#0
I also tried to set the width, height, and margin with LayoutParams.
ScrollView me = ScrollView.this;
me.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int w = me.getMeasuredWidth() - 50 // for margin;
int h = me.getMeasuredHeight() - 50;
ViewGroup.MarginLayoutParams params = new ViewGroup.MarginLayoutParams(w, h);
params.setMargins(10, 10, 10, 10);
parent.addView(children[0], params);
parent.addView(children[1], params);
With the above code, I could fit the item to the screen, but the margin was ignored.
I hope you understand my problem. How can I fix this situation?
Use View Pager Instead of Making it yourself
http://developer.android.com/reference/android/support/v4/view/ViewPager.html
http://developer.android.com/training/animation/screen-slide.html
use this for reference

GridView with different column sizes

Trying to make a highscore list, which is scrollable, and looks like this:
foo 1000
bar 876
foobar 500
foobarfoo 1
I am currently doing it with a GridView. I would like to set the name column width to 60% of the screen and the score column width to 40%. Is it possible?
Currently I am trying via a costum adapter. Here is the getview funcion for it:
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv;
if (convertView == null) {
tv = new TextView(context);
tv.setTextSize(25);
tv.setTextColor(Color.WHITE);
if (position % 2 == 0)
{
tv.setLayoutParams(new GridView.LayoutParams((width/10)*6, 50));
}
else
{
tv.setLayoutParams(new GridView.LayoutParams((width/10)*4, 50));
}
}
else {
tv = (TextView) convertView;
}
tv.setText(texts[position]);
return tv;
}
The layout is built by the gridview and a button at the bottom. The XML file is:
<?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:id="#+id/top">
<GridView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:id="#+id/grid"
android:numColumns="2"
android:columnWidth="0dp"
>
</GridView>
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/backbutton" android:text="#string/backstr"></Button>
</LinearLayout>
So the question again: Is it possible to set the GridView to let adding different sized columns? If yes, then my approach is good? (Probably not, since it is not working :)) Did I just miss something?
Thank you in advance!
We had to do this for a project, and didn't want to use anything other than a GridView because the functionality was repeated, but on one GridView we needed a slightly different view configuration (but still using an adapter and all that other good stuff). We found that you CAN do this if you override GridView's layoutChildren function, although it's pretty poorly documented.
Our implementation has a check for a special view and for if the new layout has already been implemented:
#Override
protected void layoutChildren(){
super.layoutChildren();
if(!isSpecial || layoutAlreadySet) return;
layoutAlreadySet = true;
//Implement special layout....
}
Working like a charm! Big thanks to Abhinav, who made a good advise. Here is the code for everyone who has the same problem:
public View getView(int position, View convertView, ViewGroup parent) {
TextView tv1;
TextView tv2;
LinearLayout ll;
if (convertView == null) {
tv1 = new TextView(context);
tv1.setTextSize(25);
tv1.setTextColor(Color.WHITE);
tv1.setGravity(Gravity.LEFT);
tv1.setPadding(5, 5, 5, 5);
tv1.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT,
(float) 3.0));
tv2 = new TextView(context);
tv2.setTextSize(25);
tv2.setTextColor(Color.WHITE);
tv2.setGravity(Gravity.RIGHT);
tv2.setPadding(5, 5, 5, 5);
tv2.setLayoutParams(new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FILL_PARENT,
LinearLayout.LayoutParams.FILL_PARENT,
(float) 4.0));
ll = new LinearLayout(context);
ll.setOrientation(0);
ll.setPadding(5, 5, 5, 10);
tv1.setText(names[position]);
tv2.setText(scores[position]);
ll.addView(tv1);
ll.addView(tv2);
}
else {
ll = (LinearLayout) convertView;
tv1 = (TextView) ll.getChildAt(0);
tv2 = (TextView) ll.getChildAt(1);
tv1.setText(names[position]);
tv2.setText(scores[position]);
}
return ll;
}
And the XML file:
<?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:id="#+id/top">
<ListView android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="2"
android:numColumns="2"
android:columnWidth="0dp"
android:id="#+id/list">
</ListView>
<Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/backbutton" android:text="#string/back"></Button>
</LinearLayout>
If you think you can improve this code (since I am a newbie in this field) don't hesitate, to reply! Thanks in advance!

build layout at runtime android

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.

Categories

Resources