GridView with different column sizes - android

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!

Related

ScrollView is cutting off beginning of text

I followed this piece of code written by Aby in another question: https://stackoverflow.com/a/22682248/5915747
The beginning of my text is being cut off on the left side of my screen. I'm missing quite a bit of info and not sure how to fix it, I have tried everything that worked for others but it has not worked for me.
popup.xml
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/scrollviewtest"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
tools:context="com.info.PopupActivity"
android:background="#f0f0f0"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true">
<HorizontalScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_gravity="center"
android:id="#+id/rel_layout"
android:orientation="vertical">
<TableLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="#+id/table_layout"
android:background="#80000000"
android:layout_centerHorizontal="true">
</TableLayout>
</RelativeLayout>
</HorizontalScrollView>
</ScrollView>
init method:
public void init() {
View popupview = getLayoutInflater().inflate(R.layout.popup, null);
popupWindow = new PopupWindow(
popupview, LinearLayout.LayoutParams.MATCH_PARENT,
LinearLayout.LayoutParams.MATCH_PARENT
);
popupWindow.showAtLocation(popupview, Gravity.CENTER, 0, 0);
popup_shown[0] = true;
TableLayout tableLayout = (TableLayout) popupview.findViewById(R.id.table_layout);
TableRow row0 = new TableRow(this);
TextView text0 = new TextView(this);
text0.setText("Test Header1");
row0.addView(text0);
TextView text1 = new TextView(this);
text1.setText("Test Header2");
row0.addView(text1);
TextView text2 = new TextView(this);
text2.setText("Teset Header3");
row0.addView(text2);
TextView text3 = new TextView(this);
text3.setText("Test Header4");
row0.addView(text3);
TextView text4 = new TextView(this);
text4.setText("Test Header5");
row0.addView(text4);
tableLayout.addView(row0);
for (int i = 0; i < 8; i++) {
TableRow tableRow = new TableRow(this);
TextView tv0 = new TextView(this);
tv0.setGravity(Gravity.CENTER);
tv0.setText("long test field 0");
tableRow.addView(tv0);
TextView tv1 = new TextView(this);
tv1.setGravity(Gravity.CENTER);
tv1.setText("long test field 1");
tableRow.addView(tv1);
TextView tv2 = new TextView(this);
tv2.setGravity(Gravity.CENTER);
tv2.setText("long test field 2");
tableRow.addView(tv2);
TextView tv3 = new TextView(this);
tv3.setGravity(Gravity.CENTER);
tv3.setText("long test field 3");
tableRow.addView(tv3);
TextView tv4 = new TextView(this);
tv4.setGravity(Gravity.CENTER);
tv4.setText("long test field 3");
tableRow.addView(tv4);
tableLayout.addView(tableRow);
}
}
The longer the strings are for the text views, the more it crops off, however it's a horizontal scrollview, so it should just start at the beginning of the screen and add length to the end, which is scrollable, right?
This is what it ends up looking like with the current strings in vertical/portrait orientation:
Vertical View
This is what it looks like in horizontal, it seems to fix since my screen is large enough for the data:
Horizontal View
If you have any questions, please ask!
Solved this by adding padding to the scrollview. It seems this is a common android bug.
I don't know will it work or not but try removing
android:layout_gravity="center"
line from Relative Layout

Setting width of LinearLayout dynamically?

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.

how to set Multiple gridview in same layout in android?

I want to set two grid view for same layout. I can also able to set that within same lay out but due to scrollable control its look like a "wrap_content".
but i want to show full grid view in a screen one after another like below fig.
in above fig. grid view show full height of it.
so please help me.
Thank you .
You cannot have a GridView in a ScrollbarView. So what you want is not possible. You can have the two gridviews to share the screen space equally.
<LinearLayout android:layout_height="fill_parent"
.... >
<GridView android:layout_weight="1"
....... >
<GridView android:layout_weight="1"
....... >
</LinearLayout>
Update
There is a download asynctask example here.
In onProgressUpdate set the downloaded image to its view.
protected void onProgressUpdate(Integer... progress) {
setImageToView(bitmapImg, progress[0]); // progress[0] is the index or id.
}
Update 2
You should do it the hard way. Extend the AdapterView class and measure and layout the items yourself. Here is link for start. The layout now would look like
<ScrollView ....>
<LinearLayout android:layout_height="fill_parent"
.... >
<MyGridView android:layout_height="wrap_content"
....... >
<MyGridView android:layout_height="wrap_content"
....... >
</LinearLayout>
</ScrollView>
TRY THIS :
public void createTableRow_you(int no) {
tr_u = new TableRow(this);
LayoutParams lp = new LayoutParams(LayoutParams.FILL_PARENT
, LayoutParams.WRAP_CONTENT);
tr_u.setLayoutParams(lp);
tr_u.setWeightSum((float) 1.0);
tr_u.setPadding(10, 0, 10, 0);
tr_u.setGravity(Gravity.CENTER_VERTICAL );
ImageView img1= new ImageView(this);
//img1.setLayoutParams(lp);
img1.setPadding(10, 10, 10, 10);
// img1.setScaleType(ScaleType.FIT_XY);
if (density == DisplayMetrics.DENSITY_HIGH) {
img1.setLayoutParams(new TableRow.LayoutParams(125, 125 ));
}else {
img1.setLayoutParams(new TableRow.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
if (no < photo_icon_u.size()) {
img1.setImageDrawable(photo_icon_u.get(no));
img1.setId(Integer.parseInt(photoID_profile.get(no)));
img1.setClickable(true);
img1.setOnClickListener(this);
img1.setTag("profile");
}else {
img1.setImageResource(R.drawable.icon);
img1.setVisibility(View.GONE);
}
ImageView img2= new ImageView(this);
//img2.setLayoutParams(lp);
img2.setPadding(10, 10, 10, 10);
// img2.setLayoutParams(new TableRow.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, (float) 0.33));
// img2.setScaleType(ScaleType.FIT_XY);
if (density == DisplayMetrics.DENSITY_HIGH) {
img2.setLayoutParams(new TableRow.LayoutParams(125, 125 ));
}else {
img2.setLayoutParams(new TableRow.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
if (no+1 < photo_icon_u.size() ) {
img2.setImageDrawable(photo_icon_u.get(no+1));
img2.setId(Integer.parseInt(photoID_profile.get(no+1)));
img2.setClickable(true);
img2.setOnClickListener(this);
img2.setTag("profile");
}else {
img2.setImageResource(R.drawable.icon);
img2.setVisibility(View.GONE);
}
ImageView img3= new ImageView(this);
// img3.setLayoutParams(lp);
img3.setPadding(10, 10, 10, 10);
// img3.setLayoutParams(new TableRow.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT, (float) 0.34));
//img3.setScaleType(ScaleType.FIT_XY);
if (density == DisplayMetrics.DENSITY_HIGH) {
img3.setLayoutParams(new TableRow.LayoutParams(125, 125 ));
}else {
img3.setLayoutParams(new TableRow.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT));
}
if ( no+2 < photo_icon_u.size()) {
img3.setImageDrawable(photo_icon_u.get(no+2));
img3.setId(Integer.parseInt(photoID_profile.get(no+2)));
img3.setClickable(true);
img3.setOnClickListener(this);
img3.setTag("profile");
}else {
img3.setImageResource(R.drawable.icon);
img3.setVisibility(View.GONE);
}
tr_u.addView(img1);
tr_u.addView(img2);
tr_u.addView(img3);
//. tb_photo_u.addView(tr_u);
tb_photo_u.addView(tr_u, new TableLayout.LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
You can't put a GridView inside a ScrollView because the scroll view will eat all the Vertical TouchEvents.
I had to work around this problem as well, my solution was to implement an AdapterView by myself to emulate the gridView behevior without extending ScrollView.
I did it with horizontal LinearLayout inside a vertical LinearLayout and dynamic margin between elements.
that way you will have only a root ScrollView that let you scroll down the layout with all the GridView element.
If you have some other elements with GridView, I recommend using FrameLayout with layout_weight.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1">
1st
</FrameLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginTop="20dp">
2nd
</FrameLayout>
</LinearLayout>

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.

How to add padding to a tabs label?

I just started programming for android. I'm using a tab based layout in my app. I would like to put some padding around the tab label so that it's not so close to the icon.
here is how the label is put in:
in main.java
spec = tabHost.newTabSpec("tab1").setIndicator(this.getString(R.string.tab1), res.getDrawable(R.drawable.ic_tab1)).setContent(intent);
and in string.xml
<string name="tab1">my tab label</string>
I've been searching and trying to figure this out for several hours now. I could just make the icons smaller in about two minutes but I like their size.
Can anyone suggest the best way to do simple formatting to the tab label?
tabHost.addTab(tabHost.newTabSpec("tab1").setContent(
new Intent(this, DealCities.class)).setIndicator(prepareTabView("Deals",R.drawable.deal)));
Where prepareTabView is a method.. In these method Inflate a view and add Image and Text as follows :
private View prepareTabView(String text, int resId) {
View view = LayoutInflater.from(this).inflate(R.layout.tabs, null);
ImageView iv = (ImageView) view.findViewById(R.id.TabImageView);
TextView tv = (TextView) view.findViewById(R.id.TabTextView);
iv.setImageResource(resId);
tv.setText(text);
return view;
}
Where tabs is the inflated view and its xml as follows :
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" android:id="#+id/TabLayout" android:background="#drawable/tab_bg_selector"
android:layout_width="fill_parent" android:layout_height="fill_parent"
android:gravity="center"
padding="5dip">
<ImageView android:id="#+id/TabImageView" android:src="#drawable/icon"
android:layout_width="wrap_content" android:layout_height="wrap_content"/>
<TextView android:id="#+id/TabTextView" android:text="Text"
android:paddingTop="5dip" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:textColor="#color/black"
android:textAppearance="#style/TabTextViewStyle" />
</LinearLayout>
Now you can make Your Paddings as you like..
A simpler solution is :
for (int i = 0; i < tabHost.getTabWidget().getChildCount(); i++) {
tabHost.getTabWidget().getChildAt(i).setPadding(10,10,10,10);
}
just use this code
TabWidget widget = mTabHost.getTabWidget();
for (int i = 0; i < widget.getChildCount(); i++) {
//adjust height
widget.getChildAt(i).getLayoutParams().height =40;
//adjust textview
TextView tv = (TextView) widget.getChildAt(i).findViewById(android.R.id.title);
if (tv == null) {
continue;
}
tv.setAllCaps(false);
tv.setTextSize(15);
//set padding
tv.setPadding(10,5, 10, 5);
}

Categories

Resources