I have two SearchViews in one xml layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<SearchView
android:id="#+id/my_first_custom_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</SearchView>
<SearchView
android:id="#+id/my_second_custom_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/my_first_custom_view" >
</SearchView>
</RelativeLayout>
And I inflate this layout to my MainActivity by setContentView(). Then I call methods
setQuery() for each other.
Everything is ok until a screen rotation. When I rotate the screen every searchView has text "World" instead "Hello" and "World".
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
SearchView firstSearchView = (SearchView) findViewById(R.id.my_first_custom_view);
SearchView secondSearchView = (SearchView) findViewById(R.id.my_second_custom_view);
firstSearchView.setQuery("Hello!", false);
secondSearchView.setQuery("World", false);
}
}
Someone can explain what's going wrong ?
The SearchView uses as its content the view resulted from inflating a layout file. As a result, all the SearchViews used in the layout of an activity(like your case) will have as content, views with the same ids. When Android will try to save the state to handle the configuration change it will see that the EditTexts from the SearchViews have the same id and it will restore the same state for all of them.
The simplest way to handle this issue is to use the Activity's onSaveInstanceState and onRestoreInstanceState like this:
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
// state for the first SearchView
outState.putString("sv1", firstSearchView.getQuery().toString());
// state for the second SearchView
outState.putString("sv2", secondSearchView.getQuery().toString());
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
// properly set the state to balance Android's own restore mechanism
firstSearchView.setQuery(savedInstanceState.getString("sv1"), false);
secondSearchView.setQuery(savedInstanceState.getString("sv2"), false);
}
Also have a look at this related question.
One way to alleviate this problem is to capture the orientation event change with your activity and then set the query again on your two search views.
Add this to manifest in activity in which you are having two SearchView
android:configChanges="keyboardHidden|orientation|screenSize"
Related
In the application, I have:
One main activity
4 fragments
2.a. Home fragment
2.b. Data fragment
2.c. Picture fragment
2.d. Link fragment
So inside of the home fragment, there are 3 pictures which links to Data, picture and link fragment. There is a NavigationView which also links to the fragment.
Now, I want to add these links to each picture so it can work as a Navigation links and forwards to the same fragment. How to achieve that?
Currently, I am using setOnClickListener inside home fragment to forward each fragment but I believe there are better ways to do that? This is because when i use setOnClickListener this does not update the current nav link.
Layout
That is a very common task and Google introduced the Navigation component for such tasks. See https://developer.android.com/guide/navigation/navigation-getting-started for reference.
Some reference code (you also need the navigation graph):
In MainActivity
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
NavController navController = Navigation.findNavController(this,
R.id.nav_host_fragment);
}
}
In MainActivity XML:
<fragment
android:id="#+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="0dp"
app:defaultNavHost="true"
app:layout_constraintBottom_toTopOf="#+id/bottomNavigationBorder"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:navGraph="#navigation/nav_graph" />
In "onViewCreated" of the navigation Fragment
NavController navController = Navigation.findNavController(view);
btnAction.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Bundle bundle = new Bundle();
bundle.putInt("ACTION", "1");
navController.navigate(R.id.action_mainFragment_to_nextFragment, bundle);
}
});
The function navController.navigate() can one or two arguments. The bundle is optional and is used if you want to send information to the target fragment. The "R.id....." attribute is defined in the navigation graph and describes the link between two fragments / activities.
Hope this helps.
I am new with coding Java and xml for android applications and I wanted to know how I start/open a new activity when clicking on something. In this case I am using a relative layout to keep a image and text together as one object. What I want to do is when you click on it it will start/open the new activity. How do I do this? Could someone tell me step by step since I am quite new to this.
First of all, if you want your layout to act (RelativeLayout) like a button (do not handle onClick on layout child components) firstly set in your xml layout file RelativeLayout attribute
android:clickable="true"
Or you can do this directly in your code (in onCreate method)
relativeLayout.setClickable(true);
Than you need to set onClickListener for your layout.
You can do this simply by creating anonymous class
relativeLayout.setOnClickListener(new OnClickListener()
{
#Override
public void onClick(View v)
{
Intent startActivityIntent = new Intent(getApplicationContext(),YourDesiredActivity.class);
startActivity(startActivityIntent);
}
}
UPDATE
Layout is defined in xml file, of course in Android you can do this in code ,but it is better to use xml file.
In your IDEA you have folder res->layout here you should place your layout files. For example layout with name `
relative_root_layout.xml
<xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relative_layout"
android:layout_height="wrap_content" android:layout_width="wrap_content">
<ImageView
android:id="#+id/image_view">
android:layout_width="wrap_content"
android:src="#drawable/icon"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
ImageView>
<TextView
android:id="#+id/text_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20sp"
android:layout_toRightOf="#+id/image_view"
android:text="Relative layout">
TextView>
RelativeLayout>
But in case you have only text and image it is better to use
<Button
android:id="#+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:drawableLeft="#android:drawable/btn_image"
android:text="Button with Image"
android:gravity="left"
android:drawablePadding="10dp">
Button>
How you can access your widgets ?
This is very basic thing you have to know if you are developing for android, this is essential part. Please read documentation, read books, watch tutorial or whatever.
In short you need to inflate layout in activity onCreate() method
RelativeLayout mRelativeLayout;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.relative_root_layout);
mRelativeLayout = (RelativeLayout) findViewById(R.id.relative_layout);
mRelativeLayout.setOnClickListener(.....)
}
But again this very basic things you must know.
You could set onClickListener for any of your views.
ImageView image = (ImageView) findViewById(R.id.image);
image.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
startActivity(new Intent(Youractivity.this, Moveactivity.class));
}
});
Starting a new activity is done by creating an Intent and then calling startActivity, e.g.
Intent intent = new Intent(context, AnotherActivity.class);
context.startActivity(intent);
You can wrap this code in an OnClickListener as other answerers already suggested.
A second option is to add an android:onClick attribute to your RelativeLayout
<RelativeLayout ...
android:onClick="clickMe">
<ImageView .../>
<TextView .../>
</RelativeLayout>
and in your activity
public class MyActivity extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
public void clickMe(View notused) {
Intent intent = new Intent(this, AnotherActivity.class);
this.startActivity(intent);
}
}
See startactivity for a complete example.
I am trying to get a fragment to show that contains an EditText and a button. I am new to using fragments, so I am not sure exactly what the error message I get when trying to create the fragment means.
I have a class that extends Fragment, this is where the EditText and button are created.
public class EditNameFragment extends android.support.v4.app.Fragment {
EditText editText;
ImageButton button;
public EditNameFragment(){
}
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_name_dialog, container, false);
editText = (EditText) view.findViewById(R.id.editTextDialog);
button = (ImageButton) view.findViewById(R.id.submitNewItemButtonDialog);
button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
//stuff
}
});
return view;
}
Here is edit_name_dialog.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal" android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:id="#+id/edit_name_dialog"
>
<EditText
android:id="#+id/editTextDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
/>
<ImageButton
android:id="#+id/submitNewItemButtonDialog"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
/>
</LinearLayout>
And here in my main activity (which must extend FragmentActivity because of another part) is where I try to set up my Fragment. I think it has something to do with what id I am referencing. I have seen some people using container classes when using fragments, but I do not understand why this is done.
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
EditNameFragment fragment = new EditNameFragment();
fragmentTransaction.add(R.id.edit_name_dialog, fragment, "tag");
fragmentTransaction.commit();
I get the error message when trying to run the code above
No view found for id 0x7f09002a (com.myapp:id/edit_name_dialog) for fragment EditNameFragment
If anyone could explain what I am missing here/ why people use container classes, that would be great. I know some people add fragments using XML, but I would like to do this only using java.
EDIT
I have added a class that extends FragmentActivity, following the model for a container class
public class EditNameFragmentActivity extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.edit_name_fragment_container);
}
}
Is the parameter for setContentView supposed to be the layout, or an id?
Here is the xml file that defines where the fragment should be
edit_name_fragment_container.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<fragment android:name="com.returnjump.spoilfoil.EditNameFragment"
android:id="#+id/edit_name_fragment_container"
android:layout_weight="1"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:layout="#layout/edit_name_fragment" />
</LinearLayout>
So for the parameter in
fragmentTransaction.add(R.id.edit_name_dialog, fragment, "tag");
this is supposed to reference the id of the fragment, correct?
It still gives me the same error, what am I missing?
There are basically two ways to add a fragment to an activity like the documentation say:
"statically": by declaring the fragment inside the activity's layout file.
"dynamically": adding the fragment programmatically. Like you tried to do.
Here is the documentation: http://developer.android.com/guide/components/fragments.html
If you wish to add it dynamically, here is the documentation part that you want to read:
At any time while your activity is running, you can add fragments to your activity layout. You simply need to specify a ViewGroup in which to place the fragment.
To make fragment transactions in your activity (such as add, remove, or replace a fragment), you must use APIs from FragmentTransaction. You can get an instance of FragmentTransaction from your Activity like this:
FragmentManager fragmentManager = getFragmentManager()
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
You can then add a fragment using the add() method, specifying the fragment to add and the view in which to insert it. For example:
ExampleFragment fragment = new ExampleFragment();
fragmentTransaction.add(R.id.fragment_container, fragment);
fragmentTransaction.commit();
The first argument passed to add() is the ViewGroup in which the fragment should be placed, specified by resource ID, and the second parameter is the fragment to add.
Once you've made your changes with FragmentTransaction, you must call commit() for the changes to take effect.
And about why to use dynamic fragments instead of static fragments, it has been made for interactive UI allowing you to simply handle different fragments into one activity as you please.
OnClick doesn't work. Nothing happens after clicking on layout. It seems like it is clickable, because layout changes its color, but new layout doesn't open.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/window"
android:layout_width="295dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:background="#drawable/editborder"
android:clickable="true"
android:onClick="openBigImage">
Here is more code for Main Activity:
public class MyMapActivity extends FragmentActivity implements LocationListener
{
private Marker marker;
private Hashtable<String, String> markers;
private ImageLoader imageLoader;
private DisplayImageOptions options;
private GoogleMap map;
private ListView mainListView ;
private ArrayAdapter<String> listAdapter ;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_map);
// Look up the AdView as a resource and load a request.
//AdView adView = (AdView)this.findViewById(R.id.adView);
//adView.loadAd(new AdRequest());
// Getting Google Play availability status
int status = GooglePlayServicesUtil.isGooglePlayServicesAvailable(getBaseContext());
// Showing status
if(status!=ConnectionResult.SUCCESS)
{ // Google Play Services are not available
int requestCode = 10;
Dialog dialog = GooglePlayServicesUtil.getErrorDialog(status, this, requestCode);
dialog.show();
}
else
{// Google Play Services are available
// Getting reference to the SupportMapFragment of activity_main.xml
SupportMapFragment mapFragment = (SupportMapFragment)getSupportFragmentManager().findFragmentById(R.id.map);
if (savedInstanceState == null) {
// First incarnation of this activity.
mapFragment.setRetainInstance(true);
}
else
{
// Reincarnated activity. The obtained map is the same map instance in the previous
// activity life cycle. There is no need to reinitialize it.
map = mapFragment.getMap();
}
setUpMapIfNeeded();
}
}
#Override
protected void onResume()
{
super.onResume();
setUpMapIfNeeded();
}
public void openBigImage(View v)
{
setContentView(R.layout.bigpicture);
}
bigpicture.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/bigpicture"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical">
<fragment
android:id="#+id/minimap"
android:layout_width="200px"
android:layout_height="200px"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
class="com.google.android.gms.maps.SupportMapFragment" />
<ImageView
android:id="#+id/badge"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:adjustViewBounds="true" />
</RelativeLayout>
Calling setContentView() multiple times worked in other cases, like menu items "about", "settings" etc.
Tried to make without setContentView. I've put new Layout to the main.xml and made visibility GONE. OnClick method should change visibility to visible, but again nothing happens.
Logcat says "11-25 13:47:28.638: D/GestureDetector(3156): [Surface Touch Event] mSweepDown False, mLRSDCnt : -1 mTouchCnt : 2 mFalseSizeCnt:0" when i'm clicking on linear layout.
Paul,
One thing is close the linear layout with /> .I am assuming that you have followed the map tutorials link and passed all the manifest permissions and other requirements. You might have some reasons to use px. Check if map is being created. Also give some height and background color to your badge image and see if something happens.
I tested your code without map fragment and it worked fine.
Can you post the error log ?
Found. It is a click on InfoWindow, so we should implement onInfoWindowClick.
But first we must add map.setOnInfoWindowClickListener(this); in main activity. Main activity must implement OnInfoWindowClickListener.
I've added new LinearLayout to the main.xml, made it invisible.
Here's code for onInfoWindowClick:
#Override
public void onInfoWindowClick(Marker marker) {
LinearLayout secondLL = (LinearLayout) findViewById(R.id.bigpicture);
int visibility = secondLL.getVisibility();
if(visibility == View.GONE)
{
secondLL.setVisibility(View.VISIBLE);
}
}
I think you can't use onClick attribute.
You have to use setOnClickListener() like that :
LinearLayout layout = (LinearLayout )findViewById(R.id.window);
layout .setOnClickListener(new OnClickListener() {
#Override
public void onClick(View v) {
YourActivity.this.setContentView(R.layout.bigpicture);
}
});
I found the template that ADT generates for a Master/Detail Flow Activity to be rather obtuse, and I don't like the fact that the ListView is not declared in a layout file which forces me to work with it programatically. For example, instead of just setting android:background on the ListView in a layout file, I'm forced to find the ListView via findViewById in the fragment's onCreateView(...) method, then call setBackground(...). For maintainability and general readability, I'd like to do the same thing via a layout file.
Instead, I'm trying to inflate a custom layout in the onCreateView method of the "master" fragment:
public class InboxFragment extends ListFragment {
public InboxFragment() {}
private ListView listView = null;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
listView = (ListView) inflater.inflate(R.layout.inbox_fragment_layout,
null);
return listView;
}
#Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// the following doesn't work
listView.setAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),
android.R.layout.simple_list_item_activated_1,
android.R.id.text1,
DummyContent.ITEMS));
// nor does this
//setListAdapter(new ArrayAdapter<DummyContent.DummyItem>(getActivity(),
// android.R.layout.simple_list_item_activated_1,
// android.R.id.text1,
// DummyContent.ITEMS));
}
}
However, calling setListAdapter (or even setAdapter) doesn't seem to do anything, even though I've given the ListView an id of android:id="#id/android:list" in R.layout.inbox_fragment_layout:
<ListView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#id/android:list"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#D3D3D3" />
My "master" activity just calls a fragment layout:
public class InboxActivity extends FragmentActivity {
#Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.inbox_phone_layout);
}
}
inbox_phone_layout.xml:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentPhoneInbox"
android:name="com.justin.inbox.InboxFragment"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1" />
Instead, I'm greeted with a blank page and it doesn't look like the ListView is loaded at all. What am I doing wrong, here? Sample project on GitHub.
I fixed your issue by changing inbox_phone_layout.xml to the following:
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/fragmentPhoneInbox"
android:name="com.justin.inbox.InboxFragment"
android:layout_width="match_parent"
android:layout_height="match_parent" />