Hello guys I'm working on application and my layout structure is as following :
RelativeLayout:
CompoundView:
CompoundView:
RelativeLayout:
Button
Button
RecyclerView
BrowseFragment:
Only rows
My problem is when I get to first row of browse fragment and first item in it and I want to go up (D-PAD-UP) to focus button it does nothing it works only when I push left ( D-PAD-LEFT). Anyone has solution for this ?
So the problem was in BrowseFrameLayout for some reason and to solve this issue I had to override onFocusSearchListener and manage focus myself.
In BrowseFragment which I extended I have this method :
public void workaroundFocus(){
if(getView() != null) {
View viewToFocus = getActivity().findViewById(R.id.view_to_focus);
BrowseFrameLayout browseFrameLayout = getView().findViewById(android.support.v17.leanback.R.id.browse_frame);
browseFrameLayout.setOnFocusSearchListener((focused, direction) -> {
if (direction == View.FOCUS_UP) {
return viewToFocus;
}
else {
return null;
}
});
}
}
And then:
#Override
public void onActivityCreated(#Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
workaroundFocus();
/*
Rest of the code
*/
}
And voila it works.
Since you are using the RelativeLayout you should layout the components in the order that you would like to be navigated.
Using the XML attributes presented in the RelativeLayout reference document, you will be able to establish an navigation order too:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingLeft="16dp"
android:paddingRight="16dp" >
<EditText
android:id="#+id/name"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/reminder" />
<Spinner
android:id="#+id/dates"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_below="#id/name"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="#+id/times" />
<Spinner
android:id="#id/times"
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_below="#id/name"
android:layout_alignParentRight="true" />
<Button
android:layout_width="96dp"
android:layout_height="wrap_content"
android:layout_below="#id/times"
android:layout_alignParentRight="true"
android:text="#string/done" />
</RelativeLayout>
Here the dates Spinner is below the name EditText and at left of times Spinner, the times component is below the name one and the done Button is below times. See the image below:
See the Build Basic TV Layouts guide for more tv related details.
Related
I am trying to set focus on a LinearLayout view when returning to an activity from another activity. The scenario:
I have one activity with a bunch of LinearLayout items (with stuff in them), some of which are text, others photos. Let's say the top most of 20 is a TextView and the rest are photos. When I leave this activity (to take a picture), activity goes to the top of the list where the TextView is - no matter what I do.
How do I force the focus back on the item that I was on before the new activity was triggered?
I have already tried this with no success:
[How Linear Layout get Focus?
I am currently trying to force the focus by remembering the previous view without success (though I can see the code being executed). The in my main activity:
#Override
public void onResume() {
super.onResume();
// See if we had a field with focus previously...
if (mPreviousView != null) {
if (mPreviousView.isFocusable()) {
mPreviousView.requestFocus();
}
}
}
...
#Override
protected void onPause() {
super.onPause();
mPreviousView = this.getCurrentFocus();
}
I am dynamically setting the focus in the LinearLayout:
private void initialize() {
LayoutInflater inflater = (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.field_photo_picker, this);
// To allow focus to be returned to control after taking photo
this.setFocusableInTouchMode(true);
this.setFocusable(true);
this.setClickable(true);
And finally the XML for the LinearLayout:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="5dp"
android:paddingBottom="5dp">
<TextView
android:id="#+id/name"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="18sp"
android:textStyle="normal"
android:text="" />
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="#+id/photoValue"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:textSize="17sp"
android:textStyle="normal"
android:gravity="right|center_vertical"
android:layout_weight="1"
android:layout_marginRight="5dp"
android:text="" />
<ImageButton
android:id="#+id/photoPicker"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="#drawable/form_photo"
android:padding ="5dp"
android:gravity="center_vertical"
android:focusableInTouchMode="false"
android:background="?android:attr/selectableItemBackground"
android:layout_weight="0"
/>
</LinearLayout>
<View
android:layout_marginTop="8dp"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#color/grey" />
</LinearLayout>
</merge>
make your textview and other views focusable, you made this.setFocusable(true); which doesn't make sense
I have an android app, and i want it to have two views which are similar to one another.
For example :
<Button
android:id="#+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="OK" />
and
<Button
android:id="#+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK" />
notice that the only change is that i removed the centerHorizontal line. but this is a simplified example.
Now, i want to create an app, that sometimes (ex- using a random func) uses view A and sometimes uses view B.
Is it possible to do this "views switch" at runtime?
Is it possible to build this app using the two views (notice that the button should have the same ID, i don't want to implement the logic twice)?
thanks a lot!
The only way I imagine to do that is:
Having each button in its own layout file.
Inflate the corresponding based on your function result.
Append it to the view.
Sample code:
button_a.xml:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:text="OK" />
button_b.xml:
<?xml version="1.0" encoding="utf-8"?>
<Button xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="OK_2" />
Your activity:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LayoutInflater inflater = LayoutInflater.from(this);
Button button;
if (Math.random() > 0.5) {
button = (Button) inflater.inflate(R.layout.button_a, null);
} else {
button = (Button) inflater.inflate(R.layout.button_b, null);
}
/* ...
Set listeners to the button and other stuff
...
*/
//find the view to wich you want to append the button
LinearLayout view = (LinearLayout) this.findViewById(R.id.linearLayout1);
//append the button
view.addView(button);
}
If you want this to happen dynamically (i.e. not in the onCreate, but after some user input) you can always remove the button from layout, and inflate a new random-chosen one.
Hope this helps!
I have a glsurface occupying the full screen. At the click of a button I want another layout to appear (settings type of thing). If I start with the overlay being visible, I can make it invisible and then visible again with no problem. But if I start with it invisible, I cannot make it ever visible again. Code follows:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<android.opengl.GLSurfaceView
android:id="#+id/glPlaySurface"
android:layout_width="match_parent"
android:layout_height="match_parent" >
</android.opengl.GLSurfaceView>
<RadioGroup
android:id="#+id/radioGroup1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:orientation="horizontal" >
<RadioButton
android:id="#+id/btnRotate"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:checked="true"
android:text="R"
android:textColor="#000" />
<RadioButton
android:id="#+id/btnPan"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="15dp"
android:text="P"
android:textColor="#000" />
</RadioGroup>
<Button
android:id="#+id/btnLights"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginLeft="15dp"
android:layout_toRightOf="#+id/radioGroup1"
android:text="Lights" />
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/layoutLights"
android:layout_width="100dp"
android:layout_height="100dp"
android:visibility="visible" <--- Does not work if set to invisible
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:background="#fff" >
<Button
android:id="#+id/btnLightsOK"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="15dp"
android:text="OK" />
<Button
android:id="#+id/btnLights"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentLeft="true"
android:layout_marginLeft="15dp"
android:text="OK" />
</RelativeLayout>
</RelativeLayout>
private OnClickListener mOnLightsClick = new OnClickListener() {
public void onClick(View arg0) {
if(mLayoutLights.getVisibility() == View.VISIBLE) {
mLayoutLights.setVisibility(View.INVISIBLE);
}
else {
mLayoutLights.setVisibility(View.VISIBLE);
}
}
};
Had similar error but it was due to my silly mistake of not using the UiThread.
Activity act = (Activity)context;
act.runOnUiThread(new Runnable(){
#Override
public void run() {
mLayoutLights.setVisibility(View.VISIBLE);
} });
Got it. You have to set the visibility of all the items in the layout, not just the layout. So this code worked:
if (mLayoutLights.getVisibility() == View.VISIBLE) {
((Button) findViewById(R.id.btnLightsOK)).setVisibility(View.GONE);
((Button) findViewById(R.id.btnLightsCnc)).setVisibility(View.GONE);
mLayoutLights.setVisibility(View.GONE);
} else {
mLayoutLights.setVisibility(View.VISIBLE);
((Button) findViewById(R.id.btnLightsOK)).setVisibility(View.VISIBLE);
((Button) findViewById(R.id.btnLightsCnc)).setVisibility(View.VISIBLE);
}
In my case, with a plain SurfaceView, I just set the View to GONE in xml, not INVISIBLE. Then I can set VISIBILITY correctly after that.
I have faced the same problem and debug log was clearly showing that the visibility is correctly set.
I was using databinding. For me the solution below worked.
activity.runOnUiThread(() -> binding.getRoot().post(() -> {
binding.additionalDataHolderOne.setVisibility(View.GONE);
binding.firstStreamHolder.setVisibility(View.VISIBLE);
}));
Actually, binding.getRoot().post(() -> {}); did the job.
I would suggest trying three independent things.
Changing layout width and height to wrap content as it could be an issue with matching the parent.
Calling bringToFront on the view
Wrapping the surfaceView in a FrameLayout (this is related to #2, but it still might help)
if you set the CalendarView to visibility "VISIBLE" and in the inflateView/OnCreateView after you find it with "findById" just set to "GONE" and you can do what ever you want with it.
calendarView = (CalendarView)
view.findViewById(R.id.all_scores_calendar_view);
calendarView.setVisibility(View.GONE);
calendarView.setVisibility(View.VISIBLE);
I don't why is not working (for me also) but as a workaround you can do:
val params = mLayoutLights.layoutParams
if (shoouldShow()) {
params.height = WRAP_CONTENT
} else {
params.height = 0
}
mLayoutLights.layoutParams = params
I faced a problem like this before I was put 2 views in a LinearLayout.
one of the 2 views is gone and the other one is visible.
and when I try to make the gone one visible and the visible one gone,
it was not working.
I solved this issue by using RelativeLayout as a container layout instead of the LinearLayout, It's working fine then.
In my case, I have called .setVisiblity(View.GONE) in an element where visibility is GONE
if (temp.getVisibility() == View.VISIBLE) {
temp.setVisibility(View.GONE);
}
doing something like that worked for me.
In my case I just changed layout id and it worked.
If you are using ViewBinding and you have a nested View via Include with a View whose Id is the same as in the main View, there may be a situation that the Visiblity property is not applied to one of these Views
i don't know whats reas of not working but i put my layout into cardview and set cardview visiblity gone and it's work for me
<androidx.cardview.widget.CardView
android:id="#+id/rec"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="8dp"
android:elevation="10dp"
android:foregroundGravity="center"
app:cardCornerRadius="15dp"
app:layout_constraintBottom_toTopOf="#+id/guideline3"
app:layout_constraintEnd_toEndOf="#+id/cardTxtResult"
app:layout_constraintStart_toStartOf="#+id/cardTxtResult"
app:layout_constraintTop_toTopOf="#+id/guideline6">
<androidx.recyclerview.widget.RecyclerView
android:id="#+id/main_rec"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:background="#color/gray"
android:foregroundGravity="center"
android:padding="10dp"
android:stackFromBottom="false"
android:transcriptMode="alwaysScroll" />
</androidx.cardview.widget.CardView>
and java code connected to checkbox
CHK.setOnCheckedChangeListener((compoundButton, b) -> {
if (b) {
rec.setVisibility(View.VISIBLE);
} else {
rec.setVisibility(View.GONE);
}
});
case R.id.title_call_button:
if(llButtonCallNow.getVisibility() != View.VISIBLE){
llButtonCallNow.setVisibility(View.VISIBLE);
}
else{
llButtonCallNow.setVisibility(View.GONE);
Toast.makeText(getBaseContext(), ("Im here baby :)"),
Toast.LENGTH_SHORT).show();
}
break;
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" />
I am developing an app with tabs. On one of the tabs,
I have two EditText fields and a couple of buttons. I want to add an ExpandableListView
to the tab, below the rest of the elements.
My problem is that the current class extends Activity. All the example I've found extend ExpandableListActivity, but I can't extend both for the same class.
How can I add this list to the tab? I've added an ExpandableListView element in the XML file, but whenever I run it, it doesn't show up. I understand that I need to bind the view to some data, but how do I go about doing this?
Thank you.
Here is my class code:
public class DirectionsTab extends Activity
{
private Button clear_btn;
private Button go_btn;
private EditText origin_txt;
private EditText dest_txt;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.directions_tab);
// initialize views and onClick event handler
origin_txt = (EditText)findViewById(R.id.origin_txt);
dest_txt = (EditText)findViewById(R.id.dest_txt);
clear_btn = (Button)findViewById(R.id.clear_btn);
// clear all text fields and return focus to dest_txt
clear_btn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v)
{
origin_txt.setText("");
dest_txt.setText("");
origin_txt.requestFocus();
}
});
} // end public void onCreate(Bundle savedInstanceState)
} // end public class DirectionsTab extends Activity
and XML:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<TextView
android:id="#+id/origin_lbl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="Origin"/>
<EditText
android:id="#+id/origin_txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:drawable/editbox_background"
android:layout_below="#id/origin_lbl"/>
<TextView
android:id="#+id/dest_lbl"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_below="#id/origin_txt"
android:text="Destination" />
<EditText
android:id="#+id/dest_txt"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:background="#android:drawable/editbox_background"
android:layout_below="#id/dest_lbl" />
<ExpandableListView
android:id="#+id/listView"
android:layout_below="#+id/dest_txt"
android:layout_height="wrap_content"
android:layout_width="wrap_content" /><!--android:id="#android:id/list"-->
<Button style="?android:attr/buttonStyleSmall"
android:id="#+id/clear_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#id/dest_txt"
android:layout_alignParentRight="true"
android:layout_marginLeft="10dip"
android:layout_marginTop="10dip"
android:text="Clear" />
<Button style="?android:attr/buttonStyleSmall"
android:id="#+id/go_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toLeftOf="#id/clear_btn"
android:layout_alignTop="#id/clear_btn"
android:text="Go!" />
</RelativeLayout>
I got this!, If anyone is having problems with this, make sure you follow these steps:
Copy and paste ExpandableList3 example (located in ApiDemos project from Samples folder in your Android SDK). This is just a good example of how to set up a list.
Make your class inherit from ExpandableListActivity
Create the following in your XML layout file:
<ExpandableListView
android:id="#android:id/list"
android:layout_below="#+id/go_btn"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
It is VERY important that the ID property matches what you see above, otherwise, nothing will work. This little detail wasted plenty of hours for me and was discovered seating neatly as a small detail in the android docs.