I use DialogFragments in my game for some popup information. It works fine on LG Nexus 4 running android 4.2 and it runs fine on the Desire S running 2.3.
It does however not run correctly on a Sony Xperia U (running 4). Here is what happens:
black spaces under dialogfragment
It does not place the dialog in the middle of the screen, which happens on all other devices, but it also renders a big black section on my screen below the dialog.
Here is my code:
public void ShowMessage(String title, String msg)
{
Bundle b = new Bundle();
b.putString("title", title);
b.putString("msg", msg);
DialogFragment dialog = new DialogFragment_MsgBox();
dialog.setArguments(b);
dialog.show(getSupportFragmentManager(), "msgbox");
}
and
public class DialogFragment_MsgBox extends android.support.v4.app.DialogFragment {
#Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Bundle b = getArguments();
final Dialog dialog = new Dialog(getActivity(), R.style.SetmsgDialog);
dialog.setContentView(R.layout.simpleokdialog);
if(b.containsKey("title"))
dialog.setTitle(b.getString("title"));
else
dialog.setTitle("Message");
return dialog;
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.simpleokdialog, container, false);
Bundle b = getArguments();
String msg = "";
if(b.containsKey("msg"))
{
msg = b.getString("msg");
}
TextView text = (TextView)v.findViewById(R.id.bericht);
text.setText(msg);
Button iv = (Button)v.findViewById(R.id.simpleOK);
iv.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
// When button is clicked, call up to owning activity.
getDialog().dismiss();
}
});
// TODO Auto-generated method stub
return v;
}
}
and also needed the style i use for the dialogfragment:
<style name="SetmsgDialog">
<item name="android:background">#aac6775c</item>
<item name="android:textColor">#android:color/white</item>
<item name="android:windowNoTitle">false</item>
<item name="android:textSize">14sp</item>
<item name="android:windowIsFloating">true</item>
<item name="android:windowTitleStyle">#style/setwindowTitleStyle</item>
<item name="android:windowAnimationStyle">#android:style/Animation.Dialog</item>
<item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
<item name="android:backgroundDimEnabled">true</item>
<item name="android:gravity">left</item>
</style>
What can cause this? any solutions/tips or suggestions to this problem?
I have fixed this finally, it appears that some phones/provider software have different behavior in the standard themes etc. (I have seen this with sony again with text being white with shadow on a white background, very nasty looking, and now again with sony, different behavior) So If you do overload some theme, which you always do when using your own and not fill in all the variables, use all variables to get expected out comes!
I had 'forgotten':
<item name="android:windowBackground">#android:color/transparent</item>
for which the sony xperia U uses black with no transparency, while nexus 4 and desire S use transparent color.
Related
I am using Toolbar from Appcompat with ActionMode. The ActionMode overlays the Toolbar. Now, if i click on an empty Space in the ActionMode an underlying ActionButton from the Toolbar handles the ClickEvent.
Is this normal behaviour? How can i prevent this behaviour?
((ActionBarActivity) getActivity()).getSupportActionBar().startActionMode(new ActionMode.Callback() {
#Override
public boolean onCreateActionMode(ActionMode actionMode, Menu menu) {
actionMode.getMenuInflater().inflate(R.menu.actionmode, menu);
MenuItem menuItem = menu.findItem(R.id.number);
MenuItem menuItem1 = menu.findItem(R.id.action_edit);
TextView textView = (TextView) menuItem.getActionView();
ImageButton imageButton = (ImageButton) menuItem1.getActionView();
imageButton.setBackgroundResource(R.drawable.ic_action_edit);
textView.setText("0 selected");
// Return true so that the action mode is shown
return true;
}
#Override
public boolean onPrepareActionMode(ActionMode actionMode, Menu menu) {
// As we do not need to modify the menu before displayed, we return false.
return false;
}
#Override
public boolean onActionItemClicked(ActionMode actionMode, MenuItem menuItem) {
// Similar to menu handling in Activity.onOptionsItemSelected()
switch (menuItem.getItemId()) {
case R.id.action_delete:
// Some remove functionality
return true;
}
return true;
}
#Override
public void onDestroyActionMode(ActionMode actionMode) {
// Allows you to be notified when the action mode is dismissed
}
});
XML for my ActionMode in /res/values/menu
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="#+id/number"
android:title="number"
android:actionViewClass="android.widget.TextView"/>
<item android:id="#+id/action_edit"
android:title="edit"
android:actionViewClass="android.widget.ImageButton"/>
<item android:id="#+id/action_delete"
android:title="delete"
android:icon="#drawable/ic_action_delete"/>
</menu>
You will need to set the action mode layout to be clickable.
First set the custom Theme for entire application or a single Activity in the AndroidManifest file:
<application android:theme="#style/Theme.CustomTheme">
In themes.xml resource file set the new actionModeStyle for your theme:
<style name="Theme.CustomTheme" parent="Theme.AppCompat.NoActionBar">
<item name="actionModeStyle">#style/action_mode_style</item>
</style>
Then your action_mode_style should have android:clickable set to true
<style name="action_mode_style" parent="#style/Widget.AppCompat.ActionMode">
<item name="android:clickable">true</item>
</style>
The Context
I have a HomeActivity that contains a NewsFragment. The NewsFragment contains a ListView to display news items in a list. I have a ViewPager that is added as a header-view to the ListView. This ViewPager appears as a header to the list and contains a DateFragment to display the date. The first time the user opens the HomeActivity, I want "TODAY" to be the date. When the user swipes the DateFragment to the left, I want the date text to show "TOMORROW". Swipe again and it should show the day after tomorrow. Similarly, when the user swipes in the other direction, I want to display "YESTERDAY", the day before yesterday etc. The ViewPager should support swiping infinitely (or a very large number) in both directions.
Here's how they are nested - http://tinypic.com/r/31623qw/8. (I don't have the reputation to post images yet, but this diagram is super useful for understanding this question).
The Problem
For simplicity, I'm displaying the index of the fragment as the date. When I first open the app, I see "Date: 0" being displayed as the date in the DateFragment. When I swipe the fragment to the left (to go to the next day), I can see the next fragment appear with "Date: 1" being displayed, but almost immediately, the fragment disappears. Once the fragment disappears, nothing reappears, and I just see an empty container. I can swipe to bring back the "Date: 0" Fragment, but I can't see any other Fragments. (I'm using the - Infinite View Pager by Antony T. - https://github.com/antonyt/InfiniteViewPager)
The Gory Details
I have a HomeActivity that contains a NewsFragment. The NewsFragment contains a ListView to display news items as a list. Here is the layout.xml for the NewsFragment:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ListView
android:id="#android:id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</LinearLayout>
I have a ViewPager that is dynamically added as a header to this list. So inside NewsFragment, I first initialize the ListView:
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.home_news_fragment, container, false);
list = (ListView) view.findViewById(android.R.id.list);
emptyView = view.findViewById(android.R.id.empty);
list.setEmptyView(emptyView);
return view;
}
Next, in onActivityCreated(), I initialize and load the header for the ListView, and then load the news feed items:
#Override
public void onActivityCreated(final Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
loadHeader();
loadNewsFeed();
}
In the loadHeader() method, I then dynamically create a LinearLayout container to contain my ViewPager. I create a PagerAdapter for the ViewPager and I wrap it with an InfiniteViewPager to allow infinite swiping in both directions. I then create a ViewPager and I add it to the LinearLayout container. I then add the container as a Header View to the ListView:
private void loadHeader()
{
final LinearLayout headerContainer = new LinearLayout(getActivity());
headerContainer.setId(R.id.header_container_id);
headerContainer.setLayoutParams(new AbsListView.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT));
headerContainer.setOrientation(LinearLayout.VERTICAL);
// initialize the pager adapter for the view pager
PagerAdapter pagerAdapter = new HeaderPagerAdapter(getActivity().getSupportFragmentManager());
// Create a view pager. I use a custom implementation of a view pager I found from another Stackoverflow answer - WrapContentHeightViewPager - that allows ViewPager's layout.height to wrap content. The original ViewPager does not allow wrapping of content.
WrapContentHeightViewPager mViewPager = new WrapContentHeightViewPager(getActivity());
mViewPager.setId(R.id.view_pager_header);
mViewPager.setLayoutParams(new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT));
// wrap pager to provide infinite paging with wrap-around
PagerAdapter wrappedAdapter = new InfinitePagerAdapter(pagerAdapter);
mViewPager.setAdapter(wrappedAdapter);
// Add the view pager to the header container
headerContainer.addView(mViewPager);
// add the container as a header view to the list
list.addHeaderView(headerContainer);
}
In the loadNewsFeed() method, I do an async fetch of the news feed items and populate the list by adding the items into the footer view. I won't go into the implementation details for this - outside the scope of this question.
The NewsFragment contains my pager adapter, which contains the getItem method that initializes the Fragment to be displayed by the ViewPager:
private class HeaderPagerAdapter extends FragmentPagerAdapter
{
public HeaderPagerAdapter(FragmentManager fm) {
super(fm);
}
#Override
public Fragment getItem(int i) {
return DateFragment.newInstance(i);
}
#Override
public int getCount() {
return Integer.MAX_VALUE;
}
}
And here is the actual Fragment to be displayed inside the ViewPager:
public class DateFragment extends Fragment
{
private int index;
TextView date;
public static final DateFragment newInstance(int index) {
DateFragment fragment = new DateFragment();
final Bundle args = new Bundle(1);
args.putInt(Constants.Extras.PAGE_INDEX, index);
fragment.setArguments(args);
return fragment;
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
index = getArguments() != null ? getArguments().getInt(Constants.Extras.PAGE_INDEX) : 1;
}
#Override
public View onCreateView(final LayoutInflater inflater, final ViewGroup container, final Bundle savedInstanceState)
{
View v = (ViewGroup) inflater.inflate(R.layout.summary_fragment, container, false);
date = (TextView) v.findViewById(R.id.tvDate);
return v;
}
#Override
public void onActivityCreated(final Bundle savedInstanceState)
{
super.onActivityCreated(savedInstanceState);
date.setText("Date: " + index);
}
}
For now I am simply using the index to be displayed as the date. I want to replace this with the actual date. Why does the fragment disappear on swipe?
Considerations:
Is there a refresh/redraw event that gets called?
Does it have to do with extending FragmentPagerAdapter vs. FragmentStatePagerAdapter
Override destroyItem() or instantiateItem()?
Set up a onPageScrolled listener on the ViewPager and then handle the page scroll events? I tried thehayro.blogspot.com/2012/12/enable-infinite-paging-with-android.html and that causes my fragments to disappear and then appear after a while.
Is it because I am adding the ViewPager as a header to the list view? The list view scrolls up and down and the view pager left and right. I've added this to my ViewPager implementation to tell the list view to stop intercepting our touch events:
#Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
// Tell our parent to stop intercepting our events!
boolean ret = super.onInterceptTouchEvent(ev);
if (ret)
{
getParent().requestDisallowInterceptTouchEvent(true);
}
return ret;
}
I'm sorry about the length of this post. I felt this much detail might be necessary. Thoughts?
I really need help (am a newbie to ADT/Eclipse), I set up a back ground image by placing the image first in the res/drawable folder and then proceeded to place it in my application usind the:
android:background = "#drawable/image"
I then proceeded to change the layout to "scrollview"
The image appeared in the Graphical layout but after a while, ADT showed me an error saying:
(Where the error is at where "R" is written e.g. setContentView(R.layout.activity_main);
the error reads "R cannot be resolved to a variable"
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
}
I would kindly appreciate if anyone helps :D
I've made a decent effort to find a similar question and failed, so please forgive me if this is redundant pollution.
I have a ListView and an ImageButton defined in the xml file "my_layout" corresponding to my Activity as follows:
<ListView
android:id="#+id/listViewItems"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
></ListView>
and
<ImageButton
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/btn_delete_dark"
android:id="#+id/buttonDelete"
android:layout_weight="1">
</ImageButton>
I then populate the ListView programmatically in the onCreate() method of my Activity as follows:
public class ViewItemsActivity extends Activity implements OnClickListener,
OnItemClickListener{
ImageButton buttonDelete;
ListView listViewItems;
DatabaseHandler dbHandler;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.my_layout);
buttonDeleteQuestion = (ImageButton) findViewById(R.id.buttonDelete);
listViewQuestions = (ListView) findViewById(R.id.listViewItems);
buttonDelete.setOnClickListener(this);
//get data from sql table containing items
dbHandler = new DatabaseHandler(this);
String [] items = dbHandler.getItems(); //get data to populate ListView
CustomAdapter adapter = new CustomAdapter(this,
android.R.layout.simple_list_item_1, items);
listViewItems.setAdapter(adapter);
listViewItems.setOnItemClickListener(this);
}
#Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.buttonDelete:
listViewItems.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE);
listViewItems.setItemChecked(0, true);
break;
//other cases are irrelevant
}
}
#Override
public void onItemClick(AdapterView<?> parent, View v, int pos, long id) {
// TODO Auto-generated method stub
//non relevant code
}
}
Everything works as it should except that I want the ListView to change, in appearance and functionality, as a result of clicking buttonDelete, so that it displays checkmarks to the right of each row which can be checked by clicking on them.
It was my understanding that setChoiceMode(ListView.MULTIPLE_CHOICE) and setItemChecked(i,true) would have this effect, but clearly I've missed something as it does not.
I am quite new to android and so it is possible that I've wasted someone's time with trivialities, for which I apologize.
Thank you very much.
The solution was really simple, and is the following:
in the onClick event corresponding to buttonDelete, I simply created a new adapter whose layout id is *simple_list_item_multiple_choice* and assigned it to the ListView with the lines
CustomAdapter adapter = new CustomAdapter(this,
android.R.layout.simple_list_item_multiple_choice, items);
listViewItems.setAdapter(adapter);
which did the trick.
Hello everyone I've been stick with this problem, and I can't see my mistake. I had used before basicly for having different drawable bind to a specific level, nevertheless I am trying to use it within a BroadcastReceiver wich monitor battery changes, the problem is that I don't get any UI update when I called the setImageLevel change?
The Broadcast Receiver goes like this
public class BatteryReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Log.d(LOG, "Fired Changed");
int level = intent.getIntExtra(BatteryManager.EXTRA_LEVEL, 0);
int scale = intent.getIntExtra(BatteryManager.EXTRA_SCALE, 100);
int percent = (level * 100) / scale;
imageBattery = (ImageView) findViewById(R.id.imageBatery);
imageBattery.setImageLevel(percent);
Log.d(LOG, "On UI running I am");
// imageBattery.getDrawable().mutate();
// imageBattery.invalidate();
// Log.d(LOG,"DRawable: "+((LevelListDrawable)imageBattery.getDrawable()).getCurrent());
}
}
The Log gets displayed but it does not change my ImageView if you can point me out in the right direction, or you have any insight on this issue?
Little bit of more info
Here is my Registration and unregistration both on the same activity as the BroadcastReceiver
#Override
public void onResume() {
super.onResume();
IntentFilter filter = new IntentFilter();
filter.addAction("android.intent.action.BATTERY_CHANGED");
registerReceiver(receiver, filter);
}
#Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
How do I instatiate the ImageView Drawable:
<ImageView
android:id="#+id/imageBatery"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/battery_status" />
And also battery_status.xml is a drawable (I removed some of the drawable item because you get the idea I have from 0-100)
<item
android:drawable="#drawable/stat_sys_battery_100"
android:maxLevel="100"/>
<item
android:drawable="#drawable/stat_sys_battery_90"
android:maxLevel="90"/>
<item
android:drawable="#drawable/stat_sys_battery_80"
android:maxLevel="80"/>
Do You have your BroadcastReceiver inlined in Your Activity? If so, use 'MyActivity.this.runOnUiThread()` method to change Your views.
your problem is in images
LevelListDrawable doesn't append new image when level changed, it just shows the image for level you've set
try differen images and you'll see what I mean
try this in your onCreate:
imageBattery = (ImageView) findViewById(R.id.imageBatery);
for (int i = 0; i < 10; i++) {
imageBattery.setImageLevel(i * 10);
}
is smth changed ?