I've spent a large amount of time trying to solve this issue both by myself and searching through here to find a solution, none of which have worked for me.
My current scenario is when a popup window appears I want to disable all clickable events on the foreground view which is underneath the popup window.
if (Shared.InspectionData.JobViewModel.RAMS_Id == null || Shared.InspectionData.JobViewModel.RAMS_Id.equals("")) {
// Disable foreground view here
LoadRAMSPopup();
}
private void LoadRAMSPopup() {
mainLayout.getForeground().setAlpha(150);
LayoutInflater layoutInflater = (LayoutInflater) getBaseContext().getSystemService(LAYOUT_INFLATER_SERVICE);
final View ramsView = layoutInflater.inflate(R.layout.popup_rams, null);
final PopupWindow popupRAMS = new PopupWindow(
ramsView,
ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT
);
if (Build.VERSION.SDK_INT >= 21) {
popupRAMS.setElevation(5.0f);
}
findViewById(R.id.mainLayout).post(new Runnable() {
#Override
public void run() {
popupRAMS.showAtLocation(findViewById(R.id.mainLayout), Gravity.CENTER, 0, 0);
popupRAMS.setOutsideTouchable(false);
popupRAMS.update();
Button btnGenerate = (Button) ramsView.findViewById(R.id.btnGenerate);
btnGenerate.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
Intent intent = new Intent(getApplicationContext(), CreateRAMSActivity.class);
startActivity(intent);
popupRAMS.dismiss();
mainLayout.getForeground().setAlpha(0);
}
});
}
});
}
Hitchhiking off of Akshay Mukadam Disabling all child views inside the layout. I've tweaked it slightly to include enabling my views.
public static void disableEnableViews(ViewGroup layout) {
layout.setEnabled(false);
for (int i = 0; i < layout.getChildCount(); i++) {
View child = layout.getChildAt(i);
if (child instanceof ViewGroup) {
disableEnableViews((ViewGroup) child);
} else {
if(child.isEnabled()){
child.setEnabled(false);
} else {
child.setEnabled(true);
}
}
}
}
Simply give your top view an id, reference it, and then put into the method.
Related
Can someone please explain why the first piece of code here works but not the last piece? The only difference is the index of which i insert my view, i-1 and i+1. Is i+1 just not possible with index? I can write any other number in there and it works.
upButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < drawerViewGroup3.getChildCount(); i++) {
View view = drawerViewGroup3.getChildAt(i);
TextView tv = (TextView) view.findViewById(R.id.drawer_name);
if (tv.getText().toString().equals(drawerName.getText().toString()) && i != 0) {
drawerViewGroup3.removeView(view);
drawerViewGroup3.addView(view, i - 1);
}
}
}
});
downButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
for (int i = 0; i < drawerViewGroup3.getChildCount(); i++) {
View view = drawerViewGroup3.getChildAt(i);
TextView tv = (TextView) view.findViewById(R.id.drawer_name);
if (tv.getText().toString().equals(drawerName.getText().toString())) {
drawerViewGroup3.removeView(view);
drawerViewGroup3.addView(view, i + 1);
}
}
}
});
Some context on the app. I have a vertical oriented LinearLayout with multiple LinearLayouts inside. When clicking the two Buttons in the code, one of the children is to move up or down, switching their positions.
EDIT: Ok so I figured it out.
downButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
View viewToMove = null;
int viewToMovePos = drawerViewGroup3.getChildCount();
for (int i = 0; i < drawerViewGroup3.getChildCount(); i++) {
View view = drawerViewGroup3.getChildAt(i);
TextView tv = (TextView) view.findViewById(R.id.drawer_name);
if (tv.getText().toString().equals(drawerName.getText().toString()) && i != drawerViewGroup3.getChildCount() - 1) {
viewToMovePos = i;
viewToMove = view;
}
}
alert.dismiss();
if (viewToMovePos != drawerViewGroup3.getChildCount()) {
drawerViewGroup3.removeView(viewToMove);
drawerViewGroup3.addView(viewToMove, viewToMovePos + 1);
}
}
});
Not the prettiest code and probably not gonna help others as it's very specific, but that was the answer.
When you remove a view from your LinearLayout, the view at index i is now the view which was after the one which you removed. Then you add a view at i - 1 which is before this view (the one which was previously after the removed view). The final result is that you remove a view and insert back where it used to be.
Instead, you need to add the view at i - 2.
I suggest that you look at RecyclerView. It is specifically designed to efficiently create a dynamic list of views for given data. You only have to manipulate the data and RecyclerView does all the hard work for you.
I am adding a Customized View using an array.The array elements are intialized by inflating a layout and adding those elements to a ViewGroup as shown in the image.
When I am setting onClickListener in a way to make the clicked view's background as Accent Color It happens but in order to make it mutually exclusive so that once a view is clicked other View's background should become transparent as they were intially I have used the following code But my when I click on the View, my applications stops responding.If my approach is not correct Please suggest me the right way to get desired result.
This should happen:
this should not happen:
if(noOfChild>1) {
for (j = 0; j < noOfChild; j++) {
LayoutInflater inflater = (LayoutInflater) getSystemService(getApplicationContext().LAYOUT_INFLATER_SERVICE);
childButton[j] = (inflater.inflate(R.layout.child_selection_button, null));
childButton[j].setId(j);
children.addView(childButton[j], new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, 1.0f));
childButton[j].setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
v.setBackgroundColor(ContextCompat.getColor(MainScreen.this, R.color.dimAccent));
// for (int k =0;k<noOfChild;k++){
// while(k!=v.getId()){
// childButton[k].setBackgroundColor(ContextCompat.getColor(MainScreen.this, R.color.transparent));
// }
// }
}
});
}
}
You can keep a local variable which shows the position of the last selected item. Then in your onClick() method do the switch in the position and the backgroundColor:
private View lastSelected;
//... rest of code ...
//Inside for loop
public void onClick(View v){
if (lastSelected == null){
lastSelected = v;
selectItem(lastSelected);
}
else
{
deselectItem(lastSelected);
lastSelected = v;
selectItem(lastSelected);
}
}
private void selectItem(View v){
v.setBackgroundColor(ContextCompat.getColor(MainScreen.this,R.color.dimAcent));
}
private void deselectItem(View v){
v.setBackgroundColor(ContextCompat.getColor(MainScreen.this, R.color.transparent));
}
In my app I would like to type a text with regular characters and emoticon short-cuts.
While typing characters from a soft keyboard, I would like to launch a popup menu or popup window with a series of icons/emoticon. Pressing on an icon/emoticon will insert emoticon short-cut characters at the cursor.
It's ok to have text with normal characters and emoticon-short-cut characters. Showing the emoticons in the text is one step further.
The solution I like is:
1 - Upon clicking a smiley button I start a popup:
#Override
public void onClick(View v) {
switch( v.getId()) {
case R.id.fragment_log_popup_smileys:
PopupIcons popup = new PopupIcons( myActivity, new PopupIconResultHandler() {
#Override
public void iconClicked( String iconResult) {
logTextV.getText().insert( logTextV.getSelectionStart(), iconResult);
}
});
popup.show();
break;
Any smiley characters are inserted in the text. They could be shown as the same smileys. Easy to do so.
2 - The popup
public class PopupIcons implements Serializable {
Activity myActivity;
PopupIconResultHandler myClickHandler;
public PopupIcons( final Activity activityContext, PopupIconResultHandler clickHandler) {
myActivity = activityContext;
myClickHandler = clickHandler;
}
public void show() {
Rect rectgle= new Rect();
Window window= myActivity.getWindow();
window.getDecorView().getWindowVisibleDisplayFrame( rectgle);
int StatusBarHeight= rectgle.top;
int contentViewTop= window.findViewById( Window.ID_ANDROID_CONTENT).getTop();
int TitleBarHeight= contentViewTop - StatusBarHeight;
Display display = ((WindowManager) myActivity.getSystemService( Context.WINDOW_SERVICE)).getDefaultDisplay();
LinearLayout viewGroup = (LinearLayout) myActivity.findViewById( R.id.popupIconsLinearLayout);
LayoutInflater layoutInflater = (LayoutInflater) myActivity.getSystemService( Context.LAYOUT_INFLATER_SERVICE);
View layout = layoutInflater.inflate( R.layout.popup_icons, viewGroup);
// Creating the PopupWindow
final PopupWindow popup = new PopupWindow( myActivity);
popup.setContentView(layout);
popup.setFocusable(true);
popup.setAnimationStyle( R.style.PopupMenu);
popup.setWidth( FrameLayout.LayoutParams.WRAP_CONTENT);
popup.setHeight(FrameLayout.LayoutParams.WRAP_CONTENT);
View.OnClickListener handler = new View.OnClickListener() {
#Override
public void onClick( View v) {
if( myClickHandler != null) {
myClickHandler.iconClicked( (String) v.getTag());
}
popup.dismiss();
}
};
ImageButton but = (ImageButton) layout.findViewById( R.id.popup_icon_smile); but.setOnClickListener( handler);
but = (ImageButton) layout.findViewById( R.id.popup_icon_smile_big); but.setOnClickListener( handler);
but = (ImageButton) layout.findViewById( R.id.popup_icon_smile_cool); but.setOnClickListener( handler);
// etc ... for all buttons
popup.showAtLocation( layout, Gravity.BOTTOM | Gravity.LEFT, 30 , 30);
}
}
I enjoy this method.
Do you have suggestions for improvement?
I am trying to populate data in UI fetched through REST service. The data comes up everytime but the UI doesn't get populated sometimes. The UI is kind of listing but listview is not being used. There's a ScrollView which has LinearLayout as its child and then row views are added to the linearlayout. There are times when UI just doesn't get updated even if the data is passed to it.
private void showData(List list) {
if(list != null && list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
} else {
mNoData.setVisibility(View.GONE);
final LinearLayout linearLayout = (LinearLayout) findViewById(R.id.details_layout);
findViewById(R.id.details_progress).setVisibility(View.GONE);
linearLayout.removeAllViews();
LayoutInflater layoutInflater = getLayoutInflater();
View rowView = null;
TextView txtName = null;
Button buttonPlay = null;
for (int i = 0; i < list.size(); i++) {
rowView = layoutInflater.inflate(R.layout.row_view, null);
txtName = (TextView) rowView.findViewById(R.id.row_view_name);
buttonPlay = (Button) rowView.findViewById(R.id.row_view_button_play);
final Item item = (Item) list.get(i);
rowView.setTag(i) ;
txtName.setText(item.getName());
final RecentItem recentItem = RecentsManager.getInstance().getRecentItemFromRefID(item.getId());
if (recentItem !=null) {
buttonPlay.setText(getString("Resume"));
buttonPlay.requestFocus();
}
buttonPlay.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
if (recentItem!=null) {
//do some action
} else {
//do some action
}
finish();
}
});
final int tag = (Integer) rowView.getTag() ;
rowView.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do some action
}
}) ;
txtName.setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
//do some action
}
});
buttonPlay.setId(i);
if(i < list.size())
buttonPlay.setNextFocusDownId(i+1);
linearLayout.addView(rowView);
if (i == 0) {
buttonPlay.requestFocus();
buttonPlay.setNextFocusUpId(mButtonReminder.getId());
if(mButtonReminder != null) {
mButtonReminder.setNextFocusDownId(buttonPlay.getId());
}
} else {
buttonPlay.setNextFocusUpId(i-1);
}
}
}
}
I have even checked the linearlayout children's count and the count is always equal to list size which means rows are also being added to it but it just doesn't show up on the UI.
What can be the issue?
you are using condition
if(list != null && list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
}
change it to
if(list == null || list.isEmpty()) {
mNoData.setVisibility(View.VISIBLE);
}
I was able to resolve the issue by doing certain changes as adding fillViewPort="true" for scrollview. Also, there was a background thread which was trying to update the UI because of which UI thread was breaking. This didn't resulted in a crash but the UI updation didn't happened. With these two changes it's working fine.
Has the action bar icon size changed in Android 4.2 ?
I've had a 120x48px HDPI icon that was rendered perfectly in Android 4.1 and below. It still is.
However, on any 4.2 device, it is squelched to fit as 48x48px from what I can see. Or something like that; it's definitely a square.
Any ideas ? Thanks !
This is not ideal, but it appears you can get around this limitation by using an custom action view.
Something like this:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/log_in"
android:title="Login"
android:showAsAction="always"
android:actionLayout="#layout/log_in_button"/>
</menu>
Where #layout/log_in_button points to a layout file containing an ImageButton with your icon set as the src.
You will have to bind the click listener in the OnCreateOptionsMenu method. There is a halfway good example here: http://developer.android.com/guide/topics/ui/actionbar.html#ActionView.
I only just learned to use this method, so I don't know yet if there are any major downfalls besides the increased complexity.
So, I found an answer, it's kinda hacky but works (TM):
The general idea is to listen for the layout changes and apply new bounds to the drawables. This could look like this:
public static void updateActionBar(final Activity activity) {
if (Build.VERSION.SDK_INT >= 17) {
try {
final View content = activity.findViewById(android.R.id.content);
if (content instanceof FrameLayout) {
final FrameLayout contentFrameLayout = (FrameLayout) content;
final ViewParent parent = contentFrameLayout.getParent();
if (parent instanceof LinearLayout) {
final LinearLayout parentLinearLayout = (LinearLayout) parent;
final Class<?> actionBarContainerClass = Class.forName("com.android.internal.widget.ActionBarContainer");
final Class<?> actionBarViewClass = Class.forName("com.android.internal.widget.ActionBarView");
final Class<?> actionMenuViewClass = Class.forName("com.android.internal.view.menu.ActionMenuView");
final Class<?> actionMenuItemViewClass = Class.forName("com.android.internal.view.menu.ActionMenuItemView");
for (int i = 0, childCount = parentLinearLayout.getChildCount(); i < childCount; i++) {
final View parentLinearLayoutChild = parentLinearLayout.getChildAt(i);
handleParentLinearLayoutChild(actionBarContainerClass, actionBarViewClass, actionMenuViewClass, actionMenuItemViewClass, parentLinearLayoutChild);
}
}
}
} catch (Exception e) {
// Handle or ignore
}
}
}
private static void handleParentLinearLayoutChild(final Class<?> actionBarContainerClass, final Class<?> actionBarViewClass, final Class<?> actionMenuViewClass, final Class<?> actionMenuItemViewClass, final View parentLinearLayoutChild) {
if (parentLinearLayoutChild instanceof FrameLayout && parentLinearLayoutChild.getClass().equals(actionBarContainerClass)) {
final FrameLayout actionBarContainer = (FrameLayout) parentLinearLayoutChild;
for (int i = 0, actionBarContainerChildCount = actionBarContainer.getChildCount(); i < actionBarContainerChildCount; i++) {
final View actionBarContainerChild = actionBarContainer.getChildAt(i);
handleActionBarContainerChild(actionBarViewClass, actionMenuViewClass, actionMenuItemViewClass, actionBarContainerChild);
}
}
}
private static void handleActionBarContainerChild(final Class<?> actionBarViewClass, final Class<?> actionMenuViewClass, final Class<?> actionMenuItemViewClass, final View actionBarContainerChild) {
if (actionBarContainerChild instanceof ViewGroup && actionBarContainerChild.getClass().equals(actionBarViewClass)) {
final ViewGroup actionBarView = (ViewGroup) actionBarContainerChild;
actionBarView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
#Override
public void onChildViewAdded(final View parent, final View child) {
handleActionBarViewChild(child, actionMenuViewClass, actionMenuItemViewClass);
}
#Override
public void onChildViewRemoved(final View parent, final View child) {
}
});
for (int i = 0, actionBarViewCount = actionBarView.getChildCount(); i < actionBarViewCount; i++) {
handleActionBarViewChild(actionBarView.getChildAt(i3), actionMenuViewClass, actionMenuItemViewClass);
}
}
}
private static void handleActionBarViewChild(final View child, final Class<?> actionMenuViewClass, final Class<?> actionMenuItemViewClass) {
try {
if (child instanceof LinearLayout && child.getClass().equals(actionMenuViewClass)) {
final LinearLayout actionMenuView = (LinearLayout) child;
actionMenuView.setOnHierarchyChangeListener(new ViewGroup.OnHierarchyChangeListener() {
#Override
public void onChildViewAdded(final View parent, final View child) {
handleActionMenuViewChild(child, actionMenuItemViewClass);
}
#Override
public void onChildViewRemoved(final View parent, final View child) {
}
});
for (int i = 0, actionMenuViewCount = actionMenuView.getChildCount(); i < actionMenuViewCount; i++) {
handleActionMenuViewChild(actionMenuView.getChildAt(i), actionMenuItemViewClass);
}
}
} catch (Exception e) {
// Handle or ignore
}
}
private static void handleActionMenuViewChild(final View child, final Class<?> actionMenuItemViewClass) {
try {
if (child instanceof TextView && child.getClass().equals(actionMenuItemViewClass)) {
final TextView menuViewChild = (TextView) child;
final Drawable[] compoundDrawables = menuViewChild.getCompoundDrawables();
final Drawable leftDrawable = compoundDrawables[0];
final int intrinsicWidth = leftDrawable.getIntrinsicWidth();
final int intrinsicHeight = leftDrawable.getIntrinsicHeight();
leftDrawable.setBounds(0, 0, intrinsicWidth , intrinsicHeight );
menuViewChild.setCompoundDrawables(leftDrawable, null, null, null);
menuViewChild.setPadding(menuViewChild.getPaddingLeft(), 0, menuViewChild.getPaddingRight(), 0);
menuViewChild.invalidate();
menuViewChild.requestLayout();
}
} catch (Exception e) {
// Handle or ignore
}
}
You then have to call updateActionBar in every Activity (I suggest making an abstract base activity from which you extend) in the following callbacks:
onCreate
onMenuOpened (I found that it would improve performance and reduce flickering (size changes of the drawables) if you call this delayed (e.g. 200ms))
onPrepareOptionsMenu (I found that it would improve performance and reduce flickering (size changes of the drawables) if you call this delayed (e.g. 200ms))
This works for me on Nexus 7 and Nexus 10 with Android 4.2. You can expect it to fail with future updates but at least for now it seems to work.