Which LayoutManager for the animations of a 2048 game? - android

For training purposes, I am currently replicating the 2048 game. I got the logic and interaction done, but print (and simply refresh) it inside a single TextView which looks ridiculous, of course.
When thinking about how to build a UI for the game, I am uncertain which LayoutManager to choose. What I need to be doing in the game's 4 x 4 grid is to merge and add cells inside rows and columns with animation. It seems to me that:
GridLayout won't work since it is dealing with the full dataset (16 tiles in four rows/columns) when I need to be able to deal with single rows and columns. However, I am not sure about this. I have worked with GridLayout before, but never manipulated the number of items (add, remove) and never used animation with that manipulation. Is there a way of manipulating single rows and columns?
LinearLayout won't work since I get in trouble when I want to manipulate columns, but have four horizontal LinearLayouts, or rows, but have four vertical LinearLayouts.
RelativeLayout or ConstraintLayout would be possible - maybe. Here the trouble seems to be that I have to keep track of my 16 views, TextViews probably, and programmatically construct full layouts so I can tell animation what to do. Certainly viable, but challenging.
CustomLayout is a choice, but on which superclass should I build it and why?
Am I missing the easy solution? If not, what would be the most "natural" LayoutManager for my data structure (which is currently an array of 16 integers, but could easily be changed to a 4 x 4 array of integers).

Update: Included demo of a tile appearing and two tiles being combined.
I suggest that you go with ConstraintLayout. It will allow you to position your views efficiently and can provide you with some easy animation. I have mocked up a quick sample below to demonstrate this approach.
Here is a video of the results:
The XML layout uses ConstraintLayout as the view group. The two boxes are simply text views but could easily be image views or another type of view.
The two boxes simply move vertically between horizontal guidelines at 24dp (gdln0) and 520dp (gdln100) for textView1 and 148dp (gdln25) and 520dp (gdln100) for textView2. These movement are animated using ConstraintSet and TransitionManager through a click handler attached to the "animate" button. Here is the XML followed by the code:
activity_main.xml
<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:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<android.support.constraint.Guideline
android:id="#+id/gdln0"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="24dp" />
<android.support.constraint.Guideline
android:id="#+id/gdln25"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="148dp" />
<android.support.constraint.Guideline
android:id="#+id/gdln50"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="272dp" />
<android.support.constraint.Guideline
android:id="#+id/gdln75"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="396dp" />
<android.support.constraint.Guideline
android:id="#+id/gdln100"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="520dp" />
<TextView
android:id="#+id/textView1"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="24dp"
android:background="#android:color/darker_gray"
android:gravity="center"
android:text="2"
android:textColor="#android:color/white"
android:textSize="72sp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="#id/gdln0" />
<TextView
android:id="#+id/textView2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginStart="24dp"
android:background="#android:color/darker_gray"
android:gravity="center"
android:text="4"
android:textColor="#android:color/white"
android:textSize="72sp"
app:layout_constraintStart_toEndOf="#+id/textView1"
app:layout_constraintTop_toBottomOf="#id/gdln25" />
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
android:layout_marginRight="16dp"
android:text="Animate"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" />
</android.support.constraint.ConstraintLayout>
MainActivity.java
public class MainActivity extends AppCompatActivity {
private int mSquareSide;
private int mMargin;
private int mBoardState = 0;
private TextView mNewView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Resources r = getResources();
mSquareSide = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 100, r.getDisplayMetrics());
mMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 24, r.getDisplayMetrics());
findViewById(R.id.button).setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
ConstraintLayout layout = (ConstraintLayout) findViewById(R.id.layout);
ConstraintSet newSet = new ConstraintSet();
mBoardState = (mBoardState + 1) % 3;
switch (mBoardState) {
case 0: // Just reset the board to its starting condition.
setContentView(R.layout.activity_main);
findViewById(R.id.button).setOnClickListener(this);
break;
case 1: // Move tiles down and insert new tile.
mNewView = new TextView(layout.getContext());
mNewView.setId(View.generateViewId());
mNewView.setBackgroundColor(getResources().getColor(android.R.color.darker_gray));
mNewView.setTextSize(72);
mNewView.setTextColor(getResources().getColor(android.R.color.white));
mNewView.setText("2");
mNewView.setVisibility(View.INVISIBLE);
mNewView.setGravity(Gravity.CENTER);
ConstraintLayout.LayoutParams lp = new ConstraintLayout.LayoutParams(mSquareSide, mSquareSide);
mNewView.setLayoutParams(lp);
layout.addView(mNewView);
newSet.clone(layout);
newSet.connect(mNewView.getId(), ConstraintSet.TOP,
R.id.gdln0, ConstraintSet.BOTTOM);
newSet.connect(mNewView.getId(), ConstraintSet.START,
ConstraintSet.PARENT_ID, ConstraintSet.START, mMargin);
newSet.clear(R.id.textView1, ConstraintSet.TOP);
newSet.clear(R.id.textView2, ConstraintSet.TOP);
newSet.connect(R.id.textView1, ConstraintSet.BOTTOM,
R.id.gdln100, ConstraintSet.BOTTOM);
newSet.connect(R.id.textView2, ConstraintSet.BOTTOM,
R.id.gdln100, ConstraintSet.BOTTOM);
TransitionManager.beginDelayedTransition(layout);
newSet.applyTo(layout);
mNewView.setVisibility(View.VISIBLE);
break;
case 2: // Move tiles up and combine two tiles.
newSet.clone(layout);
newSet.clear(R.id.textView1, ConstraintSet.BOTTOM);
newSet.clear(R.id.textView2, ConstraintSet.BOTTOM);
newSet.connect(R.id.textView1, ConstraintSet.TOP,
R.id.gdln0, ConstraintSet.BOTTOM);
newSet.connect(R.id.textView2, ConstraintSet.TOP,
R.id.gdln0, ConstraintSet.BOTTOM);
Transition transition = new AutoTransition();
transition.addListener(new Transition.TransitionListener() {
#Override
public void onTransitionStart(Transition transition) {
}
#Override
public void onTransitionEnd(Transition transition) {
mNewView.setText("4");
// Here you would remove the overlapped view
// with layout.removeView(View);
}
#Override
public void onTransitionCancel(Transition transition) {
}
#Override
public void onTransitionPause(Transition transition) {
}
#Override
public void onTransitionResume(Transition transition) {
}
});
TransitionManager.beginDelayedTransition(layout, transition);
newSet.applyTo(layout);
break;
}
}
});
}
}

I think I would go with plain drawing the whole thing without using any TextView or similar.
Let me explain you why.
Assuming you have a set of 16 TextView, which is the maximum that you can have in your grid, you should manage which one is visible and which one is not, hide it or not, move it inside a layout or not. This would take up many resources and if you're using a layout like the ones you've described, a "free" transition would not be possible too.
Assume you have two tiles and you want one to slide on the other and merge them. The only usable layout I can think of is RelativeLayout because it's the one with the most easily manipulable constraints.
You'll have to deal with every TextView though, managing the gradual transition and the overlap, while making Android consider ALL the stuff a TextView can do.
Now, you'll have to do all that movement/overlapping stuff anyway, so why don't you do that by drawing each tile? You'll have to write some more code to draw an hypothetic Tile class into a canvas (note that you might change your data structure a bit).
After you have your drawing mechanism you'll have to make the same stuff you would do with TextViews, but in a different, freer, way of thinking, with fewer constraints and by using less Android resources.
I know you were asking advice about some Layout to use and I'm proposing to draw the tiles by yourself, this might not be what you needed and if I bothered you with this long talk I apologise, but if you were asking for advice in a "wider" manner I think this is a good idea to keep in mind.
And it would be a great occasion to learn about 2d drawing on Android too!
Happy coding!

Related

What is meaning of margin in constraint set connect

The official documentation of the constraint set connect says: https://developer.android.com/reference/android/support/constraint/ConstraintSet.html#connect(int, int, int, int, int)
void connect (int startID,
int startSide,
int endID,
int endSide,
int margin)
the margin to constrain (margin must be postive)
For my understanding if I want to connect two views with the left to right of then this margin is left margin.
//left to right of
constraintset.connect(textView.id,ConstraintSet.LEFT,previousTextViewId,ConstraintSet.RIGHT,10)
then 10 is the left margin. Am I right? I have implemented this concept but no margin is set even no right or left. What am I missing?
Update: It looks like this issue has been fixed, but I haven't checked it out. See the bug report.
Your understanding is also how I understand things. Here is a quick way to check how things are working.
In the layout below, the top left corner of textRight lines up with the lower right corner of textLeft. When MainActivity runs, textRight should move 1,000px down and 1,000px to the right. It moves 1,000 px down but does not move to the right at all.
I believe that this is an outstanding issue. See this issue report.
I don't know a work-around and I am surprised that this could even be a bug. I am willing to stand corrected if anyone sees the error.
two_text_views.xml
<?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:id="#+id/layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="#+id/textLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="TextView1"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:layout_marginStart="8dp" />
<TextView
android:id="#+id/textRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextView2"
android:layout_marginTop="0dp"
app:layout_constraintTop_toBottomOf="#+id/textLeft"
app:layout_constraintStart_toEndOf="#+id/textLeft"
android:layout_marginStart="0dp" />
</android.support.constraint.ConstraintLayout>
**MainActivity.java**
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
ConstraintLayout layout;
super.onCreate(savedInstanceState);
setContentView(R.layout.two_text_views);
ConstraintSet constraints = new ConstraintSet();
constraints.clone(layout);
constraints.connect(R.id.textRight, ConstraintSet.LEFT, R.id.textLeft, ConstraintSet.RIGHT, 1000);
constraints.connect(R.id.textRight, ConstraintSet.TOP, R.id.textLeft, ConstraintSet.BOTTOM, 1000);
constraints.applyTo(layout);
}
}
EDIT So, here is a fix. Use ConstraintSet.START and ConstraintSet.END instead of ConstraintSet.LEFT and ConstraintSet.RIGHT. I just tried it and it works OK. I can't say why left and right don't work.

when rotate how to dynamically change layout to avoid re-start activity

Having a layout which has horizontally side by side A and B parts when in landscape mode. Let's say A take 1/3 of the screen and B take other 2/3.
When rotate what is wanted is that the A keeps its original width but is changed to overlay on top of the B and B changes to have width of full screen underneath the A.
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<FrameLayout
android:id="#+id/left_part"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.3" />
<FrameLayout
android:id="#+id/right_part"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.7" />
</LinearLayout>
The part A, and B are holders for different fragments, which has it's adapetr with cursor etc. and could have a few stacked up in backstack. So when rotate would prefer to not re start the activity so that the context is maintained, but just some how to rearrange the layout dynamically.
Not sure if it is doable. Any suggestion?
Thanks!
Handling the Configuration Change Yourself
Your activity should be using saved instance state to persist the data from the old layout and restore it into the new layout.
It's theoretically possible to define a single layout that has sub groups from the different orientations, populate them both, then show / hide those as the rotation occurs using the method mentioned above for handling it yourself, but you are better off sticking Android's stock mechanism to handle this.
seems it should work with dynamically changing the layout, tried following shows the expected behavior.
Please comment if seeing any issue with this approach or having better solution. Thanks!
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal">
<FrameLayout
android:id="#+id/right_pane"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:layout_alignParentLeft="false"
android:layout_toRightOf="#+id/left_part" />
<FrameLayout
android:id="#+id/left_part"
android:layout_width="#dimen/left_part_width"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"/>
</RelativeLayout>
void doChangeMode() {
RelativeLayout.LayoutParams leftLp = (RelativeLayout.LayoutParams) leftPart.getLayoutParams();
RelativeLayout.LayoutParams rightLp = (RelativeLayout.LayoutParams) rightPart.getLayoutParams();
if (mode == mode_side_by_side) {
mode = mode_overlap;
rightLp.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
} else {
mode = mode_side_by_side;
rightLp.addRule(RelativeLayout.ALIGN_PARENT_LEFT, 0);
//api 17 above
//rightLp.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
}
Handler delayHandler = new Handler();
delayHandler.post(new Runnable() {
#Override
public void run() {
rootView.requestLayout();
}
});
}

Listview changing size of (reused) views

I am all for reusing views in listview. I always set visibility, contents, witdth etc. of all controls again in getView Unfortunately it seems ListView fails to recalculate height.
Picture one shows the initial item showed:
Picture two shows how item one is rendered after we scrolled away and back into it
The background linearlayout height (the black area) made me think that in picture two, Android is reusing a view that just showed a much heigher item (e.g. the second item). But why does it not recalibrate/reset/recalclulate itself (it is in "wrap_content" mode in its XML) when reused as view for the first item which content (text + image) is not as heigh?
In truth I am not sure what is happening. The problem only manifests itself if I have image in the view. I have tried organize the bitmap/image loading in different ways (sample code underneath) with different things commented out, but that does not seem to make much difference. I am really at a loss here as to the reason.
override_listitem_news.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="10dip"
android:background="#android:color/black"
>
<TextView
android:id="#+id/listitem_news_label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="bold"
android:textSize="22sp"
android:padding="5dip"
android:text="#string/newsItemTitle"/>
<TextView
android:id="#+id/listitem_news_date"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="italic"
android:textSize="15sp"
android:padding="5dip"
android:text="#string/newsItemDate"/>
<TextView
android:id="#+id/listitem_news_content"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textStyle="normal"
android:textSize="15sp"
android:padding="5dip"
android:autoLink="web"
android:text="#string/newsItemDesc"
android:background="#android:color/darker_gray"
/>
<ImageView
android:id="#+id/listitem_news_icon"
android:layout_width="match_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
Here is code where I load image in getView
ViewTreeObserver vto = image.getViewTreeObserver();
vto.addOnGlobalLayoutListener(
new OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
image.getViewTreeObserver().removeGlobalOnLayoutListener(this);
image.setScaleType(ImageView.ScaleType.CENTER_INSIDE);
SharedCode.sharedUtilScaleImage_Width(image);
}
}
);
image.setTag(data.image_file_name + data.image_file_url);
Bitmap bit = null;
bit = SharedCode.sharedGetFileFromOffline(thisActivityContext, "news", data.image_file_name, MyGetKindOfFile.ImageAsBitmap).bitmap;
if (bit != null) {
image.setImageBitmap(bit);
image.setVisibility(View.VISIBLE);
}
else {
image.setImageBitmap(null);
image.setVisibility(View.GONE);
}
image.setPadding(0, 0, 0, 0);
image.setBackgroundColor(data.backgroundColorInt);
For what it is worth, problem appeared to be related to the imageview. Just for reference, I will write here how I solved it.
In getView I fixed the imageview width to screen width (instead of "wrap-content" and/or parent view width - earlier code used OnGlobalLayoutListener for parent width)
I switched over to using SetDrawable instead of SetImageBitmap. It is odd, but this difference was actual very important in solving the odd space around the imageview after scrolling an item/row in/out of view.
My research did also indicate that others had problems using wrap_content in listview for cases similar to mine, but I was not able to find anyone who had experienced exact same problems as me.

Align a Button with an Image inside another Layout

Apologies for the confusing header. My problem is explained better in the following image:
I need the green Button to be aligned with the top of the Image, but the Image is inside another Layout. Is this possible?
It can be done in code if necessary; XML is not required. I am targeting Android 2.2 and newer.
EDIT:
My current implementation is to simply set the MarginTop-property of the Button, but this is inconvenient when I need to change the sizes of the text inside the LinearLayout, which I plan to do depending on the screen size.
I think it can be solved by somehow finding the Y coordinate of the Image, perhaps by adding the heights of the TextViews, and then setting this as the MarginTop for the Button, but this sounds cumbersome. Is there really no other option?
The LinearLayout is going to be placed inside a ViewPager (with multiple views, all having an image in the same position), which is why I can't do it the way preeya explains.
It's possible but more complicated than including the button into the same layout. If you definitely don't want to do that, you can't use XML (which is always faster). You have to do 3 steps in your code:
1.) Wait until the view is drawn
private void waitForViewToBeDrawn(){
// get your layout
final RelativeLayout mainLayout = (RelativeLayout) findViewById(R.id.mainLayout);
ViewTreeObserver vto = mainLayout.getViewTreeObserver();
// add a listener
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
// you also want to remove that listener
mainLayout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
// go on to next step
getPositionOfImageView();
}
});
}
That approach works best for me, but if you have troubles - here are some alternatives.
There are also [more solutions][2] out there when you use API level 11 and higher...
2.) Get the top-position of your imageView
private void getPositionOfImageView(){
ImageView imageView = (ImageView) findViewById(R.id.imageView);
// Top position view relative to parent (Button and ImageView have same parent)
int topCoordinate = imageView.getTop();
adjustButton(topCoordinate);
}
3.) Add or adjust the button in order to be aligned with the image
public void adjustButton(int topCoordinate){
Button button = (Button) findViewById(R.id.button);
RelativeLayout.LayoutParams params = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
params.topMargin = topCoordinate;
button.setLayoutParams(params);
}
This step would be smoother by using API 11: button.setTop(topCoordinate)
Of course you can shorten all of it and put it in a singele method, just thought that 3 steps are better to explain. Hope that code helps to get started!
U can use linearlayout for displaying image & button as follows :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/longText"
android:gravity="center"
android:text="Some very long text" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:id="#+id/subtitle"
android:layout_below="#+id/longText"
android:text="subtitle" />
<Button
android:id="#+id/button1"
android:layout_width="wrap_content"
android:layout_below="#+id/subtitle"
android:layout_toLeftOf="#+id/subtitle"
android:layout_height="wrap_content"
android:text="button" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_toRightOf="#+id/button1"
android:layout_below="#+id/subtitle"
android:orientation="horizontal"
>
<ImageView
android:id="#+id/imageView2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:src="#drawable/ic_launcher" />
</LinearLayout>
</RelativeLayout>

float animated ImageView on top of other elements within LinearLayout - android

I have an extended ImageView that I'm reusing 7 times horizontally (within a LinearLayout) across my screen. Directly above and below this ImageView are other extended ImageViews that are within their own LinearLayouts. I'm spacing these all evenly by using the weight property within the LinearLayout so they space evenly across the screen. What I need to do is have this middle ImageView be able to float on top of either the top or bottom ImageViews to which it lines up with an animation. Is there some sort of z-index I can put on elements so that I can float this middle IV above the others?
Snippet of my xml:
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/opponentrow">
<ImageView
android:id="#+id/your1"
android:layout_width="45px"
android:layout_height="60px"
android:src="#drawable/topimage"
android:layout_weight="1" />
...
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/tokenrow">
<ImageView
android:id="#+id/your1"
android:layout_width="20px"
android:layout_height="20px"
android:src="#drawable/centerimage"
android:layout_weight="1" />
...
</LinearLayout>
<LinearLayout
android:orientation="horizontal"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<ImageView
android:id="#+id/your1"
android:layout_width="45px"
android:layout_height="60px"
android:src="#drawable/bottomimage"
android:layout_weight="1" />
...
</LinearLayout>
the ellipses just indicate that those imageviews are repeated 7 times each. Also, they are not TRUE ImageViews as I said, they are extended.
here is a snippet for the imageview that's in the middle (one with centerimage as its source) that does the animation (this is within the .java file)
public Tokens(Context context) {
super(context);
// TODO Auto-generated constructor stub
setOnClickListener(myListener);
}
private OnClickListener myListener = new OnClickListener(){
public void onClick(View v) {
doAnimate();
}
};
private void doAnimate(){
final Animation animUp = new TranslateAnimation(0,0,0,-22);
animUp.setDuration(200);
animUp.setFillAfter(true);
final Animation animDown = new TranslateAnimation(0,0,0,22);
animDown.setDuration(200);
animDown.setFillAfter(true);
if(avail)
startAnimation(animDown);
}
some important considerations: I need to retain the even horizontal spacing for the 7 elements (all 3 rows of them). I'm open to using a different Layout type if my objectives can't be met with LinearLayout.
thanks for your time
I ended up writing a custom view and calling a stacked xml file with:
View view=layoutInflater.inflate(R.layout.handlayout, this);
it seems to work and actually I like this solution better anyway because I'm including all three elements (in the 'column') into one view.

Categories

Resources