I'm current having a problem designing an activity which can switch from a 'grid' to 'list' view. I'm using a GridView and to switch to the 'list', I set the maximum number of columns to 1. Now my problem is that when I switch to 'list' view, I want the image on the left along with some text on the right and not just an image in the center. All the data is taken from a custom class which is populated manually. The following images will demonstrate.
What I want:
What I have:
My Code (XML and Java) is as follows:
single_item.xml
<?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" >
<ImageView
android:contentDescription="#string/content"
android:id="#+id/imageView1"
android:layout_width="128dp"
android:layout_height="128dp"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
activity_main.xml
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="#+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.gridview.MainActivity"
tools:ignore="MergeRootFrame" >
<GridView
android:id="#+id/gridView1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="auto_fit"
android:columnWidth="128dp"
android:verticalSpacing="10dp"
>
</GridView>
</FrameLayout>
MainActivity.java
private GridView myGrid;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
myGrid = (GridView) findViewById(R.id.gridView1);
myGrid.setAdapter(new myGridAdapter(this));
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu items for use in the action bar
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, menu);
return super.onCreateOptionsMenu(menu);
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
GridView gv = (GridView) findViewById(R.id.gridView1);
//ImageView iv = (ImageView) findViewById(R.id.imageView1);
switch (item.getItemId()) {
case R.id.action_grid:
Toast.makeText(this, "Grid Button", Toast.LENGTH_SHORT).show();
gv.setNumColumns(GridView.AUTO_FIT);
return true;
case R.id.action_list:
Toast.makeText(this, "List Button", Toast.LENGTH_SHORT).show();
gv.setNumColumns(1);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
Does anyone have any idea how I can accomplish this? I've been reading for quite some time now and have also thought of viewSwitcher and viewFlipper but don't think that they are exactly what I'm looking for. I've also juggled with the idea of creating separate activities for each layout but then also read about the drawbacks.
Thanks for your time.
The simplest option would probably be:
Add a TextView in single_item.xml, and position it to the right of the image.
Pass the current state of the GridView (i.e. the mode it's in) to your custom adapter.
In the Adapter's getView(), depending on this state:
Call setVisibility() on the TextView, with either VISIBLE or GONE.
Update the ImageView's layoutParams, to align it to the center or right of its parent.
This does not require any duplication.
Example code:
#Override
public View getView(int position, View convertView, ViewGroup parent)
{
if (convertView == null)
{
convertView = LayoutInflater.from(mContext)inflate(...);
}
TextView tv = convertView.findViewById(R.id.textView1);
ImageView imageView = convertView.findViewById(R.id.imageView1);
// Show/hide text according to ListView mode.
tv.setVisibility(mMode == SHOW_TEXT ? View.VISIBLE : View.GONE);
// also update imageView.getLayoutParams() according to mMode.
Related
I am trying to programatically add a whole bunch of textViews of a certain width and at a certain location onto a tab. Now their setX() might be placed beyond the resolution of the screen. For instance, my tab is 1240 pixels in width, and I want to place a TextView at 2000 pixels and of course have a horizontal scroll feature available. I'm essentially creating a timeline on the fly depending on the data pulled.
I'm just trying to (at the moment) get multiple TextViews thrown on to the screen, and to have the horizontal scroll view for them. I am not sure if even doing a setX(2000); will populate a TextView beyond the screen. How can I get the HorizontalScrollView to work so that I may slide my main layout to the right to see the remaining two TextViews that were created?
Some basic code:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/relative_layout"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context=".MainActivity"
android:orientation="horizontal">
<HorizontalScrollView
android:id="#+id/horizontal"
android:layout_width="wrap_content"
android:layout_height="wrap_content" >
</HorizontalScrollView>
</RelativeLayout>
The MainActivity:
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RelativeLayout layout = (RelativeLayout) findViewById(R.id.relative_layout);
for(int i = 50; i < 550; i+=100){
TextView myText = new TextView(this);
myText.setX(i * 3);
myText.setText("HELLLLLOOOO");
layout.addView(myText);
}
}
#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;
}
}
MainActivity
public class MainActivity extends Activity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LinearLayout sv = (LinearLayout)findViewById(R.id.ll);
for(int i = 50; i < 550; i+=50){
TextView myText = new TextView(this);
myText.setX(i * 3);
myText.setText("HELLLLLOOOO");
sv.addView(myText);
}
}
#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;
}
}
xml
<HorizontalScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/horizontal"
android:layout_width="fill_parent"
android:layout_height="fill_parent" >
<LinearLayout
android:id="#+id/ll"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal">
</LinearLayout>
</HorizontalScrollView>
Create one custom view for example
public class Example extends HorizontalScrollView {
}
Execute all unimplemented methods, then write this:
LinearLayout l = new LinearLayout(context);
TextView tv = new TextView(context);
tv.setText("Example");
tv.setTextColor(Color.RED);
l.addView(tv);
addView(l);
Now in your xml, put the packagename and class name like this:
<com.argha.Example android:height and all />
Done, now you have HorizontalScroll view with a TextView... more text you want just do same as above.
Sorry if you found any code error, because I typed with my phone.
This is my initial layout of which the following EditText with id: assign_edit and weight_edit are part of. The name of this layout is new_class_container.
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<EditText
android:id="#+id/assign_edit"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:gravity="center_horizontal"
android:hint="#string/example_assign"
android:singleLine="true"
android:inputType="textCapWords"
android:layout_weight="1">
</EditText>
<EditText
android:id="#+id/weight_edit"
android:layout_width="fill_parent"
android:layout_weight="1"
android:layout_height="wrap_content"
android:hint="#string/example_weight"
android:layout_marginLeft="3dp"
android:gravity="center_horizontal"
android:inputType="number"
android:singleLine="true">
</EditText>
</LinearLayout>
The layout that I want to inflate is named new_class. In this layout, I copy pasted the exact same EditText's mentioned above. The following is my java file
public class DefiningClass extends Activity {
private ViewGroup mContainerView;
private EditText assignName;
private EditText assignWeight;
#Override
public void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.new_class_container);
mContainerView = (ViewGroup) findViewById(R.id.container);
}
#Override
public boolean onCreateOptionsMenu(Menu add){
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.main, add);
return true;
}
public boolean onOptionsItemSelected(MenuItem item){
switch(item.getItemId()){
case R.id.btn_save:
//INSERT INSTRUCTIONS TO SAVE
String str = assignName.getText().toString();
Toast msg = Toast.makeText(getBaseContext(),str,Toast.LENGTH_LONG);
msg.show();
break;
case R.id.btn_add:
//findViewById(android.R.id.empty).setVisibility(View.GONE);
addItem();
break;
default:
return true;
}
return super.onOptionsItemSelected(item);
}
private void addItem() {
final ViewGroup newView = (ViewGroup) LayoutInflater.from(this).inflate(
R.layout.new_class, mContainerView, false);
assignName = (EditText) newView.findViewById(R.id.assign_edit);
assignWeight = (EditText) newView.findViewById(R.id.weight_edit);
mContainerView.addView(newView, 0);
}
}
I put a Toast in my btn_save to see the work it does. When I run it, it only shows the most recent EditText. How can I make it so the toast recognizes all the edittexts that I have "inflated" and placed in it. For instance, if I had three edittexts, first said Hello, 2nd, Welcome, 3rd, Bye. The toast only shows Bye and not the other two.
What can I do for it to recognize the other two? When I save it in the future I want all the edittexts to be saved.
Use
<EditText
android:id="#+id/assign_edit"/> // missing #+
Your findViewById looks for a view with the id in the current infalted layout.
So having the same ids in different layout xml files is not a problem.
Check the topic id in the below link
http://developer.android.com/guide/topics/ui/declaring-layout.html
An ID need not be unique throughout the entire tree, but it should be unique within the part of the tree you are searching (which may often be the entire tree, so it's best to be completely unique when possible).
I have an activity with a list, whose items are made of an image+text. I need to allow the user to change the view and have a gridview instead of it (whose elements are still made of the same image+text).
The user can do it through an icon menu:
public boolean onOptionsItemSelected(MenuItem item)
{
if(item.getItemId()== R.id.change_view)
{
// ?
}
}
I tried to just set the new adapter(see below) but it doesn't work..do I have to create a new activity to do that?
if(item.getItemId()== R.id.change_view)
{
setContentView(R.layout.grid_view);
gridViewAdapter = new GridViewAdapter(this,R.layout.bookmark_list_item,MyApp.getItems().findAll());
list.setAdapter(gridViewAdapter);
list.setVisibility(View.VISIBLE);
}
There are several ways you could achieve that.
One solution is to have both the ListView and GridView stacked in a FrameLayout, and when you want to switch between these views, set the visibility GONE to one view and VISIBLE to another, then viceversa.
Put both the ListView and GridView in a ViewFlipper
Or, use a ViewSwitcher
And finally, use just a GridView, but when you want to transition to a list view, set programmatically the number of columns to 1.
I finally resolved with something like this:
For the layout of my activity i have:
<?xml version="1.0" encoding="utf-8"?>
<merge xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent" >
<ViewStub android:id="#+id/list"
android:inflatedId="#+id/showlayout"
android:layout="#layout/list_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"/>
<ViewStub android:id="#+id/grid"
android:inflatedId="#+id/showlayout"
android:layout="#layout/grid_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"/>
</merge>
then i've defined the layout for the list and the grid (and also for their items), and managed the passage between them inflating the layouts and then by this method:
private void changeView() {
//if the current view is the listview, passes to gridview
if(list_visibile) {
listview.setVisibility(View.GONE);
gridview.setVisibility(View.VISIBLE);
list_visibile = false;
setAdapters();
}
else {
gridview.setVisibility(View.GONE);
listview.setVisibility(View.VISIBLE);
list_visibile = true;
setAdapters();
}
}
the complete code is available in this article: http://pillsfromtheweb.blogspot.it/2014/12/android-passare-da-listview-gridview.html
I have this ListView that just needs to show data.
So I don't want to make it clickable.
First I've tried changing XML listview to:
<ListView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentTop="true"
android:clickable="false" >
But it didn't work.
So to solve my problem I set through code:
list.setSelector(android.R.color.transparent);
but I can't believe there's no better solution. Any idea?
Here it is, following the comment:
One way to do so is:
ListView.setOnClickListener(null); OR
You can add android:focusable="false" android:focusableInTouchMode="false" OR
another way in the layout android:listSelector="#android:color/transparent"
Cheers.
Just override isEnabled(position) in your adapter and return false
#Override
public boolean isEnabled(int position) {
return false;
}
override the below method. Return false to say all the items are not clickable.
#override
public boolean areAllItemsEnabled() {
return false;
}
And override below method to return which item is not clickable
public boolean isEnabled(int position) {
if(position == your_item_pos) {
return false;
}
return true;
}
android:listSelector="#android:color/transparent"
it changes the on-clicked color to same as when it is not clicked!
so it appears as if it is plain text...it's a work around.
Just copy this method in your adapter class.
Nothing to do .........
#Override
public boolean isEnabled(int position) {
return false;
}
You may set any condition to make some selected item unclickable.
#Override
public boolean isEnabled(int position) {
//Y for non clickable item
if(data_list.get(position).equalsIgnoreCase("Y"))
{
return false;
}
return true;
}
android:focusable="true"
to any of the item inside listview now listview wont clickable
You could use
yourListView.setOnItemClickListener(null);
Just set android:enabled="false" to the listview and it would do the trick..why to unneccesary keep overriding methods..
Easy way:
listView.setSelector(android.R.color.transparent);
Try this code
In Adapter.getView()
i.setOnClickListener( null );
i.setLongClickable( false );
i.setClickable( false );
In fact,
#override isEnabled() and
setOnClickListener(null)
setClickable(false)
setLongClickable(false)
There are not working for me.
I solve it by override performItemClick
#Override
public boolean performItemClick(View view, int position, long id) {
if(!clickAble){
return false;
}
return super.performItemClick(view,position,id);
}
This is because your ListView item may have a focusable or clickable element, please try the following approach either in XML Layout file or in code:
Add this attribute to the root ViewGroup element of your ListItem XML file (i.e. LinearLayout, RelativeLayout, ...) :
android:descendantFocusability="blocksDescendants"
Add this line to your List Adapter method which is responsible for creating/recycling the list item (most probably getView() or newView()), while parent is the ViewGroup of list item:
parent.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
Only using list.requestFocusFromTouch() in the onResume() method of the containing fragment worked for me.
¯\(ツ)/¯
I have this ListView that just needs to show data. So I don't want to make it clickable.
I have done this in one of my projects, and the sample bellow works fine.
Basically, you just need:
a data source (ArrayList, for example)
a ListView Widget
an ArrayAdapter, in order to bind the data source with the ListView
MainActivity.java
package com.sample.listview;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.ArrayAdapter;
import android.widget.ListView;
public class SecondActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// data source
String[] arrayData = {"Debian", "Ubuntu", "Kali", "Mint"};
// ListView Widget from a Layout
ListView listView = (ListView) findViewById(R.id.mainListView);
// an ArrayAdapter (using a layout as model for displaying the array items)
ArrayAdapter aa = new ArrayAdapter<String>(this, R.layout.main_list_item_layout, arrayData);
// binding the ArrayAdapter with the ListView Widget
listView.setAdapter(aa);
}
}
activity_main.xml
--->Make sure that the ListView Widget is using wrap_content for layout_width and layout_height
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
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"
android:orientation="vertical"
android:paddingBottom="#dimen/activity_vertical_margin"
android:paddingLeft="#dimen/activity_horizontal_margin"
android:paddingRight="#dimen/activity_horizontal_margin"
android:paddingTop="#dimen/activity_vertical_margin"
tools:context="com.sample.listview.MainActivity">
<ListView
android:id="#+id/mainListView"
android:layout_width="wrap_content" <---- HERE
android:layout_height="wrap_content" <---- HERE
/>
</LinearLayout>
main_list_item_layout.xml
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/mainListItem"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textColor="#ff0000"
android:textSize="20sp"
>
</TextView>
That's it: a ListView not clickable, just presenting data on the screen.
So here's my problem.
I'm working on API 14, I made a "MasterDetailFlow" with the help of Eclipse.
On the left part of the "twopane", I have some textviews, and a fragment.
(I made it simple)
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:baselineAligned="false"
android:orientation="horizontal"
tools:context=".ListActivity" >
<RelativeLayout
android:layout_width="0dip"
android:layout_height="match_parent"
android:layout_weight="27"
android:orientation="vertical" >
<TextView
android:text="toto"
/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="textView"/>
<fragment
android:id="#+id/fragment1"
android:name=""
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="button"
/>
</RelativeLayout>
//the right part of the screen, doesn't matter
<FrameLayout
/>
</LinearLayout>
The Fragment class is like that
public class MyFragment extends Fragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = null;
if (mItem != null) {
if(mItem.isTrue){
rootView = inflater.inflate(layout1, container, false);
}else{
rootView = inflater.inflate(layout2, container, false);
}
}
}
}
I dynamically add items in the list with a ArrayAdapter.
The thing is : When the list doesn't need to be scrolled (the height of the list is smaller than the height of the fragment), everything is displayed the good way.
But when the list is bigger (the visible part is OK) and I scroll the list, some items which should have the layout1 have the layout2, and the other way.
Those items are weirdly always at the junction, like the first element hidden.
And when you click on the item, it act normally. For exemple, a item that should be layout1 (but is displayed layout2) act as an item layout1 on click.
I don't know if it's clear, because it's not to me :)
And when I print in logcat the list of Strings which is in the fragment, it's in the good order. So it looks like a "display error" only, but where does it come from?
Does anyone have some similar problem? Know the issue?
Thanks.
EDIT :
Here is my Custom ArrayAdapter. I don't have the methods getItemViewType and getViewTypeCount, I should work on that.
Till now I was using a boolean stored in the DummyItem to know if it's a type 1 item or a type 2.
public class CustomArrayAdapter extends ArrayAdapter<DummyItem>
#Override
public View getView(int p_position, View p_convertView, ViewGroup p_parent) {
DummyItem item = data.get(p_position);
View row = p_convertView;
if(row==null){
if(item.isTrue){
LayoutInflater inflater = ((Activity)m_context).getLayoutInflater();
row = inflater.inflate(layoutResourceId, p_parent, false);
row.setTag(item);
TextView label1 = (TextView) row.findViewById(textViewId);
label1.setText(item.content);
}else{
LayoutInflater inflater = ((Activity)m_context).getLayoutInflater();
row = inflater.inflate(R.layout.simple_list_item_activated_1_custom, p_parent, false);
TextView label2 = (TextView) row.findViewById(R.id.text1);
labelPiece.setText(item.content);
}
}else{
}
return row;
}
}