I am creating my first Android app using a Navigation Drawer, and such most of my pages are fragments. Each page will contain several ImageButtons.
My goal is for the user to click an ImageButton, and then be displayed a "popup" list of images with their respective names. When the user selects an image, the ImageButton's src should become that image.
Any tips on how I could achieve this? Thanks!
Here is one of my fragments:
public class FragmentAnubis extends Fragment {
View myView;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
myView = inflater.inflate(R.layout.god_anubis, container, false);
return myView;
}
And here is its corresponding layout:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_height="match_parent"
android:orientation="vertical"
android:weightSum="100">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:orientation="horizontal"
android:layout_weight="100">
<ImageButton
android:id="#+id/imageStarterItem"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:adjustViewBounds="true"
android:padding="7dp"
android:background="#null"
android:scaleType="fitCenter"
app:srcCompat="#drawable/ah_puch" />
<ImageButton
android:id="#+id/imageRelic1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:adjustViewBounds="true"
android:padding="7dp"
android:background="#null"
android:scaleType="fitCenter"
app:srcCompat="#drawable/ah_muzen_cab" />
<ImageButton
android:id="#+id/imageRelic2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:adjustViewBounds="true"
android:padding="7dp"
android:background="#null"
android:scaleType="fitCenter"
app:srcCompat="#drawable/agni" />
</LinearLayout>
</LinearLayout>
First of all, remove unnecessary root LinearLayout.
I guess you use DialogFragment to show list of images. In onclick handler get image source and send it throw event bus - Rx event bus or GreenRobots Event Bus https://github.com/greenrobot/EventBus
In source activity you can catch all events and set source to first button
Related
My problem is this, I have multiple RelativeLayouts in a LinearLayout inside of a ScrollView that is in the main RelativeLayout. When trying to obtain the id's in the fragment class I have it keeps giving me errors.
I've looked around for an answer for this for about 2 days now and have only come across an idea of using
<include name="some_name" layout="#layout/some_layout"/>
and it doesn't really help me with my app. I'm trying to develop a calendar week view which I already have the numbers working and the time on the left.
Here is my xml file:
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="#+id/day_labels_linear_layout"
android:layout_width="match_parent"
android:layout_height="60dp"
android:orientation="horizontal">
<!-- not important but this holds the numbers up top -->
</LinearLayout>
<ScrollView
android:id="#+id/calendar_scroll_view"
android:layout_width="match_parent"
android:layout_height="fill_parent"
android:layout_alignParentBottom="true"
android:layout_below="#+id/day_labels_linear_layout"
android:fadingEdge="none"
android:overScrollMode="never"
android:scrollbars = "none">
<!-- used to space each day with the day_labels_linear_layout weights -->
<LinearLayout
android:id="#+id/calendar_spacer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<!--This has all of the hours, I just didn't include them
because it would take up so much room-->
<RelativeLayout
android:id="#+id/hours_relative_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2.5"
android:background="#color/scheduler_background" >
<TextView
android:id="#+id/time_12_am"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:paddingBottom="25dp"
android:paddingTop="25dp"
android:text="#string/text_time_12_am" />
<TextView
android:id="#+id/time_1_am"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/time_12_am"
android:layout_centerHorizontal="true"
android:paddingBottom="25dp"
android:paddingTop="25dp"
android:text="#string/text_time_1_am" />
<TextView
android:id="#+id/time_2_am"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/time_1_am"
android:layout_centerHorizontal="true"
android:paddingBottom="25dp"
android:paddingTop="25dp"
android:text="#string/text_time_2_am" />
</RelativeLayout>
<RelativeLayout
android:id="#+id/sunday_relative_layout"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="2" >
<View
android:id="#+id/divider_sunday_left"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:background="#color/divider_scheduler" />
<Button
android:id="#+id/sunday_day"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true"
android:background="#color/transparent" />
<View
android:id="#+id/divider_sunday_right"
android:layout_width="1dp"
android:layout_height="match_parent"
android:layout_alignParentRight="true"
android:background="#color/divider_scheduler" />
</RelativeLayout>
<!-- there is a Relative layout for each day-->
</LinearLayout>
</ScrollView>
</RelativeLayout>
So when I try to access the id's this is what I get:
RelativeLayout sundayRL;
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState){
View view = inflater.inflate(R.layout.fragment_scheduler, null);
sundayRL = (RelativeLayout) view.findViewById(R.id.sunday_relative_layout);
}
It gives me the error: sunday_relative_layout cannot be resolved or is not a field, I added a button to see if I could get the id for that and the same result happened. Yet I was able to find the id's for each of the day numbers and day names that is in the top LinearLayout.
Does anyone have a better solution to this? I'm trying to register when the user clicks the view so I can send them to a scheduling page.
EDIT:
So changing null to container allowed me to find my Ids
View view = inflater.inflate(R.layout.fragment_scheduler, container);
But it caused another issue with a map fragment on one of the other fragments saying I didn't have the right API key which it does.
If you have nested layouts
eg:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout >
<RelativeLayout
android:id="#+id/rl2>
<Button
android:id="#+id/getStarted"
/>
</RelativeLayout>
</RelativeLayout>
And you want to press a button in the nested one.
Add ID on the nested Layout.
and use this code in onCreate()
View view = (View) findViewById(R.id.rl2);
Button button = (Button) view.findViewById(R.id.getStarted);
I need to have like several listviews on a scrollview which Android doesn't allow me to do so I decided to make it manually to simply inflate some listrows on a vertical LinearLayout, but everything goes not the right way
private void fillData(final ViewGroup parent, final ArrayList<Person> array ){
for (int i=0;i<array.size();i++){
final View view = lf.inflate(R.layout.personal_listrow, parent,true);
parent.setBackgroundColor(getActivity().getResources().getColor(R.color.background_light_darker));
view.setBackgroundColor(getActivity().getResources().getColor(R.color.background_night_lighter));
TextView tvName=(TextView) view.findViewById(R.id.tvName);
TextView tvStatus=(TextView) view.findViewById(R.id.tvStatus);
TextView tvGender=(TextView) view.findViewById(R.id.tvGender);
//fill textviews with info, set the onClickListeners and so on
}
So what I get - the view.setBackgroundColor paints parent as well .
parent is a vertical LinearLayout, view is horizontal LinearLayout - it's strange that I don't paint inflated element only so please explain me why
The next thing - after I add something to array - 1st element changes and all the rest is with unchanged text. However, I walked through the code with debugger - it passes every element and sets text.
The clicklisteners works on the 1st element only..
Would you plz explain
here's vertical , parent layout - nothing special:
<LinearLayout
android:id="#+id/rodll"
android:layout_marginTop="16dp"
android:layout_marginBottom="8dp"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="wrap_content">
the inflateable listrow is nothing special also :
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center_vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal" >
<TextView
android:id="#+id/tvStatus"
android:layout_width="0dp"
android:layout_weight=".3"
android:maxLines="1"
android:layout_height="wrap_content"
android:text="tvSt" />
<TextView
android:id="#+id/tvName"
android:layout_weight="1"
android:layout_width="0dp"
android:maxLines="1"
android:layout_height="wrap_content"
android:text="tvName" />
<TextView
android:id="#+id/tvGender"
android:layout_weight=".1"
android:layout_width="0dp"
android:maxLines="1"
android:layout_height="wrap_content"
android:text="tvGender" />
<com.andexert.library.RippleView
android:id="#+id/removeRipple"
xmlns:ripple="http://schemas.android.com/apk/res-auto"
android:layout_marginLeft="30dp"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginRight="7.5dip"
android:padding="3dp"
ripple:rv_alpha="255"
ripple:rv_zoom="true"
ripple:rv_zoomScale="0.8"
ripple:rv_type="rectangle">
<ImageView
android:id="#+id/remove_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/remove" />
</com.andexert.library.RippleView>
<com.andexert.library.RippleView
android:id="#+id/addRipple"
xmlns:ripple="http://schemas.android.com/apk/res-auto"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginRight="7.5dip"
android:padding="3dp"
ripple:rv_alpha="255"
ripple:rv_zoom="true"
ripple:rv_zoomScale="0.8"
ripple:rv_type="rectangle">
<ImageView
android:id="#+id/add_icon"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/add" />
</com.andexert.library.RippleView>
</LinearLayout>
So. what's the problem and how to solve it?
Do I need to create 2 fragment layout for it? 1st layout is (FirstName, Gender, Category and etc..) and 2nd layout is (LastName, DOB and etc...)
Then use fragment to arrange it according to screen size?
But I dont think is good right? because then we need to decide how many row I need to put in one layout.
What is the best approach to achieve it?
View in tablet:
View in phone:
Use a single Fragment or Activity and then use a different layout for different screen sizes & orientations. If you use separate Fragments, the code that processes the user interaction will be in multiple places. Using a single Fragment or Activity will make your code much simpler.
Here are some example layouts to get you started. I'm using all TextViews but you could replace the gender TextView with a Spinner quite easily.
For phone or smaller screens you would use this layout:
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="#+id/first_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Chee"/>
<TextView
android:id="#+id/last_name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Kin"/>
<TextView
android:id="#+id/gender"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Male"/>
<TextView
android:id="#+id/date_of_birth"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="dd/mm/yy"/>
</LinearLayout>
And then for landscape or larger screens, this one will put last name and date of birth in a second column.
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/first_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Chee"/>
<TextView
android:id="#+id/last_name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Kin"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="#+id/gender"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Male"/>
<TextView
android:id="#+id/date_of_birth"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:hint="dd/mm/yy"/>
</LinearLayout>
</LinearLayout>
Give them the same filename (e.g. person_info.xml) and put them in resource folders for the different screen sizes & orientation. (e.g. layout & layout-land).
In your fragments onCreate() you then inflate the layout and Android handles choosing the correct file based on the users screen size & orientation.
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
fragmentView = inflater.inflate(R.layout.person_info, container, false);
firstNameTextView = (TextView) fragmentView.findViewById(R.id.first_name);
lastNameTextView = fragmentView.findViewById(R.id.last_name);
genderTextView = (TextView) fragmentView.findViewById(R.id.gender);
dobTextView = (TextView) fragmentView.findViewById(R.id.date_of_birth);
return fragmentView;
}
Since the TextViews have the same android:id in both layouts, your code can treat them the same no matter which layout gets loaded.
I'm learning Android and I was trying out FrameLayout containing ImageViews, I tried to do a little app that switchs between two images when you click on them the code is the following:
My xml looks like this:
>
<FrameLayout 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"
tools:context=".Hola" >
<ImageView
android:id="#+id/segunda"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="metodosegunda"
android:scaleType="fitCenter"
android:src="#drawable/img1" />
<ImageView
android:id="#+id/primera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="metodoprimera"
android:scaleType="fitCenter"
android:src="#drawable/img2" />
</FrameLayout>
And my main program:
public class Hola extends Activity {
ImageView primera;
ImageView segunda;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.teta_layout);
primera = (ImageView) findViewById(R.id.primera);
segunda = (ImageView) findViewById(R.id.segunda);
}
public void metodoprimera (View view){
primera.setVisibility(View.GONE);
segunda.setVisibility(View.VISIBLE);
}
public void metodosegunda (View view){
segunda.setVisibility(View.GONE);
primera.setVisibility(View.VISIBLE);
}
}
This program should show an image and as soon as you click on it it should hide that image and show the other and so on.
The thing is that this won't work , but as soon as I switch the imageview order in the xml, it works, and i don't really understand why it should not work this way.
Thank you guys in advance
Try adding:
android:visibility="gone"
to the XML for one of the ImageView's.
I'll try to go more explicit with the explanation, here is the thing:
If I have the XML like this it will show the images (depending on visibility) but the oClick thing will not work:
<FrameLayout 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"
tools:context=".Hola" >
<ImageView
android:id="#+id/segunda"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="metodosegunda"
android:scaleType="fitCenter"
android:src="#drawable/img1"
android:visibility="gone" />
<ImageView
android:id="#+id/primera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="metodoprimera"
android:scaleType="fitCenter"
android:src="#drawable/img2"
android:visibility="visible" />
</FrameLayout>
If I swap the ImageView's order in the XML It will work perfectly:
<FrameLayout 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"
tools:context=".Hola" >
<ImageView
android:id="#+id/primera"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="metodoprimera"
android:scaleType="fitCenter"
android:src="#drawable/img2"
android:visibility="visible" />
<ImageView
android:id="#+id/segunda"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="metodosegunda"
android:scaleType="fitCenter"
android:src="#drawable/img1"
android:visibility="gone" />
</FrameLayout>
It's not about the visibility of each Imageview since it does not matter what value I put on them It won't work the first way but i will work the second way.
Seems like a weird issue since the oder of the imageviews should not matter if you set them visible or gone ...
I'm trying to create a music player that will be visible in all my activities. To do this, I'm going to use a Fragment as some of you advised me earlier.
Since I have no experience with Fragments whatsoever, I decided to implement a fragment in a "filler" activity first.
I created a simple fragment containing only a button and some text, and try to inflate that in my filler activity.
However, after inflating this fragment does not show up. A message does get printed to LogCat telling me that the fragment has been inflating.
I'm pretty sure I'm missing something, but since I have no experience with this and I couldn't find a tutorial that quite explained how to do this, I don't know what it is that I'm missing.
Music player Fragment
public class AppMusicPlayer extends Fragment{
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
System.out.println("fragment added");
return inflater.inflate(R.layout.musicplayer_main, container, false);
}
}
Music Player layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical" >
<Button
android:id="#+id/button1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Button" />
<TextView
android:id="#+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="This is the fragment you're looking for" />
</LinearLayout>
Filler Activity
public class Filler extends FragmentActivity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.filler);
Button b = (Button) findViewById(R.id.terug);
b.setOnClickListener(new View.OnClickListener() {
public void onClick(View arg0) {
Intent intent = new Intent();
setResult(RESULT_OK, intent);
finish();
}
});
}
}
Filler layout
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<!-- Title bar -->
<RelativeLayout
android:id="#+id/linearLayout1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:background="#drawable/title_bar" >
<TextView
android:id="#+id/fillertitle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:text="Work In Progress"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textStyle="bold" >
</TextView>
<Button
android:id="#+id/terug"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:layout_centerVertical="true"
android:background="#drawable/button_back"
android:text="Back"
android:textColor="#FFFFFFFF"
android:textStyle="bold" >
</Button>
</RelativeLayout>
<!-- End of title bar -->
<TextView
android:id="#+id/wip"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="This section of the app has not been made yet. Work in progress." >
</TextView>
<fragment
android:id="#+id/musicPlayerFragment"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:name="com.mobowski.app.player.AppMusicPlayer" />
</LinearLayout>
Obviously I'm doing something wrong, but what?
Note: I'm using Android 2.3 with the Compatibility library.
Any help is appreciated
The problem has been fixed with the help of Yashwanth Kumar and blessenm. One gave an XML solution, the other a programmatic solution. Now I'm just wondering which solution is the most desirable one. Are there any concessions to be made with either of the solutions, or does it all boil down to the programmer's preferred solution?
I haven't tried adding fragments directly to xml. But what I normally do is add a framelayout or linearlayout to the filler layout.
Suppose its id is 'fragment_holder'. I use the following code in the fragment activity right after setContentView. Try this
FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.add(R.id.fragment_holder,new AppMusicPlayer(),"musicplayer");
ft.commit();
you should mention layout_height as 0dip, not the width in vertical linear layout.
change that it should work.
<fragment
android:id="#+id/musicPlayerFragment"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:layout_weight="1"
android:name="com.mobowski.app.player.AppMusicPlayer" />