I am using the Expanding-Collection-Library which uses the method
public void instantiateCard(LayoutInflater inflaterService, final ViewGroup head, ListView list, ECCardData data)
to instantiate all the views of inside the head ViewGroup.
I change the visibility of a few views inside this method, depending, on whether the card is fully expanded or collapsed.
I want to collapse the cards in the activity's onBackPressed(), which works fine, but I cannot change the visibility of the child views of the head ViewGroup.
I tried accessing the views by declaring class variables inside MainActivity which are then set in instantiateCard() and though I get no errors that the view cannot be found nothing happens on visibility change.
The same when trying to define separate variables inside the activity and instantiateCard and setting them independently.
#Override
public void instantiateCard(LayoutInflater inflaterService, final ViewGroup head, ListView list, ECCardData data) {
final LinearLayout headerButtonContainer = head.findViewById(R.id.headerButtonContainer);
final LinearLayout nameContainer = head.findViewById(R.id.nameContainer);
final TextView tvAailablePlacesHead = head.findViewById(R.id.tvAvailablePlacesHead);
final TextView tvNameHead = head.findViewById(R.id.tvNameHead);
// here I also tried setting the activities variables like
// tvAcNameHead = tvNameHead;
// since just decalring a field variable and using it like
// nameHeadFieldVariable = head.findViewById(R.id.tvNameHead);
// would lead to not being able to change the visibility here either
// Card toggling by click on head element
head.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(final View v) {
ecPagerView.toggle();
if (headerButtonContainer.getVisibility() == View.VISIBLE) {
setDetailOverlayItemsVisible(headerButtonContainer, nameContainer, tvNameHead, tvAailablePlacesHead);
} else {
setDetailOverlayItemsInvisible(headerButtonContainer, nameContainer, tvNameHead, tvAailablePlacesHead);
}
}
});
}
Related
I need to show an image in full screen, on clicking of View Pager in android.
I have tried this.
view.myPager.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
Log.e("VIEW PAGER", "VIEW PAGER");
Toast.makeText(activity, "ZOOM", Toast.LENGTH_SHORT).show();
}
});*
Suggestion appreciated.
Thanks
Set the listener on the image inside instantiateItem():
#Override
public Object instantiateItem(View collection, int position) {
final LayoutInflater inflater = getLayoutInflater();
View layout = inflater.inflate(R.layout.my_layout, null);
final ImageView image = (ImageView)layout.findViewById(R.id.image_display);
final int cPos = position;
image.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
ImageView i = (ImageView)v;
if(cPos == 0)
{
//...
}
//...
}
});
return layout;
}
Alternatively, you could use the ImageView.setTag() method to include data about what Activity to launch. e.g.
if(position == 0) image.setTag("com.blah.android.SomeActivity");
if(position == 1) image.setTag("com.blah.android.AnotherActivity");
//...
And the inside the onClick() above have this instead:
ImageView i = (ImageView)v;
String activityClassName = (String)i.getTag(); // Get the info we stored in the tag.
MyActivity.this.startActivity((new Intent()).setClassName(MyActivity.this, activityClassName));
Note that here you don't actually need the cast to ImageView, since getTag() is a method of View. You also don't need a separate OnClickListener for each ImageView. You could just create a single instance of an OnClickListener that grabs the tag data as above, and launches the appropriate activity. Set this OnClickListener on every ImageView inside instantiateItem().
P.S. I strongly recommend, if you are downloading images, that you look at some of the image downloaders that have been written for Android. e.g.
https://github.com/nostra13/Android-Universal-Image-Loader
You cannot click on a ViewPager, as a ViewPager manages a UI, but does not have its own UI.
You will need to add appropriate listeners (e.g., OnClickListener) to widgets inside pages in the ViewPager, just as you would for an app that did not have a ViewPager.
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'm using a ViewPager with a FragmentPagerStateAdapter. Every page has a list, manually managed => I create views for this rows by inflating a layout from xml. Resulting in, that views in different rows have the same id. Because the rows are inflated from XML...
The behaviour now is following:
Page 1 looks like following:
// Page 1:
// Row 1: EditText = "Test1"
// Row 2: EditText = "Test2"
I swipe to Page 2 and then to Page 3, afterwards I swipe back to Page 1 and Page 1 looks like following:
// Page 1:
// Row 1: EditText = "Test2"
// Row 2: EditText = "Test2"
Problem: All EditTexts display the value of the lastEditText in the list... (Note, the EditTexts have the same ID).
If I manually set the ids of my EditTexts to the row index, everything works fine.
Is this normal? Is there an easy (good) solution for that problem?
Tt seems like a bug in Android 3.X
The solution is setting ID's manually so they never match between fragments or resetting id's when Fragment becomes invisible.
I like the second one since it can be easily disabled or enabled and requires no special id handling.
/**
* Used for resetting and restoring View id's. This is used as a workaround for
* Android 3.x when ViewPager Fragment instances with the same layout have
* problems referencing next focus id's.
*/
public final class ViewIdResetter {
private final Map<View, Integer> viewMap;
public ViewIdResetter(final View rootView) {
this.viewMap = new HashMap<View, Integer>();
this.fillmap(rootView);
}
private void fillmap(final View view) {
if (view instanceof ViewGroup) {
final ViewGroup vg = (ViewGroup) view;
for (int i = 0; i < vg.getChildCount(); i++) {
this.fillmap(vg.getChildAt(i));
}
}
this.viewMap.put(view, view.getId());
}
public void clearIds() {
for (final View key : this.viewMap.keySet()) {
key.setId(-1);
}
}
public void restoreIds() {
for (final View key : this.viewMap.keySet()) {
key.setId(this.viewMap.get(key));
}
}
}
The Fragment
private ViewIdResetter resetter;
#Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
this.resetter = new ViewIdResetter(view);
}
#Override
public void setUserVisibleHint(boolean isVisibleToUser) {
super.setUserVisibleHint(isVisibleToUser);
if (isVisibleToUser) {
if (this.resetter != null) {
this.resetter.restoreIds();
}
} else {
if (this.resetter != null) {
this.resetter.clearIds();
}
}
}
setUserVisibleHint is triggered by ViewPager when the Fragment becomes visible.
The ViewIdResetter makes sure only one Fragment at a time has the same id's set.
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
I have got ListView with a custom Adapter. Every row contains clickable buttons and texts.
At the moment onClickListeners are set in the body of getView(), this is quite insane idea because this method is called very frequently. Inside every onClick function, I need access to the private data to call new activity with the bundle.
How can I move the onClick definition outside getView() routine?
When onClick will be called I need info about the position of the list element (to access private data) and which View was clicked (to start the correct Activity).
public View getView(int position, View convertView, ViewGroup parent) {
if(convertview == null) {
convertView = ((Activity) getContext()).getLayoutInflater().inflate(R.layout.photo_tweet_row, null);
}
TextView userTweet = (TextView) v.findViewById(R.id.feed_user_tweet_body);
RepliesButton repliesBtn = (RepliesButton) v.findViewById(R.id.feed_replies_button);
Status twitterDataItem = getItem(position);
if (twitterDataItem != null) {
if (userTweet != null) {
userTweet.setText(twitterDataItem.getText());
}
if (repliesBtn != null) {
repliesBtn.setText(" replies");
}
userTweet.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(getContext(), ProfileActivity.class);
intent.putExtra(getContext().getString(R.string.serializable_user), twitterDataItem.getUser());
getContext().startActivity(intent);
}
});
repliesBtn.setOnClickListener(new View.OnClickListener() {
public void onClick(View view) {
if (!twitterDataItem.getComments().contentEquals("0")) {
Intent myIntent = new Intent(getContext(), RepliesToFeedActivity.class);
myIntent.putExtra("photoTweet", twitterDataItem);
getContext().startActivity(myIntent);
}
}
});
}
return convertView;
}
Your activitiy has to implement the OnClickListener, and move the implemented method up to the activity level.
Based on the view parameter of the method you are able to detect from which UI object the event came from (button, textview).
As for how to detect for which record/row in a listview. You have to set a custom tag on the buttons and textviews in the getView method, that you will read in the event via getTag this tag can be a custom object too if string is not enough. Probably/recommended way is to be the position in the adapter.
I am afraid that Pentium10 answer is not correct. If the checkbox is to be clickable and checkable independently from the list item itself, (say it is defined in the list item xml layout), then it will intercept the click event, and the list item (the list's OnItemClickListener) will not receive the click at all.
Therefore you must implement the onClickListener in the adapter itself - either in getView(), or have the adapter implement onClickListener - in this case the items must be tagged for the listener to know which item it is operating on.