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);
}
Related
I'm adding multiple Views by code into Layout. I need each new View to be above previous one(top of the parent layout).
EDIT: To be more accurate I'll describe what the app module should does. User start with clean screen and one button at the bottom of the screen. The button adds a View at the top of the screen. Next clicks should add next views above previous ones to make the newest View be on the top of a container. The app saves state and on restart user see views in the same order.
Call the following method from Button's onClick Event.
private final int LAYOUT_TOP_INDEX = 0;
private void addViewOnTop(View view){
if(layout != null && view !=null)
layout.addView(view, LAYOUT_TOP_INDEX);
}
where 'layout' is your Layout (e.g., LinearLayout) to which the View is to be added.
Would really need more information from you to give a more accurate answer, but if you're saying what i think you are then you can just add these views to a LinearLayout with orientation set to vertical.
And assuming you're iterating through a list to dynamically add views, instead of incrementing from 0, increment down from the size of the list.
for(int i = size; i >= 0; i--){
linearLayout.add(new TextView(Context));
}
View positions inside ViewGroups are defined by the LayoutParams
How does this happen? Views pass their LayoutParams to their parent ViewGroups
//100% programatic approach with simple LayoutParams
LinearLayout myLinearLayout = new LinearLayout(this);
//if the **parent** of the new linear layout is a FrameLayout
FrameLayout.LayoutParams layoutParams =
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.MATCH_PARENT);
//or if you have the XML file you don't have to worry about this
//myLinearLayout = (LinearLayout)findViewById(R.id.my_simple_linear_layout);
//you could have a LinkedList<TextView>
LinkedList<TextView> textViewList = new LinkedList<>();
//assuming the order is the correct order to be displayed
Iterator<TextView> descendingIterator = textViewList.descendingIterator();
while(descendingIterator.hasNext())
{
//just add each TextView programatically to the ViewGroup
TextView tView = descendingIterator.next();
myLinearLayout.addView(tView);
}
Just like we defined LayoutParams for the LinearLayout we could also define LayoutParams for the TextView
IMPORTANT: when setting LayoutParams you need to be sure they fit the VIEWGROUP, that is the parent of the View being added
private TextView textViewFactory(String myText) {
TextView tView = new TextView(getBaseContext());
//controling the position relatively to the PARENT
//because you are adding the textview to a LINEAR LAYOUT
LinearLayout.LayoutParams paramsExample =
new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT, 1.0f);
tView.setLayoutParams(paramsExample);
//configuring the insides of the textview
//you can also do all kinds of stuff programatically
tView.setGravity(Gravity.CENTER_HORIZONTAL);
tView.setPadding(10, 10, 10, 10);
tView.setTypeface(Typeface.DEFAULT_BOLD);// (null, Typeface.BOLD_ITALIC);
tView.setTypeface(Typeface.SANS_SERIF);
tView.setTypeface(null, Typeface.ITALIC);
tView.setTypeface(Typeface.defaultFromStyle(R.style.AppTheme));
tView.setId(R.id.aux_info);
tView.setText(myText);
//.........all kinds of stuff really
return tView;
}
If you mean adding a view programmatically so that the new one is added above the previous one, instead of below it, then I suggest this:
Maintain an ArrayList with the items you want to turn into views
Put them into a ListView
When you want to add a new view that must appear at the top of the list, insert it as the first element of your ArrayList and recreate the ListView from it.
I want to create a layout (see class RosterPlayerView below) that comprises an image with text below it and then instantiate that view multiple times in a relative layout. I used relative layout instead of linear as the layout will become more complex.
When I first ran the code below (but without the setId calls) the text appeared above the image. Thanks to this stack overflow article I discovered that relative layout needs unique widget ids to work. But when I added the setId() calls the text view is not displayed at all.
What am I doing wrong?
public class RosterPlayerView extends RelativeLayout {
ImageView imageView;
TextView textView;
static int layoutId = 100;
public RosterPlayerView(Context context, int playerId, Drawable photo) {
super(context);
imageView = new ImageView(context);
textView = new TextView(context);
addView(imageView, new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
imageView.setId(layoutId++);
RelativeLayout.LayoutParams timeLayoutParams = new RelativeLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
timeLayoutParams.addRule(RelativeLayout.BELOW, imageView.getId());
addView(textView, timeLayoutParams);
imageView.setImageDrawable(photo);
textView.setId(layoutId++);
textView.setText("0:00");
}
}
a LinearLayout would be an awful lot simpler for what you are trying to do. So would inflating an XML layout, for that matter.
Try to set the Id of you imageView before adding it to the layout.
You can also create a LinearLayout with the imageView and textView inside before adding it to the RelativeLayout
I have a question regarding Android Activitys:
An Activity has the Method addContentView(View) while a ViewGroup has a (similar?) addView(View) Method.
Unfortunately its undocumented where the View from addContentView is placed. Is it like a LinearLayout just adding the View to the bottom, or is it more like a FrameLayout, which adds its Views "onTop" ? Does it depend on the ViewGroup set by setContentView?
If I dive into the sources I see that addContentView will call Window's abstract Method addContentView. Unfortunately I cannot see which class is implementing this Method. So whats the behaviour of Activitys addContentView exactly?
The base layout of every activity is a FrameLayout. This means the layout you usually set via setContentView() is a child of this layout. addContentView() adds just another child, therefore it behaves like a FrameLayout (which means it adds new UI elements above existing ones).
You can check this by using a tool called hierachyviewer from your ANDROID_SDK\tools folder. Here are two screenshots:
This is the layout before calling addContentView(), my activity consists of the default FrameLayout, holding a LinearLayout with a Button (my layout here). This is reflected in the bottom row here, the other elements above are the title/statusbar.
After adding a TextView via addContentView() it looks like this. You can see that the base FrameLayout got a new child.
public void addContentView(View view,
LayoutParams params) {
mActivity.addContentView(view, params);
}
//
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);
}
//
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout mainLayout =
(LinearLayout)findViewById(R.id.mainlayout);
//newButton added to the existing layout
Button newButton = new Button(this);
newButton.setText("Hello");
mainLayout.addView(newButton);
//anotherLayout and anotherButton added
//using addContentView()
LinearLayout anotherLayout = new LinearLayout(this);
LinearLayout.LayoutParams linearLayoutParams =
new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT);
Button anotherButton = new Button(this);
anotherButton.setText("I'm another button");
anotherLayout.addView(anotherButton);
addContentView(anotherLayout, linearLayoutParams);
}
}
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.
I need to layout the views from the RIGHT side in a Fragment in Android, however, android did not layout the sub views as what I thought.
I tried to add a TableLayout and an ImageView to a LINEARLAYOUT, the width of the ImageView was fixed and the width of TableLayout is dynamic. Furthermore, the ImageView need to be located on the right side.
Part of the source code:
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
Context c = getActivity().getApplicationContext();
LinearLayout l = new LinearLayout(c);
LayoutParams params = new LayoutParams(LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT, 0);
params.gravity = Gravity.RIGHT;
l.setLayoutParams(params);
// l.setGravity(Gravity.RIGHT);
PankouAttachmentView pav = new PankouAttachmentView(c, null);
pav.setLayoutParams(params);
l.addView(pav);
ImageView iv = new ImageView(c);
iv.setClickable(true);
iv.setFocusable(true);
iv.setImageResource(R.drawable.testarrow);
iv.setMaxWidth(BUTTON_WIDTH);
iv.setLayoutParams(new LayoutParams(BUTTON_WIDTH,
LayoutParams.MATCH_PARENT));
l.addView(iv);
return l;
}
Any help will be appreciated.THX :)
I'm not sure I completely understand your question but have you tried using a relative layout? Relative layout lets you accomplish much easier than a linear layout. See the android hello views tutorial.