I have a question about Android.
Assume we have our main xml layout file, and defining there a place holder by using (for example) a FrameLayout. Also assume we have 2 other xml layout files displaying any content.
So what I want to do is inject dynamically and programmtically one of the two layouts into the place holder. I know there exists the concept of Activitis, Fragments, ViewFlipper etc. But I find it comfortable to do things like this:
public class MainActivity extends Activity {
private FrameLayout placeHolder;
private View view1;
private View view2;
private RelativeLayout canvasPlaceHolder;
private PuzzleCanvas canvas;
private TextView infoLabel;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// init gui
setContentView(R.layout.activity_main);
// Load layouts from xml
LayoutInflater factory = getLayoutInflater();
view1 = factory.inflate(R.layout.view1, null);
view2 = factory.inflate(R.layout.view2, null);
}
}
with for example a Button on screen that does something like this:
#Override
public void onClick(View v) {
placeHolder.removeView(view1);
placeHolder.addView(view2);
}
For example to show a loadingAnimation (view2) instead of the normal content (view1) and so I can define both views comfortable and independent in xml.
Is the use of LayoutInflater commendable? What about the performance and memory management? What do you think about this? Is that a common way in Android?
Use 'include ' tag on the xml's frame layout to include both your xml's in the main xml. All you have to do is switch their ' VISIBILITY' through java according to ur app logic.
eg: on a listener, set :
public void onClick(View v) {
innerView1.setVisibilty(View.INVISIBLE);
innerView2. setVisibilty(View.VISIBLE);
}
// Load layouts from xml
LayoutInflater factory = getLayoutInflater();
view1 = factory.inflate(R.layout.view1, null);
view2 = factory.inflate(R.layout.view2, null);
Using LayoutInflater is ok, but I suggest not directly do this action in onCreate, if your layout is very complex, it might cause ANR (draw layout over 5 secs). Since these two views only appears after user reaction, I prefer to do with sendEmptyMessage with handler.
onCreate(...){
handler.sendEmptyMessage(1);
}
private Handler handler = new Handler(){
#Override
public void handleMessage(final Message msgs) {
if(msgs.what == 1){
view1 = factory.inflate(R.layout.view1, null);
view2 = factory.inflate(R.layout.view2, null);
}
}
}
Related
I need to have an scroll with items together, and the selected item should expand a part down.
I am currently using a Gallery (I tried with viewflow and viewpager, but the items have much space between them), but I need to know how can I do this effect.
I have 2 ideas, but i don't know how can I implement it.
1) The expandable part is a LinearLayout with visibility=gone, and when the item is selected, this layout should be visible. (Gallery do not have "onItemSelectedListener")
2) Treat each element as a fragment (once I use a Viewpager that use this, https://github.com/mrleolink/SimpleInfiniteCarousel)
It does not necessarily have to be a gallery, any idea is welcome
I am working on an Activity.
Depends on the behavior that you want. Some questions can more than one item be expanded at a time? Do you want the views to be paged (snap into place) or smooth scroll them?
One Suggestion I have is to make a custom view for the individual cells. Then add them programmatically to a HorizontalScrollView Object.
HorizontalScrollView hsv = new HorizontalScrollView(activity);
LinearLayout hll = new LinearLayout(activity);
hll.setOrientation(LinearLayout.HORIZONTAL);
for(int i=0;i<items.length();i++){
hsv.addView(new CustomExpandView(item));
}
The CustomExpandView would be used for your cells and could be something like this...
public class CustomExpandView extends RelativeLayout implements OnClickListener {
MyActivity mActivity = null;
ImageView ivImage, ivOverImage;
RelativeLayout rlView;
public CustomExpandView(Context context) {
super(context);
initialize();
}
public CustomExpandView(Context context, AttributeSet attrs) {
super(context, attrs);
initialize();
}
public void initialize() {
mActivity = (MyActivity) this.getContext();
LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.custom_cell_expand, this, true);
//you can initialize subviews here
rlView = (RelativeLayout) getChildAt(0);
ivImage = (ImageView) rlView.getChildAt(0);
ivOverImage = (ImageView) rlView.getChildAt(1);
rlView.setOnFocusChangeListener(new OnFocusChangeListener(){
#Override
public void onFocusChange(View v, boolean hasFocus) {
LinearLayout expand = v.findViewById(R.id.view_i_want_to_expand);
if(hasFocus)
expand.setVisibility(View.VISIBLE);
else
expand.setVisibility(View.GONE);
}
});
}
You gave the answer yourself. You can use a ViewPager, with fragments, and have an animation to extend the lower part of the window. Depends on whether you want the windows to be full screen or not. A viewpager doesn't necessarily need fragments, you can use ordinary views, and an appropriate adapter. Just play with it and see which solution you like most.
Next time, just create the code and the app, and ask a much more specific question, with code to illustrate the issue you're experiencing.
You could simply define a TableView with just one TableRow (or as many as you need) and set a onClickListener for each of those Views inside the TableRow, which would make that on any click, the selected View would expand itself.
I don't know whether you'll have a static number of Views inside that row or you'll construct them dynamically, but this should work for any of them, the real "work" here about populating that row.
Once you have your row of Views, simply declare an onClickListener() on each of them. For example, this should be enough:
OnClickListener myListener = new OnClickListener() {
#Override
public void onClick(final View v) {
v.setVisibility(View.VISIBLE);
}
};
And as the onClick event for all of your items inside the TableRow:
for (View v : myTableRowViews)
v.setOnClickListener(myListener);
This has a disadvantage: You can know which View has been clicked for selection, but natively you cannot know which has been deselected, so you'll need to keep track of the last selected tab declaring a class-wide variable and setting it each time onClick() is fired, so your listener will become something like this:
// In your class declare a variable like this
View lastSelected = null;
OnClickListener myListener = new OnClickListener() {
#Override
public void onClick(final View v) {
if (lastSelected != null)
lastSelected.setVisibility(View.GONE);
v.setVisibility(View.VISIBLE);
lastSelected = v;
}
};
Additionally, you can set an animation to the effect to make it more attractive, but mainly this is the idea.
One last thing: To make it work this way you'll need to set the layout_height of both your TableRow and the View items inside, so it may expand afterwards when you set the additional part as visible. Also, to make it look good all of your Views will have to be the same height (both in the reduced and extended state).
i have an activity that displays two buttons , on click of call button i want to show another activity as shown in image.
Please help .How to achieve this
One way to do it is to have a custom layout which you add to each activity with a viewgroup as such:
private View view;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ViewGroup parent = (ViewGroup) findViewById(R.id.linearLayout1);
view = LayoutInflater.from(getBaseContext()).inflate(R.layout.custom_layout,
null);
parent.addView(view);
Then you just need to implement your listeners and whatnot further down :)
You need to create xml file of these two buttons and add that new xml into old one by using Layout Inflator. for e.g
1) your new xml
LayoutInflator buttons = LayoutInflater.from(getBaseContext()).inflate(R.layout.buttons,
currentxml, false);
2) your old xml parent referenced through id -->
RelativeLayout relativeLayout = (RelatveLayout) findViewById(R.id.oldxml);
3) now add..
relativeLayout.addView(buttons);
You can Use Pop up By Adding this in your function. Popuser is a xml file which you want to inflate.
public void popupshow(){
try{
LayoutInflater inflater=(LayoutInflater)SRSDMain.this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
Display display=getWindowManager().getDefaultDisplay();
int width=display.getWidth()/2;
int height=display.getHeight()/2;
View pop=inflater.inflate(R.layout.popupuser,null,false);
pop.measure(View.MeasureSpec.UNSPECIFIED,View.MeasureSpec.UNSPECIFIED);
height=pop.getMeasuredHeight();
width=pop.getMeasuredWidth()+50;
pu=new PopupWindow(pop,width,height,true);
pu.showAtLocation(findViewById(R.id.ll3),Gravity.CENTER,1,1);
Button btn=(Button)pu.getContentView().findViewById(R.id.button);
btn.getBackground().setColorFilter(new LightingColorFilter(0xFF505450,0xFF101010));
btn.setTextColor(Color.WHITE);
btn.setTypeface(null,Typeface.BOLD);
btn.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
//anything you want to do
pu.dismiss();
}
});
}
catch(Exception ex){
//Catch The Exception
}
}
}
I have an activity with a LinearLayout which I want to add multiple buttons to. These buttons are Custom Views which I inflate. I need to add these custom buttons to my Linear Layout in code. All of this works.
What I cant get to work is to use findViewById in my custom button after I have inflated it so I can set its properties. findViewById returns null.
Activity Code:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.levelbrowser);
LinearLayout uttonLayout = (LinearLayout)findViewById(R.id.ButtonLayout);
LevelBrowserButton button1 = new LevelBrowserButton(this, "Level 1");
ButtonLayout.addView(button1);
}
Custom Button Code:
public LevelBrowserButton(Context context, String name)
{
super(context);
LayoutInflater inflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View layout = inflater.inflate(R.layout.levelbrowser_button, this);
TextView nameTextView = (TextView) layout.findViewById(R.id.NameTextView);
// nameTextView = null!
NameTextView.setText("test"); // This will throw an exception
}
I have read through many posts on the internet and still cant get this to work. I have also tried "Clean..." in Eclipse on my project.
MainActivity.java:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
this.setTitle(R.string.app_name);
setContentView(new SampleView(this));
}
}
SampleView.java:
public class SampleView extends View {
#Override
protected void onDraw(Canvas canvas) {
if (certaincondition = true) {
//add elements to canvas etc
} else {
//How do I do the below? The layout is defined in xml.
//I do not want to use Intent. Please help me
//create a layout from resource R.layout.idAbout and transfer control.
}
}
}
Use a layout inflater:
View newRootViewElement;
LayoutInflater li = (LayoutInflater)getSystemService(Context.LAYOUT_INFLATER_SERVICE);
newRootViewElement= li.inflate(R.layout.idAbout, null);
You can inflate a layout using
View.inflate(getContext(), R.layout.idAbout, viewParent);
where viewParent is a ViewParent that will be the parent of the inflated view (and can be null).
But what are you trying to do? It's more than a little odd to start a new activity or to modify the view hierarchy from within onDraw(). You might want to post a runnable to a Handler that will do what you want on the next cycle of the event loop. To start a new activity (such as displaying “About” info for the app) you should take a look at the Intent class.
I have set up a ViewFlipper in my Android application that will host a series of windows to display messages. Each window should correspond to a different set of messages, similar to multiple open chats. For each window I am using the same window.xml view to bring the view onto the screen, it also has the variable for the EditText need to edit.
For reference I am creating and adding children as follows:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
detector = new GestureDetector(this,this);
setContentView(R.layout.viewflip);
flipper = (ViewFlipper) findViewById(R.id.viewflip);
addChild(flipper);
addChild(flipper);
}
private void addChild(ViewFlipper flip){
int index=0;
View view = getView();
if(flip.getChildCount()==0){
flip.addView(view,index);
}
else{
flip.addView(view,flip.getChildCount());
}
}
private View getView(){
LayoutInflater inflater = this.getLayoutInflater();
View view = inflater.inflate(R.layout.window, null);
return view;
}
As you can see, I am basically duplicating the view (I'm not sure this is the proper approach to my design). So if I were to do something in the onCreate function after adding the children, such as
EditText messageHistoryText = (EditText) findViewById(R.id.messageHistory);
messageHistoryText.append("Testing :\n");
I see the text on both windows.
I thought that something like this would be better:
View v1 = flipper.getChildAt(1);
EditText messageHistoryText2 = (EditText) v1.findViewById(R.id.messageHistory);
messageHistoryText2.append("Testing2 :\n");
but when I use that one, I don't see anything at all. Perhaps there is a mistake on adding the children. Perhaps I can't use the same view, or perhaps I am selectively changing an EditText in an incorrect way.
Tips?
Try the following,
EditText messageHistoryText = flip.getChildAt(j).findViewById(R.id.messageHistory);
where j represents the child position in ViewFlipper.