Here is the code that work :
In the code below everything work, but when i try to add a second view it crashes.
public void ClearAllV() {
ImageView IM2 = new ImageView(this);
HorizontalScrollView SW = (HorizontalScrollView) findViewById(R.id.horizontalScrollView1);
HorizontalScrollView.LayoutParams lp = new HorizontalScrollView.LayoutParams(
HorizontalScrollView.LayoutParams.WRAP_CONTENT,
HorizontalScrollView.LayoutParams.WRAP_CONTENT);
SW.removeAllViews();
IM2.setImageResource(R.drawable.have_fun);
SW.addView(IM2, lp);
}
But if i try to add a second imageview like the one below it crash,
public void ClearAllV() {
ImageView IM2 = new ImageView(this);
ImageView IM3 = new ImageView(this);
HorizontalScrollView SW = (HorizontalScrollView) findViewById(R.id.horizontalScrollView1);
HorizontalScrollView.LayoutParams lp = new HorizontalScrollView.LayoutParams(
HorizontalScrollView.LayoutParams.WRAP_CONTENT,
HorizontalScrollView.LayoutParams.WRAP_CONTENT);
SW.removeAllViews();
IM3.setImageResource(R.drawable.have_fun);
IM2.setImageResource(R.drawable.have_fun);
SW.addView(IM2, lp);
SW.addView(IM3, lp);
}
The ScrollView and HorizontalScrollView should only hold one child.
Usually you would have a LinearLayout as the only child of the HorizontalScrollView, and add your views to that.
From the ScrollView-documentation:
A ScrollView is a FrameLayout, meaning you should place one child in
it containing the entire contents to scroll;
[...]
A child that is often used is a LinearLayout in a vertical orientation, presenting a vertical array of top-level items that the user can scroll through
Note that this is about the ScrollView (not the HorizontalScrollView (the hsv doc says the same thing but with horizontal instead of vertical), and thus mentions a vertical layout.
Related
I'm creating the above popup, the content of which consists of rows of horizontal LinearLayout views within a main vertical LinearLayout. Each horizontal LinearLayout contains one ImageView and one TextView.
I'm creating this within a PopupWindow, and doing so programmatically so that I can change the ImageView source as required.
As you can see the first icon seems to take up a lot of space, despite having the same code generating it as the other icons.
Below is the code:
LinearLayout verticalLayout = new LinearLayout(context);
verticalLayout.setOrientation(LinearLayout.VERTICAL);
LinearLayout.LayoutParams mainLayoutParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);
verticalLayout.setLayoutParams(mainLayoutParams);
LinearLayout.LayoutParams layoutParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
LinearLayout.LayoutParams iconParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.MATCH_PARENT);
LinearLayout.LayoutParams textParams =
new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
//History row
LinearLayout historyLayout = new LinearLayout(context);
historyLayout.setLayoutParams(layoutParams);
historyLayout.setOrientation(LinearLayout.HORIZONTAL);
ImageView historyIcon = new ImageView(context);
historyIcon.setImageResource(R.drawable.small_book_grey);
historyIcon.setAdjustViewBounds(true);
historyIcon.setLayoutParams(iconParams);
historyLayout.addView(historyIcon);
TextView historyText = new TextView(context);
historyText.setLayoutParams(textParams);
historyText.setText("History");
historyLayout.addView(historyText);
verticalLayout.addView(historyLayout);
//Exam row...
//... (duplicate of history row)
I've tried playing around with the layout parameters, even creating a mock xml layout that displays the content as I'd like, to match the parameters to.
If anyone can give some advice on making that book icon the same size as the others, I'd be grateful.
Add a scaleType to ImageView of fitCenter
Write this code under historyIcon.setAdjustViewBounds(true);
historyIcon.setWidth()`
And put width according to your layout.
Although I didn't figure out why the first image was scaling differently to the other images, I did find another solution: Using compound left drawables.
historyText.getViewTreeObserver()
.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
#Override
public void onGlobalLayout() {
Drawable img = m_context.getResources().getDrawable(
R.drawable.small_book_grey);
img.setBounds(0, 0, img.getIntrinsicWidth() * historyText.getMeasuredHeight() / img.getIntrinsicHeight(), historyText.getMeasuredHeight());
historyText.setCompoundDrawables(img, null, null, null);
historyText.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
Manually setting the bounds to match the TextView worked. Seems clunky, but it was the only way I could get it to do what I was aiming for.
I want to add a scroll view to all the layouts that I have. But dynamically. Because the app will run in different screen sizes, and when I will get a screen size smaller than a specific size, then I want to show the layout in a scroll view.
So I made this method, it will be called on the check that the screen is small. I will pass my activity and I want to change the root layout to scroll view or just add a ScrollView as the root layout. So if the root layout is a LinearLayout, then I want to put that layout in the ScrollView. And I have not named all the layouts, meaning that I didn't give an ID to the layout, so I cannot use findViewById.
public static void SetActivityRoot(Activity c) {
View v = c.getWindow().getDecorView();
// View v = v.getRootView();
ScrollView sv = new ScrollView(c);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
sv.setLayoutParams(lp);
((ViewGroup)v.getParent()).removeView(v);
sv.addView((View) v);
((ViewGroup)v.getParent()).addView(sv);
}
It's giving me an error saying that "you cannot remove view from null" etc. Or that "you cannot add view to layout as it already has parent view". How can I make this work?
Finally solved my problem.
public static void SetActivityRoot(Activity c) {
View v = ((ViewGroup)c.findViewById(android.R.id.content)).getChildAt(0);
ScrollView sv = new ScrollView(c);
LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
sv.setLayoutParams(lp);
((ViewGroup) v.getParent()).removeAllViews();
sv.addView((View) v);
c.addContentView(sv, lp);
}
I have linear layout but bottom part not display if scrolling data is more then screen size.
Streaching Bottom Part when Using Scrollview inside the linearlayout, when scrolling data more then height of the device height.
If i have less data then vertical screen size then all button of bottom appears correctly.
public class TestGUI extends LinearLayout {
sv = new ScrollView(context);
hsv = new HorizontalScrollView(context);
this.addView(topLinearHorizonal);
hsv.addView(tableLayout);
sv.addView(hsv);
this.addView(sv);
this.addView(fullbottomLinearHorizonal);
}
Edited:
LinearLayout fullbottomLinearHorizonal= new LinearLayout(context);
fullbottomLinearHorizonal.setOrientation(VERTICAL);
fullbottomLinearHorizonal.addView(clearLinearHorizonal);
fullbottomLinearHorizonal.addView(bottomLinearHorizonal);
If you want to show fullbottomLinearHorizonal always at the bottom(visible) you can try below while adding views to TestGUI:
LinearLayout.LayoutParams svParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, 0, 1);
this.addView(sv, svParams);
LinearLayout.LayoutParams fullbottomParams = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, WRAP_CONTENT);
this.addView(fullbottomLinearHorizonal, fullbottomParams);
Edit: Also default orientation for LinearLayout is horizontal. See link.
You should better set it vertical at TestGUI:
this.setOrientation(VERTICAL);
If you want fullbottomLinearHorizonal at the end of the scroll content then you must add it inside of the scrollView.
I've a RelativeLayout which consists of an ImageView and TextView. Now, to this RelativeLayout I want to add a LinearLayout, which should be aligned below the TextView. Right now, the LinearLayout is added to the RelativeLayout, but it is not aligned below the TextView. Here is my code :
void addRatingToImage(RelativeLayout relativelLayout, Movies movieObject) {
ImageView ratingImageView;
LinearLayout ratingLayout = new LinearLayout(mContext);
ratingLayout.setOrientation(LinearLayout.HORIZONTAL);
double roundedRating = roundUpRating(Double.parseDouble(movieObject.mRating));
for(int i = 0; i < 5; i++) { //TODO: Check
ratingImageView = new ImageView(mContext);
if(i < roundedRating) {
ratingImageView.setBackgroundResource(R.drawable.star_2);
ratingLayout.addView(ratingImageView);
}
else {
ratingImageView.setBackgroundResource(R.drawable.star_1);
ratingLayout.addView(ratingImageView);
}
}
RelativeLayout.LayoutParams ratingLayoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, RelativeLayout.LayoutParams.WRAP_CONTENT);
TextView movieNameTextView = (TextView)relativelLayout.getChildAt(2);
ratingLayoutParams.addRule(RelativeLayout.BELOW, movieNameTextView.getId());
ratingLayout.setLayoutParams(ratingLayoutParams);
relativelLayout.addView(ratingLayout);
}
I have one doubt here. Does RelativeLayout.BELOW work, when it is applied to a different kind of layout, nested in a RelativeLayout? Thanks.
Yes, RelativeLayout.BELOW will work. It is recognized by parent RelativeLayout no matter what the child view class is.
According to your problem, I suppose that RelativeLayout is behaving that way because you've set fill_parent for your TextView movieNameTextView's layout width.
Im posting from my phone so please excuse stupid typos and formatting issues.
I have an activity which lists saved games that the player can load.
I created a simple layout xml file which defines a ScrollView. On load, I grab all the saved games and programatically add a view for each saved game to a vertically oriented LinearLayout child of the ScrollView.
The view for each game consists of a Horizontally oriented LinearLayout which in turn contains a Button and a vertically oriented LinearLayout. That LinearLayout in turn contains some TextViews and ImageViews (and one more LinearLayout which I'm ommitting here for the sake of clarity).
The hierarchy looks something like this (some details omitted).
ScrollView
LinearLayout - vertical
Each saved game:
LinearLayout - horizontal
Button - load game
LinearLayout - vertical
TextView - game name
TextView - date string
My problem:
I would like the top of the button and the "game name" texview to be vertically aligned but the TextView (or maybe it's LinearLayout parent) has some rogue padding on top that I can't get rid of. See screenshot for details.
LoadSaved class:
Note: mScrollView is badly named. It refers to the ScrollView's child LinearLayout.
public class LoadSaved extends Activity {
public LinearLayout mScrollView;
private MinerDb mDb;
public void onCreate(Bundle b) {
super.onCreate(b);
setContentView(R.layout.loadsaved);
mDb = new MinerDb(this);
mScrollView = (LinearLayout) findViewById(R.id.load_scroll_view);
Bundle[] savedGames = mDb.getSavedGames();
for (int i = 0; i < savedGames.length; i++) {
Bundle game = savedGames[i];
final int gameId = game.getInt("gameId");
String name = game.getString("name");
String date = game.getString("date");
Bundle player = game.getBundle("player");
int playerMoney = player.getInt("money");
int playerHealth = player.getInt("health");
LinearLayout gameContainer = new LinearLayout(getApplicationContext());
gameContainer.setPadding(5, 5, 5, 5);
gameContainer.setGravity(Gravity.TOP);
gameContainer.setOrientation(LinearLayout.HORIZONTAL);
gameContainer.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
Button loadButton = new Button(getApplicationContext());
loadButton.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
loadButton.setText("Load");
LinearLayout gameInfo = new LinearLayout(getApplicationContext());
gameInfo.setOrientation(LinearLayout.VERTICAL);
gameInfo.setPadding(10,0,10,10);
gameInfo.setGravity(Gravity.TOP);
gameInfo.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
TextView nameView = new TextView(getApplicationContext());
nameView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
nameView.setGravity(Gravity.TOP);
nameView.setText(name);
TextView dateView = new TextView(getApplicationContext());
dateView.setPadding(5,0,0,0);
dateView.setGravity(Gravity.TOP);
dateView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
dateView.setText(date);
LinearLayout playerView = new LinearLayout(getApplicationContext());
playerView.setOrientation(LinearLayout.HORIZONTAL);
playerView.setPadding(5,0,0,0);
playerView.setGravity(Gravity.TOP);
playerView.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
TextView playerMoneyView = new TextView(getApplicationContext());
playerMoneyView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
playerMoneyView.setPadding(0,0,10,0);
playerMoneyView.setTextColor(Color.GREEN);
playerMoneyView.setText("$" + playerMoney);
TextView playerHealthView = new TextView(getApplicationContext());
playerHealthView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
playerHealthView.setPadding(0,0,10,0);
playerHealthView.setTextColor(Color.RED);
playerHealthView.setText(playerHealth + "%");
playerView.addView(playerMoneyView);
playerView.addView(playerHealthView);
gameInfo.addView(nameView);
gameInfo.addView(dateView);
gameInfo.addView(playerView);
gameContainer.addView(loadButton);
gameContainer.addView(gameInfo);
mScrollView.addView(gameContainer);
loadButton.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
Log.e("LoadSaved", "LoadSaved::onCreate: Clicking: " + gameId);
Intent loadGameIntent = new Intent(LoadSaved.this, Miner.class);
loadGameIntent.putExtra("load_game", gameId);
startActivity(loadGameIntent);
finish();
}
});
}
}
}
loadsaved.xml
<LinearLayout
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:id="#+id/load_scroll_view" />
</ScrollView>
</LinearLayout>
If you want any kind of alignment, why don't you use a RelativeLayout? That's basically designed to align one view with another. android:layout_alignTop sounds like something you want.
(And, of course, verify that the padding values are the same in all controls, but I'm sure you did that.)
Why don't you try using a ListView for that kind of gui.
You will still need to define a row xml.
+1 to the answers suggesting ListView and RelativeLayout. For this type of situation you probably want a ListView with an item layout using RelativeLayout. (ListView will scale much better if there are many items, and if this is for a list of saved games it seems like this could grow quite a bit.) For this type of UI it's recommended to have the whole row/list item clickable rather than use a small Load button, but that's a design issue and ultimately up to you.
Don't use getApplicationContext for creating your views. Activity is a Context, just pass this in your case.
By default LinearLayouts try to align child views by their text baseline if present. Note that the bottom of your button's Load text aligns perfectly with the CURRENT_GAME text in your screenshot. Try gameContainer.setBaselineAligned(false).
Normally your gameInfo layout would only report the baseline of one of its children if you set a baselineAlignedChildIndex, but it looks like this behavior changed between cupcake and eclair when creating LinearLayouts programmatically. (Link to the commit that changed it in AOSP here.)