Replace a view with other view By code - android

I want to replace a view with other other by code
For example i need to change a imageview to progressBar by code.
public void changeToProgressBar(ImageView imageview,Context context){
ProgressBar one = new ProgressBar(context);
one.setLayoutParams(imageview.getLayoutParams());
imageview.setVisibility(View.GONE);
one.setVisibility(View.VISIBLE);
//NOW I NEED TO PLACE 'one' EXACTLY THE PLACE WHERE 'imageview' WAS THERE
}
I need to use this many place. I know to set by sending the parent viewgroup.
Is there anyway to get the parent viewgroup from imageview
Thanks

This is trivial to do and other posters have linked to or hinted at the solution. You can get the parent of a View by View.getParent(). You need to cast the returned value to a ViewGroup (q: can a View's parent be anything else than a ViewGroup?). Once you have the parent as a ViewGroup you can do ViewGroup.removeChild(viewToRemove) to remove the old view and add the new one using ViewGroup.addChild(viewToAdd).
You might also want to add the new view at the same index as the remove view to make sure that you don't put the new view on top of or below other views. Here's a complete utility class for you to use:
import android.view.View;
import android.view.ViewGroup;
public class ViewGroupUtils {
public static ViewGroup getParent(View view) {
return (ViewGroup)view.getParent();
}
public static void removeView(View view) {
ViewGroup parent = getParent(view);
if(parent != null) {
parent.removeView(view);
}
}
public static void replaceView(View currentView, View newView) {
ViewGroup parent = getParent(currentView);
if(parent == null) {
return;
}
final int index = parent.indexOfChild(currentView);
removeView(currentView);
removeView(newView);
parent.addView(newView, index);
}
}
Something to consider is that you'll lose any positioning in a relative layout when you replace one view with another. One solution to this would be to make sure that the view you want to replace is wrapped in a another view and that wrapped container view is the one that is positioned in a relative layout.

Retrieve the view you would like to change by calling findViewById() from the activity level http://developer.android.com/reference/android/app/Activity.html#findViewById(int) Then find the sub view you would like to change http://developer.android.com/reference/android/view/View.html#findViewById(int)
Then use the functions from http://developer.android.com/reference/android/view/ViewGroup.html to manipulate the view.

Just as User333 described that could be one solution..
It's also possible to delete the imageview by calling yourview.removeView(imageview) and then create your progress bar and put that inside the view instead by yourview.addView(progressbar)

You can change Android Activities view from any other simple java class or in other activity.
you only need to pass current view and get your element by this view you want to change As :
public class MainActivity extends Activity{
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Setting UI
View currentView = getWindow().getDecorView().getRootView();
//showHeaderLayout is simple java class or it can be any activity
changeLayout.setView(currentView);
}
Class : changeLayout
public class changeLayout{
public static View setView(final Activity activity, final View myView)
{
// myView helps to get Activity view , which we want to change.
TextView tv = (TextView) myView.findViewById(R.id.tv);
tv.setText("changs Text Via other java class !!");
}
}
Note : Passing view makes you able to change any activity view outside an Activity.

I think following ould be the best approach as in this we don't need to set layout params.
setvisibility(Visibility.GONE)
setvisibility(Visibility.VISIBLE)

I am sure that following link not only help you, but even shows you the direction for your requirement. https://stackoverflow.com/a/3760027/3133932

For this, take both imageview and progressBar and set the visibility according to your requirements.
For example
If you want progressBar to be visible, put setvisibility(Visibility.GONE) for imageview and put setvisibility(Visibility.VISIBLE) for progressBar

Related

Adding a View makes a ListView within a fragment to refresh

This might be a little bit hard to explain, so the best way I can think of, is providing you a Video showing up the issue.
In the Video I show myself scrolling listview, and after 5 seconds, a View is created and added inside that holder in the bottom. In that moment, listview is refreshed.
http://tinypic.com/player.php?v=vpz0k8%3E&s=8#.U0VrIvl_t8E
The issue is the following:
I've an Activity with a layout that consists of a:
Fragment (above RelativeLayout), match parent, match parent.
RelativeLayout, as wrap content.
The fragment displays a ListView with animations for every row.
If I add a View on the "RelativeLayout", it makes the fragment to readjust to the new size, as it's set above this RelativeLayout, so every Row is rebuilt again.
Do you guys think in any way to avoid this?
EDIT: Sourcecode:
https://bitbucket.org/sergicast/listview-animated-buggy
Don't start the animation if the layout process for the added footer view is running. The end of the layout process can be determined using the ViewTreeObserver (the start obviously starts with adding the footer view):
hand.postDelayed(new Runnable() {
#Override
public void run() {
ViewTreeObserver viewTreeObserver = holder.getViewTreeObserver();
viewTreeObserver.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
holder.getViewTreeObserver().removeGlobalOnLayoutListener(this);
mIgnoreAnimation = false;
}
});
mIgnoreAnimation = true;
holder.addView(viewToAdd);
}
}, 5000);
Add this method to your Activity:
public boolean ignoreAnimation() {
return mIgnoreAnimation;
}
And check it in your Fragment:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Context context = FragmentTest.this.getActivity();
TextView tv = new TextView(context);
tv.setText("Pos: " + position);
tv.setTextSize(35f);
if (runAnimation()) {
Animation anim = AnimationUtils.loadAnimation(context, R.anim.animation);
tv.startAnimation(anim);
}
return tv;
}
private boolean runAnimation() {
Activity activity = getActivity();
if (activity != null && activity instanceof MainActivity) {
return ! ((MainActivity)activity).ignoreAnimation();
}
return true;
}
Of course the whole Activity - Fragment communication can be improved considerably but the example gives you the idea how to solve the problem in general.
While it prevents the animation from being started, it doesn't prevent the ListView from being refreshed although the user won't notice. If you are concerned about performance you can improve the Adapter code by re-using the views:
#Override
public View getView(int position, View convertView, ViewGroup parent) {
Context context = FragmentTest.this.getActivity();
TextView tv = null;
if (convertView != null && convertView instanceof TextView) {
tv = (TextView) convertView;
}
else {
tv = new TextView(context);
}
Yes, I can think of a possible way to solve this.
Your problem is:
You have set layout params of your holder to wrap_content. By default, when it has no content, it is "zero-sized" somewhere in the bottom and invisible to you (not invisible in terms of Android, though, sic!)
When you add a View to this holder, the framework understands, that the size of your holder container is different now. But this container is a child of another container - your root RelativeLayout, which, in turn, contains another child - your <fragment>.
Thus, framework decides, the root container alongside with its children should get laid out again. That's why your list gets invalidated and redrawn.
To fix the issue with list getting invalidated and redrawn, simply specify some fixed layout parameters to your holder. For example:
<RelativeLayout
android:id="#+id/holder"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true" >
</RelativeLayout>
That will prevent the list from being redrawn. But in that case you'll get your holder displayed from the very beginning.
Yes. This is the expected behavior of RelativeLayout
You are adding the ListView Fragment and TextView into a RelativeLayout, So whenever there is a change in the child view dimension, will affect the other child in the RelativeLayout.
So here when you add a new TexView , the other child Fragment is affected even though its height is match_parent.
You can fix this only by changing the parent layout to LinearLayout.

Dynamically Add and Remove Views from Layout

I'm working on one demo project in that I had create one XML file containing some views like ImageView, EditText. I'm loading this XML file on FrameLayout at runtime. At one point I want to remove all that views and again want to display them, I used removeView() method on button click but it does not work for me,,Please tell me the right way to do it..
public class Demo extends Fragment implements OnClickListener, OnTouchListener{
//Declaration of framelayout
FrameLayout f;
//Declaration of imageview
ImageView imageview;
View view, framelayoutview;
File file;
EditText etcardname, EditTextUserName,EditTextUsesrMobNumber,EditTextUsesrEmailID,EditTextUsesrAddress;
TextView dialogtesting;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
view = inflater.inflate(R.layout.activity_modify_card ,container, false);
framelayoutview = inflater.inflate(R.layout.frame_layout_data ,container, false);
captureImageInitialization();
Initialize();
return view;
}
// Initialization of all views components
private void Initialize() {
f=(FrameLayout)view.findViewById(R.id.framelayout);
Button btneditcardreset=(Button)view.findViewById(R.id.buttonresetcard);
btneditcardreset.setOnClickListener(this);
Bundle bundle = this.getArguments();
int myInt;
myInt = bundle.getInt("position");
imageview=(ImageView)framelayoutview.findViewById(R.id.imageViewicon);
EditTextUserName=(EditText)framelayoutview.findViewById(R.id.modifycardeditTextusername);
EditTextUsesrMobNumber=(EditText)framelayoutview.findViewById(R.id.editTextmobilesnumber);
EditTextUsesrEmailID=(EditText)framelayoutview.findViewById(R.id.editTextemailid);
EditTextUsesrAddress=(EditText)framelayoutview.findViewById(R.id.editTextaddress);
imageview.setOnTouchListener(this);
EditTextUserName.setOnTouchListener(this);
EditTextUsesrMobNumber.setOnTouchListener(this);
EditTextUsesrEmailID.setOnTouchListener(this);
EditTextUsesrAddress.setOnTouchListener(this);
f.addView(framelayoutview);
}
#Override
public void onClick(View v){
if(v.getId()==R.id.buttonresetcard){
if(framelayoutview.getParent()!=null){
f.removeAllViews();
}
f.addView(framelayoutview);
}
}
Sorry to all I forgot to tell that I provided OnTouchListener so that I can move the views anywhere in Layout. So when I press reset button all Views should get move back to their original location means where they were at on first load..
you can use
imageview.setVisibility(View.GONE);
And
imageview.setVisibility(View.VISIBLE);
on particular event
If you had added your views dynamically to your FrameLayout then you can remove them.
Otherwise, if you showing your views from XML which are exist inside the frameLayout XML then you can't remove them but you can hide them from showing by setting setVisibility(View.GONE) or setVisibility(View.INVISIBLE).
Try this-
#Override
public void onClick(View v){
if(v.getId()==R.id.buttonresetcard){
if(framelayoutview.getParent()!=null){
f.setVisibility(View.GONE);
}
f.addView(framelayoutview);
}
}

LayoutInflater for using xml and View class

after I asked if I should use XML or a View class for my project you told me, that I should do everything possible in XML and use a class for the rest. You told me, that animating Sprites isn't possible with XML so I wanted to make a View Class. I got the tip to google "LayoutInflater" for this and I did.
There aren't many Informations about inflaters so I visited android's developers database and tried to find out how this works.
As far as I know now, you have to put something into the onCreate method of your main game activity (the setContentView has to be the mainXML).
So now I created a LinearLayout in my mainXML and called it "container" and made this being a ViewGroup called "parent".
Now I have created a global variable "private View view" and wrote this line:
view = LayoutInflater.from(getBaseContext()).inflate(new ViewClass(this),
null);
Thw Problem now is that u can't inflate a class like this and I think I'm doing this whole inflating thing wrong.
Do you have any tips and tricks for me for making it work to have a LinearLayout in my mainXML and being able to make the content from my View Class appear in it?
EDIT:
Got it to work without errors, but nothing happens if I start my game now.
Here is the code pls answer if u have any solutions:
super.onCreate(savedInstanceState);
// inflate mainXML->
View mainView = getLayoutInflater().inflate(R.layout.activity_game, null);
// find container->
LinearLayout container = (LinearLayout) mainView.findViewById(R.id.container);
// initialize your custom view->
view = new GameLayout(this);
// add your custom view to container->
container.addView(view);
setContentView(R.layout.activity_game);
And my GameLayout:
public GameLayout(Context context)
{
super(context);
}
#Override
protected void onDraw(Canvas canvas)
{
canvas.drawColor(Color.BLACK);
}
There are two ways of going about this. I'll show you one of them. Do the following in your onCreate(Bundle) before calling setContentView(...):
// inflate mainXML
View mainView = getLayoutInflater().inflate(R.layout.mainXML, null);
// find container
LinearLayout container = (LinearLayout) mainView.findViewById(R.id.container);
// initialize your custom view
view = new ViewClass(this);
// add your custom view to container
container.addView(view);
Finally:
setContentView(mainView);
Alternatively, you can place your custom view inside mainXML:
<your.package.name.ViewClass
android:id="#+id/myCustomView"
android:layout_width="match_parent"
android:layout_height="match_parent"
.... />

Android: How to get a view given an activity inside a normal class?

I have a normal class (not an activity). Inside that class, I have a reference to an activity.
Now I want to access a view (to add a child) contained in the layout xml of that activity.
I don't know the name of the layout file of that activity. I only know the ID of the view, which I want to access (for example: R.id.my_view).
How can I do that?
Regarding the NullPointerException (which you should add to the question), always make sure you've called setContentView() in your Activity before trying to access a View defined in XML. Example usage:
public class MainActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
...
}
...
}
Then, somewhere,
ViewGroup group = (ViewGroup) context.findViewById(R.id.group); // In your example, R.id.my_view
The reason you need to have called setContentView() is that before it's called, your View(Group) doesn't exist. Because findViewById() is unable to find something that doesn't exist, it returns null.
As simple as that!
View view = activity.findViewById(R.id.my_view);
In case of the Layout:
LinearLayout layout = (LinearLayout) activity.findViewById(R.id.my_layoutId);
And to add the Views:
layout.addView(view);
You could make your method accept an Activity parameter and then use it to find the view by id.
Ex:
public class MyClass{
public void doSomething(Activity context){
TextView text=(TextView)context.findViewById(R.id.my_textview);
}
}
Then in your activity:
obj.doSomething(YourActivity.this);

Add an array of buttons to a GridView in an Android application

I have an application that will have 5-15 buttons depending on what is available from a backend. How do I define the proper GridView layout files to include an array of buttons that will each have different text and other attributes? Each button will essentially add an item to a cart, so the onClick code will be the same except for the item it adds to the cart.
How can I define an array so I can add a variable number of buttons, but still reference each of them by a unique ID? I've seen examples of the arrays.xml, but they have created an array of strings that are pre-set. I need a way to create an object and not have the text defined in the layout or arrays xml file.
Update - Added info about adding to a GridView
I want to add this to a GridView, so calling the [addView method](http://developer.android.com/reference/android/widget/AdapterView.html#addView(android.view.View,%20int) results in an UnsupportedOperationException. I can do the following:
ImageButton b2 = new ImageButton(getApplicationContext());
b2.setBackgroundResource(R.drawable.img_3);
android.widget.LinearLayout container = (android.widget.LinearLayout) findViewById(R.id.lay);
container.addView(b2);
but that doesn't layout the buttons in a grid like I would like. Can this be done in a GridView?
In the following code, you should change the upper limits of the for to a variable.
public class MainActivity
extends Activity
implements View.OnClickListener {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TableLayout layout = new TableLayout (this);
layout.setLayoutParams( new TableLayout.LayoutParams(4,5) );
layout.setPadding(1,1,1,1);
for (int f=0; f<=13; f++) {
TableRow tr = new TableRow(this);
for (int c=0; c<=9; c++) {
Button b = new Button (this);
b.setText(""+f+c);
b.setTextSize(10.0f);
b.setTextColor(Color.rgb( 100, 200, 200));
b.setOnClickListener(this);
tr.addView(b, 30,30);
} // for
layout.addView(tr);
} // for
super.setContentView(layout);
} // ()
public void onClick(View view) {
((Button) view).setText("*");
((Button) view).setEnabled(false);
}
} // class
Here's a nice sample for you:
https://developer.android.com/guide/topics/ui/layout/gridview.html
You should just create buttons instead of imageviews in getView adapter method.
If you are using a GridView, or a ListView (etc), and are producing Views to populate them via the adapter getView(pos, convertView, viewGroup), you might encounter confusion (i did once).
If you decide to re-use the convertView parameter, you must reset everything inside of it. It is an old view being passed to you by the framework, in order to save the cost of inflating the layout. It is almost never associated with the position it was in the layout before.
class GridAdapter extends BaseAdapter // assigned to your GridView
{
public View getView(int position, View convertView, ViewGroup arg2) {
View view;
if (convertView==null)
{
view = getLayoutInflater().inflate(R.layout.gd_grid_cell, null);
}
else
{
// reusing this view saves inflate cost
// but you really have to restore everything within it to the state you want
view = convertView;
}
return view;
}
// other methods omitted (e.g. getCount, etc)
}
I think this represents one of those Android things where the concept is a little difficult to grasp at first, until you realize there's a significant optimization available within it (have to be nice to CPU on a little mobile device)

Categories

Resources