In my android app, I want to make a gridlayout of a 5x5 grid. No spacing in between any rows/columns. The grid should match the parent width/height with a 10dp margins. Also all the cells should have equal width and height (i.e. all widths the same, and all heights the same even if width not equals height).
This is what I have so far but nothing shows
public class ColorGrid {
private Context context;
private RelativeLayout container = null;
private GridLayout gridlayout = null;
public ColorGrid(RelativeLayout container) {
this.context = container.getContext();
this.container = container;
this.gridlayout = createGrid();
for(int i=0; i<25; i+=1) {
addCell();
}
container.addView(gridlayout);
}
private GridLayout createGrid() {
GridLayout gridview = new GridLayout(context);
gridview.setColumnCount(5);
gridview.setRowCount(5);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
params.setMargins(10, 10, 10, 10);
gridview.setLayoutParams(params);
return gridview;
}
private void addCell() {
View cell = new View(context);
cell.setBackgroundColor(Color.parseColor("#ffffff"));
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(0, 0, 1.0f);
cell.setLayoutParams(params);
gridlayout.addView(cell);
}
public void dismiss() {
if (container != null && gridlayout != null) {
container.removeView(gridlayout);
}
}
}
Does anyone know whats wrong?
Thanks
Related
I'm creating a ScrollView, nesting in a RelativeLayout (which contains tables). Everything is properly added to the layout. The problem is: vertically scrolling works fine, but horizontal scrolling does NOT work at all. I already tested various combinations of MATCH_PARENT, WRAP_CONTENT and FILL_PARENT. No try even worked close. So my question is: What am I missing here?
Here is the code:
public class PlayerView extends View {
private RelativeLayout relativeLayout;
private TableLayout tableLayout;
private int player_loop;
private int player_count;
public PlayerView(Context context, int player_count){
super(context);
setPlayer_count(player_count);
}
public ScrollView create_scrollView(){
ScrollView scrollView = new ScrollView(getContext());
ScrollView.LayoutParams scroll_params = new ScrollView.LayoutParams(
ScrollView.LayoutParams.MATCH_PARENT,
ScrollView.LayoutParams.MATCH_PARENT
);
scrollView.setLayoutParams(scroll_params);
scrollView.addView(create_relativeLayout());
return scrollView;
}
public RelativeLayout create_relativeLayout(){
relativeLayout = new RelativeLayout(getContext());
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT
);
relativeLayout.setLayoutParams(relativeParams);
create_Player_Table_Layout();
return relativeLayout;
}
public void create_Player_Table_Layout(){
for(player_loop = 1; player_loop <= player_count; player_loop++){
relativeLayout.addView(player_table(getResources().getString(R.string.dummy_player_name) + player_loop, player_loop));
}
}
public TableLayout player_table(String playername, int playernumber){
tableLayout = new TableLayout(getContext());
tableLayout.setId(playernumber * 1000);
if (playernumber > 1) {
//TABLE PLACEMENT
RelativeLayout.LayoutParams tbl_params_New = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
tbl_params_New.addRule(RelativeLayout.RIGHT_OF, (playernumber - 1) * 1000);
tableLayout.setLayoutParams(tbl_params_New);
}
//Add Playername
TableRow row_playername = new TableRow(getContext());
TextView view_name = new TextView(getContext());
TableRow.LayoutParams view_name_params = new TableRow.LayoutParams();
view_name_params.setMargins(20,20,20,20);
view_name.setLayoutParams(view_name_params);
view_name.setGravity(Gravity.CENTER);
view_name.setText(playername);
view_name.setTextSize(20);
view_name.setId(playernumber * 100);
row_playername.addView(view_name);
tableLayout.addView(row_playername);
//Add Lifepoints
TableRow row_lifepoints = new TableRow(getContext());
TextView view_lifepoints = new TextView(getContext());
TableRow.LayoutParams view_lifepoints_params = new TableRow.LayoutParams();
view_lifepoints_params.setMargins(20, 0, 20, 20);
view_lifepoints.setText("40");
view_lifepoints.setTextSize(40);
view_lifepoints.setGravity(Gravity.CENTER);
view_lifepoints.setId(playernumber * 100 + 10);
view_lifepoints.setLayoutParams(view_lifepoints_params);
row_lifepoints.addView(view_lifepoints);
tableLayout.addView(row_lifepoints);
Log.d("Test", "Player count:" + player_count);
for(int opponent_loop = 1; opponent_loop <= player_count; opponent_loop++){
tableLayout.addView(commander_damage_from_player(player_loop, opponent_loop));
}
return tableLayout;
}
private TableRow commander_damage_from_player(int player_loop, int opponent_loop){
TableRow row = new TableRow(getContext());
TextView textView = new TextView(getContext());
TableRow.LayoutParams layoutParams = new TableRow.LayoutParams();
layoutParams.setMargins(20, 0, 40, 20);
textView.setLayoutParams(layoutParams);
textView.setText("0 | " + getResources().getString(R.string.dummy_player_name)+ " " + opponent_loop);
textView.setTextSize(20);
textView.setId(player_loop + 100 + opponent_loop);
row.addView(textView);
return row;
}
private void setPlayer_count(int player_count){
this.player_count = player_count;
}
}
And for documentation the calling class:
public class Home extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
PlayerView playerView = new PlayerView(this, 8);
setContentView(playerView.create_scrollView());
}
}
The only way you can do this is by creating a horizontalscrollview to be the child of the scrollview. If you make the minor modification to your create_relativeLayout() to create a horizontalscroll view then it will work correctly. I have seen this happen in other examples.
public HorizontalScrollView create_relativeLayout(){
HorizontalScrollView horizontalScrollView = new HorizontalScrollView(getContext());
relativeLayout = new RelativeLayout(getContext());
RelativeLayout.LayoutParams relativeParams = new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.MATCH_PARENT,
RelativeLayout.LayoutParams.MATCH_PARENT
);
relativeLayout.setLayoutParams(relativeParams);
create_Player_Table_Layout();
horizontalScrollView.addView(relativeLayout);
return horizontalScrollView;
}
I am new to Android Development. I have been working with using a GridLayout to display Dynamically inserted ImageViews.
My issue is located in "onFocusWindowChanged" but I pasted my onCreate where I do my assignments of the images.
private List<Behavior> behaviors = null;
private static int NUM_OF_COLUMNS = 2;
private List<ImageView> images;
private GridLayout grid;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_behaviors);
XMLPullParserHandler parser = new XMLPullParserHandler();
try {
behaviors = parser.parse(getAssets().open("catagories.xml"));
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
grid = (GridLayout) findViewById(R.id.behaviorGrid);
images = new ArrayList<ImageView>();
grid.setColumnCount(NUM_OF_COLUMNS);
grid.setRowCount(behaviors.size() / NUM_OF_COLUMNS);
for (Behavior behavior : behaviors)
images.add(this.getImageViewFromName(behavior.getName()));
}
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
View view = (View) findViewById(R.id.scrollView);
int width = (int) (view.getWidth() * .45);
Log.i("ViewWidth", Integer.toString(width));
GridLayout.LayoutParams lp = new GridLayout.LayoutParams();
lp.height = width;
lp.width = width;
int childCount = images.size();
ImageView image;
for (int i = 0; i < childCount-1; i++) {
image = images.get(i);
image.setLayoutParams(lp);
grid.addView(image);
}
}
In my (short) previous experience, using
grid.add(View);
worked fine, but now I am only seeing the last child display only. Looking through the debugger I can see that the gridview is being populated with more than just the last element, as well as the last imageview.
Thank you for your help
you should create a GridLayout.LayoutParams for each ImageView:
for (int i = 0; i < childCount-1; i++) {
GridLayout.LayoutParams lp = new GridLayout.LayoutParams();
lp.height = width;
lp.width = width;
......
}
GridLayout.LayoutParams contains location information, e.g [column:2, row:3]. In your code, all ImageViews are set the same GridLayout.LayoutParams, so they are located in the same cell(overlapping each other).
When use LinearLayout.LayoutParams instead, there is no location information in it. GridLayout will create a new GridLayout.LayoutParams for each child view, so all ImageViews use their own different GridLayout.LayoutParams and location.
Wish this help. You can read the GridLayout.java and ViewGroup.java for more details.
So I solved my issue, although I'm not sure how-
GridLayout.LayoutParams lp = new GridLayout.LayoutParams();
changed to...
LinearLayout.LayoutParams lp = new LinearLayout.LayoutParams(x,y);
made it work just as I wanted it. But I'm not sure why- If anyone could explain, please do :)
I'm using the twoway view for the first and i'm struggling to specify the layout attributes for the views. I have tow kinds of views, header and the episode.
This is the xml of both:
Show:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_margin="#dimen/margin_16dp"
android:layout_width="248dp"
android:layout_height="160dp"
android:background="#color/black">
//More views...
</RelativeLayout>
Header:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="54dp"
android:background="#color/red_800">
//More views
I set the height to be 54dp in the header and 160dp for the show but what i'm getting is this, it's always the same (wrong) height, the red bar is the header.
http://postimg.org/image/xx1dk45n9/
Code:
public static class ViewHolder extends RecyclerView.ViewHolder{
public TextView title,date,rate,episode;
public ImageView image;
public ViewHolder(View view) {
super(view);
image = (ImageView)view.findViewById(R.id.image);
title = (TextView)view.findViewById(R.id.title);
date = (TextView)view.findViewById(R.id.date);
rate = (TextView)view.findViewById(R.id.rate);
episode = (TextView)view.findViewById(R.id.episode);
}
}
public static class ViewHolderHeader extends RecyclerView.ViewHolder{
public TextView date,children;
public ViewHolderHeader(View view) {
super(view);
date = (TextView)view.findViewById(R.id.date);
children = (TextView)view.findViewById(R.id.children);
}
}
public CalendarAdapter(Context context) {
mContext = context;
readDateFormat(context);
simpleDateFormat = new SimpleDateFormat(datePattern, Locale.US);
}
#Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
final View view;
if (viewType == CalendarGridItem.TYPE.SHOW.ordinal()){
view = LayoutInflater.from(mContext).inflate(R.layout.calendar_grid_tile, parent, false);
return new ViewHolder(view);
}
else {
view = LayoutInflater.from(mContext).inflate(R.layout.calendar_grid_header, parent, false);
return new ViewHolderHeader(view);
}
}
#Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
final View view = holder.itemView;
final CalendarGridItem item = mShows.get(position);
final SpannableGridLayoutManager.LayoutParams lp =
(SpannableGridLayoutManager.LayoutParams) view.getLayoutParams();
if (getItemViewType(position) == CalendarGridItem.TYPE.HEADER.ordinal()){ //Header
final ViewHolderHeader holder1 = (ViewHolderHeader)holder;
CalendarHeader header = (CalendarHeader)item;
Log.d(TAG,"Entrou header: "+header.getDate());
//Mete a colSpan a 2
if (lp.colSpan != 2)
lp.colSpan = 2;
lp.height = 100; //Even forcing the height doesn't work
view.setLayoutParams(lp);
}else{ //Show
final ViewHolder holder1 = (ViewHolder)holder;
UpcomingShow show = (UpcomingShow)item;
if (lp.colSpan != 1)
lp.colSpan = 1;
view.setLayoutParams(lp);
}
}
Fragment layout:
<org.lucasr.twowayview.widget.TwoWayView
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="#+id/spanGrid"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#color/background"
style="#style/TwoWayView"
app:twowayview_layoutManager="SpannableGridLayoutManager"
app:twowayview_numColumns="2"/>
What i'm doing wrong ? I'm not used to the recycler view way of doing things, i must be missing something. Teste with Android 4.1.1 and 4.4
Currently have quite the same problem (mine is that elements are all "squares")
It seems like it not possible to give specific height/width for elements in the item layout.
When you look in the source code, in the SpannableGridLayoutManager.java file, you have the method : LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp).
In there, those are the incrimated lines :
final LayoutParams spannableLp = new LayoutParams((MarginLayoutParams) lp);
spannableLp.width = LayoutParams.MATCH_PARENT;
spannableLp.height = LayoutParams.MATCH_PARENT;
But if you do remove that, you "break" all the logic for the spannable grid view...
I also thought that TwoWayView can display the items as squares. So I was digging in the source and found , like Wicha said, that MATCH_PARENT in two places was causing the undesired behaviour.
So I made the following adjustments in the SpannableGridLayoutManager file (commented some lines in checkLayoutParams method) :
#Override
public boolean checkLayoutParams(RecyclerView.LayoutParams lp) {
// if (lp.width != LayoutParams.MATCH_PARENT ||
// lp.height != LayoutParams.MATCH_PARENT) {
// return false;
// }
if (lp instanceof LayoutParams) {
(.....)
}
and here (use width and height from layout params in generateLayoutParams method) :
#Override
public LayoutParams generateLayoutParams(ViewGroup.LayoutParams lp) {
final LayoutParams spannableLp = new LayoutParams((MarginLayoutParams) lp);
spannableLp.width = lp.width; //LayoutParams.MATCH_PARENT;
spannableLp.height = lp.height; //LayoutParams.MATCH_PARENT;
if (lp instanceof LayoutParams) {
(....)
}
Also, in your Adapter class, goes something like this :
#Override
public void onBindViewHolder(ViewHolder viewHolder, final int i) {
viewHolder.image.setScaleType(ImageView.ScaleType.FIT_XY);
viewHolder.image.setPadding(5,5,5,5);
SpannableGridLayoutManager.LayoutParams layoutParams = ((SpannableGridLayoutManager.LayoutParams) viewHolder.itemView.getLayoutParams());
layoutParams.width = cell_width * item.size; //multiply size
layoutParams.height = cell_height * item.size;//multiply size
layoutParams.colSpan = item.size;
layoutParams.rowSpan = item.size;
viewHolder.image.setLayoutParams(layoutParams);
}
Some observations:
cell_width is calculated like screen width/3 in portrait orientation and screen width/4 in landscape.
cell_height is calculated like image_width / image_ratio.
item.size : I decided to have 1:1 or 2:2 or 3:3 aspect ratios for the items, so item_size is the multiplication value.
I have this code below that creates a square with an image, textview and 2 image buttons.
It looks like this:
I want it so that the text is always in 1 line. The width of the square needs to expand so it includes the full text. In the image, the text gets cropped. The two little buttons (info and settings) needs to be in the corners of the square. Also there is another problem, the text is not vertically centered and it should be.
I can't quite get it to look right. Does anyone know how to fix this?
Thanks
public static LinearLayout createNodeWrapper(Activity context, Fish fish) {
ImageView imageview = createImageView(context, fish);
TextView nametv = createNameView(context, fish.getName());
ImageButton info = createButton(context, R.drawable.ic_action_info);
ImageButton settings = createButton(context, R.drawable.ic_action_settings);
LinearLayout namewrapper = createNameWrapper(context);
namewrapper.addView(info);
namewrapper.addView(nametv);
namewrapper.addView(settings);
LinearLayout contentwrapper = createContentWrapper(context, fish);
contentwrapper.addView(imageview);
contentwrapper.addView(namewrapper);
LinearLayout fullwrapper = createFullWrapper(context, fish);
fullwrapper.addView(contentwrapper);
return fullwrapper;
}
private static ImageView createImageView(Context context, Fish fish) {
ImageView imageview = new ImageView(context);
LinearLayout.LayoutParams params = fish.getImageParams();
params.gravity = Gravity.CENTER;
params.setMargins(20, 20, 20, 20);
imageview.setLayoutParams(params);
imageview.setScaleType(ImageView.ScaleType.FIT_CENTER);
return imageview;
}
private static TextView createNameView(Context context, String name) {
TextView nametv = new TextView(context);
nametv.setText(name);
nametv.setTextAppearance(context, R.style.node);
nametv.setPadding(10, 0, 10, 10);
nametv.setGravity(Gravity.CENTER);
nametv.setSingleLine(true);
LinearLayout.LayoutParams textparams = new LinearLayout.LayoutParams(0, LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f);
textparams.gravity = Gravity.CENTER;
nametv.setLayoutParams(textparams);
return nametv;
}
private static ImageButton createButton(Context context, int resId) {
ImageButton imageButton = new ImageButton(context);
imageButton.setPadding(0, 0, 0, 0);
LinearLayout.LayoutParams imageparams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
imageparams.gravity = Gravity.CENTER;
imageButton.setLayoutParams(imageparams);
imageButton.setBackgroundResource(resId);
return imageButton;
}
private static LinearLayout createNameWrapper(Context context) {
LinearLayout wrapper = new LinearLayout(context);
wrapper.setOrientation(LinearLayout.HORIZONTAL);
wrapper.setPadding(0, 0, 0, 0);
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT);
wrapper.setLayoutParams(params);
return wrapper;
}
private static LinearLayout createContentWrapper(Context context, Fish fish) {
LinearLayout wrapper = new LinearLayout(context);
wrapper.setOrientation(LinearLayout.VERTICAL);
wrapper.setPadding(3, 0, 3, 3);
LinearLayout.LayoutParams params = fish.getParams();
wrapper.setLayoutParams(params);
wrapper.setMinimumWidth(MIN_NODE_WIDTH);
return wrapper;
}
private static LinearLayout createFullWrapper(Context context, Fish fish) {
LinearLayout wrapper = new LinearLayout(context);
wrapper.setBackgroundResource(R.drawable.category_bg);
wrapper.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams params = fish.getParams();
params.setMargins(10, 10, 10, 10);
wrapper.setLayoutParams(params);
return wrapper;
}
For the text, try this answer: https://stackoverflow.com/a/2142968/2629065 it will scale down the text until it fits the parameters you give it.
You padded the top, which adds to the height of the item, offsetting the gravity alignment. Remove the top padding and use a margin, or pad the bottom.
I have TextView created programmatically, like that:
TextView mTextView = new TextView(getApplicationContext());
final LayoutParams params = new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
((MarginLayoutParams) params).setMargins(8, 8, 0, 0);
mTextView.setText(mText);
mTextView.setLayoutParams(params);
mTextView.setPadding(2, 2, 2, 2);
mTextView.setBackground(getResources().getDrawable(R.drawable.note_corps));
tagMap.addView(mTextView);
textViewsWidth = mTextView.getWidth();
But mTextView.getWidth() always returns 0
And if I try:
mTextView.getLayoutParams().width
It returns the LayoutParams corresponding value in the LayoutParams class (-1 or -2)
How can I get the view's width ?
EDIT I need to do this here:
#Override
public void onPostExecute(Hashtable<String, Integer> hash){
final ScrollView tagMapScroll = (ScrollView) findViewById(R.id.tagMapScroll);
final LinearLayout tagMap = (LinearLayout) findViewById(R.id.tagMap);
final ArrayList<Integer> arr = new ArrayList<Integer>(hash.values());
final Enumeration<String> e = hash.keys();
int index = 0;
int textViewsWidth = 0;
while(e.hasMoreElements()){
final TextView tV = new TextView(getApplicationContext());
tV.setTextColor(Color.parseColor("#666666"));
tV.setText(Html.fromHtml(randomColor() + e.nextElement()));
tV.setTextSize(arr.get(index));
final LayoutParams params = new TableLayout.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
((MarginLayoutParams) params).setMargins(8, 8, 0, 0);
tV.setLayoutParams(params);
tV.setPadding(2, 2, 2, 2);
tV.setBackground(getResources().getDrawable(R.drawable.note_corps));
tagMap.addView(tV);
textViewsWidth += tV.getWidth();
index++;
}
tagMapScroll.setVisibility(ScrollView.VISIBLE);
}
EDIT SOLUTION I used this from #androiduser's answer:
mTextView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
int width = mTextView.getMeasuredWidth();
int height = mTextView.getMeasuredHeight();
Problem solved !
I used this solution:
yourView.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
// Ensure you call it only once
yourView.getViewTreeObserver().removeOnGlobalLayoutListener(this);
// Here you can get the size :)
}
});
get this way:
tV.post(new Runnable() {
#Override
public void run() {
int width=tV.getMeasuredWidth();
}
});
those values are constant value for FILL_PARENT and WRAP_CONTENT. If you want to check the view size you can try this way:
tagMap.addView(mTextView);
tagMap.post(new Runnable() {
#Override
public void run() {
mTextView. getWidth();
}
});
you have to wait until android draws the TextView. This way you are posting a Runnable in the tagMap queue, that is executed, hopefully after the textview is draw (so it should be weight and height)
In this method you can get the width height of the view..
#Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
int width = mTextView.getWidth();
int height = mTextView.getHeight();
}
and define TextView mTextView as global
You have to use ViewTreeObserver class which is used to register listeners that can be notified of global changes in the view tree. Such global events include, but are not limited to, layout of the whole tree, beginning of the drawing pass, touch mode change.
In the Activity's onCreate mehotd put this:
ViewTreeObserver vto = mTextView.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
mTextView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
int viewWidth = mTextView.getMeasuredWidth();
}
});