The following code is suppose to be doing this :
- Displaying a string using a standard TextView
- Displaying a string using a extended TextView. (This one overrides OnDraw and draws a line across the string, making it look like it was striked out)
The problem is that only the standard one is appearing.
Please check the following code :
ExpenseWatchActivity.java (This is the main activity)
package com.app.expensewatch;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
import java.util.Calendar;
public class ExpenseWatchActivity extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
int day,mon,yr;
Calendar cal = Calendar.getInstance();
day = cal.get(Calendar.DATE);
mon = 1 + cal.get(Calendar.MONTH);
yr = cal.get(Calendar.YEAR);
String text = getResources().getString(R.string.hello, day , mon , yr);
TextView tx1 = (TextView)findViewById(R.id.text1);
tx1.setText(text);
List1 list = (List1)findViewById(R.id.list1);
list.setText(text);
}
}
List1.java (This is the extended TextView)
package com.app.expensewatch;
import android.util.AttributeSet;
import android.widget.TextView;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import com.app.expensewatch.R;
public class List1 extends TextView {
public List1(Context context) {
super(context);
}
public List1(Context context, AttributeSet attrs) {
super( context, attrs );
}
public List1(Context context, AttributeSet attrs, int defStyle) {
super( context, attrs, defStyle );
}
float ht = (float)getHeight();
float wd = (float)getWidth();
#Override
protected void onDraw(Canvas canvas)
{
Paint divider = new Paint();
divider.setColor(getResources().getColor(R.color.line1));
canvas.drawLine(0,ht/2,wd,ht/2,divider);
}
}
main.xml
<?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="fill_parent"
android:orientation="vertical" >
<TextView
android:id="#+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello" />
<com.app.expensewatch.List1
android:id="#+id/list1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/hello" />
/>
</LinearLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">ExpenseWatch</string>
<string name="hello">Today is : %1$d / %2$d / %3$d</string>
</resources>
colors.xml
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="line1">#6456648f</color>
</resources>
When you set your width and height in the extended TextView, the view hasn't been measured yet. Its width and height are zero. Override onMeasure() in your extended TextView, and set your width and height there.
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
ht = getHeight();
wd = getWidth();
}
Always avoid setting a private variable that will hold a dimension in a view until after onMeasure() has been called.
Related
I'm not quite sure how to ask this but I need a scrollview that will scroll with an amplitude visualizer as it records audio. EDIT: To be clear, the ScrollView is not scrolling even with touches and gestures.
Here's a screenshot of the app with the custom view. The red bars show the average amplitude of a second.
The bars fill from left to right, but when it reaches the edge it does not scroll.
Here's the XML for the HorizontalScrollView and the AudioVisualizer view:
<HorizontalScrollView
android:id="#+id/hsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<com.blueteam.audiotes.AudioVisualizer
android:id="#+id/visualizer"
android:layout_width="match_parent"
android:layout_height="200dp" />
</HorizontalScrollView>
Here's the code for the AudioVisualizer element:
package com.blueteam.audiotes;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.View;
import java.util.ArrayList;
/**
* Created by tanner on 3/21/17.
*/
public class AudioVisualizer extends View {
private final int BAR_WIDTH = 10;
private final int BAR_STARTING_POINT = 0;
private final int BAR_SPACE = 2;
private final int BAR_BOTTOM = 200;
private final int BAR_MINIMUM_HEIGHT = 20;
private ArrayList<Rect> bars;
private Paint paint;
private ArrayList<Tag> tags;
public AudioVisualizer(Context context, AttributeSet attrs) {
super(context, attrs);
bars = new ArrayList<Rect>();
paint = new Paint();
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL_AND_STROKE);
}
#Override
protected void onDraw(Canvas canvas) {
for(Rect r : bars)
canvas.drawRect(r.left, r.top, r.right, r.bottom, paint);
}
public void addBar(int height) {
if (height < BAR_MINIMUM_HEIGHT)
height = BAR_MINIMUM_HEIGHT;
else if (height > BAR_BOTTOM)
height = BAR_BOTTOM;
bars.add(new Rect(BAR_STARTING_POINT + bars.size() * (BAR_SPACE + BAR_WIDTH),
BAR_BOTTOM - height,
(BAR_STARTING_POINT + bars.size() * (BAR_SPACE + BAR_WIDTH)) + BAR_WIDTH,
BAR_BOTTOM));
}
}
I tried setting the AudioVisualizer width to something like 2000 just to see if it would scroll when the child was clearly larger than the ScrollView, but it still didn't work.
I'm guessing I'm missing something simple.
Change your xml like this:
<HorizontalScrollView
android:id="#+id/hsv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<com.blueteam.audiotes.AudioVisualizer
android:id="#+id/visualizer"
android:layout_width="wrap_content"
android:layout_height="200dp" />
</HorizontalScrollView>
And whenever you addBar do this:
audioVisualizer.addBar(10);
parentHsv.fullScroll(HorizontalScrollView.FOCUS_RIGHT);
I solved it. I didn't override onMeasure. Here's my code:
#Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int width = (BAR_WIDTH + BAR_SPACE) * bars.size();
setMeasuredDimension(width, MeasureSpec.getSize(heightMeasureSpec));
}
I also needed to call v.requestLayout() before v.invalidate() to update the size.
I would like to test out using fragment manager to replace fragments dynamically. In the main layout, under the parent liner layout, I have 3 layouts, one child linear layout and 2 child frame layouts. The idea is to use a button in the first child linear layout to swap fragments in the 3rd frame layouts.
The issue I am seeing: when the application is loaded, only the child linear layout shows up on the screen; the fragments and their frame layout container is not visible. Can someone tell whether I am doing anything wrong here? There are no particular errors in the LogCat...
I tried to tweak the weight parameter for child layouts to resolve this issue, but without too much success.
Thanks a lot in advance.
Here are the activities classes:
[MainActivity.java]
package com.jiao.android.todolist;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.view.Menu;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.TextView;
public class MainActivity extends Activity implements NewItemFragment.OnNewItemAddedListener {
private ArrayAdapter<String> aa;
private ArrayList<String> todoItems;
private ArrayAdapter<String> aa2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//Get reference to the Fragments
FragmentManager fm = getFragmentManager();
ToDoListFragment todoListFragment = (ToDoListFragment)fm.findFragmentById(R.id.list_container);
//The codes below shows how to load fragments dynamically through Fragment Manager transaction
//into the predefined frame container in the layout xml
if(todoListFragment == null)
{
todoListFragment = new ToDoListFragment();
FragmentTransaction ft = fm.beginTransaction();
ft.add(R.id.item_container, new NewItemFragment());
ft.add(R.id.list_container, todoListFragment);
ft.commit();
}
//Create the ArrayList of to do items
todoItems = new ArrayList<String>();
//Create the ArrayAdapter to bind the array to the List View
aa = new ArrayAdapter<String>(this,R.layout.todolist_item,todoItems);
//Bind the Array Adapter to the List View
todoListFragment.setListAdapter(aa);
}
#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;
}
public void onNewItemAdded(String newItem){
todoItems.add(newItem);
aa.notifyDataSetChanged();
}
public void onSwapButtonClicked (View view)
{
//Get reference to the Fragments
FragmentManager fm2 = getFragmentManager();
ToDoListPlainFragment todoListFragment2 = new ToDoListPlainFragment();
//The codes below shows how to load fragments dynamically through Fragment Manager transaction
FragmentTransaction ft2 = fm2.beginTransaction();
String myNewFragmentTag = null;
ft2.replace(R.id.list_container, todoListFragment2,myNewFragmentTag);
ft2.commit();
//Create the ArrayAdapter to bind the array to the List View
aa2 = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1,todoItems);
//Bind the Array Adapter to the List View
todoListFragment2.setListAdapter(aa2);
}
}
[NewItemFragment.java]
package com.jiao.android.todolist;
import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
public class NewItemFragment extends Fragment {
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View view = inflater.inflate(R.layout.new_item_fragment,container,false);
final EditText myEditText = (EditText)view.findViewById(R.id.myEditText);
//this is how an editText can respond to DPAD_CENTER
//or the enter key
myEditText.setOnKeyListener(new View.OnKeyListener() {
#Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
// TODO Auto-generated method stub
if(event.getAction()==KeyEvent.ACTION_DOWN)
if((keyCode == KeyEvent.KEYCODE_DPAD_CENTER)||
(keyCode == KeyEvent.KEYCODE_ENTER))
{
String newItem = myEditText.getText().toString();
onNewItemAddedListener.onNewItemAdded(newItem);
myEditText.setText("");
return true;
}
return false;
}
});
return view;
}
public interface OnNewItemAddedListener {
public void onNewItemAdded(String newItem);
}
private OnNewItemAddedListener onNewItemAddedListener;
#Override
public void onAttach(Activity activity)
{
super.onAttach(activity);
try{
onNewItemAddedListener = (OnNewItemAddedListener)activity;
}catch (ClassCastException e)
{
throw new ClassCastException(activity.toString()+" must implement OnNewItemAddedListener");
}
}
}
[MyTextView.java]
package com.jiao.android.todolist;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.widget.TextView;
public class MyTextView extends TextView{
public MyTextView(Context context,AttributeSet attrs, int defStyle)
{
super(context,attrs, defStyle);
// do not forgot to call the ini() method, otherwise, allt he paint objects
// won't be initialized
init();
}
public MyTextView (Context context)
{
super(context);
// do not forgot to call the ini() method, otherwise, allt he paint objects
// won't be initialized
init();
}
public MyTextView(Context context, AttributeSet attrs)
{
super(context, attrs);
// do not forgot to call the ini() method, otherwise, allt he paint objects
// won't be initialized
init();
}
private Paint marginPaint;
private Paint linePaint;
private int paperColor;
private float margin;
private void init(){
//Get a referencve to our resource table
Resources myResources = getResources();
//Create the paint brushes we will use in the onDraw method.
marginPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
marginPaint.setColor(myResources.getColor(R.color.notepad_margin));
linePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
linePaint.setColor(myResources.getColor(R.color.notepad_lines));
System.out.println("line paint is"+linePaint.getColor());
//Get the paper background color and the margin width.
paperColor = myResources.getColor(R.color.notepad_paper);
margin = myResources.getDimension(R.dimen.notepad_margin);
}
#Override
public void onDraw(Canvas canvas){
//Color as paper
canvas.drawColor(paperColor);
//Draw ruled lines
//drawLine(float startX, float startY, float stopX, float stopY, Paint paint)
canvas.drawLine(0, 0,0, getMeasuredHeight(), linePaint);
canvas.drawLine(0, getMeasuredHeight(), getMeasuredWidth(), getMeasuredHeight(), linePaint);
//Draw Margin
canvas.drawLine(margin,0,margin,getMeasuredHeight(), marginPaint);
//Move the text across from the margin
canvas.save();
//The translate() method remaps the (0,0) position on the canvas
//or you can think you move the canvas
//Translate - Basically do what it says. Just translate the canvas using x,y.
//If you want to draw two objects and the one is just translation of the other e.g x2 = x1 + 50 for each point .
//You don't have to make all your calculations again for the second object but you can just translate the canvas
//and draw again the same object.
canvas.translate(margin,0);
super.onDraw(canvas);
//This call balances a previous call to save(),
//and is used to remove all modifications to the matrix/clip state since the last save call.
//canvas.save and canvas.restore undo things like rotation and translation. They don't undo drawing on the canvas.
canvas.restore();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent keyEvent){
return super.onKeyDown(keyCode, keyEvent);
}
}
[ToDoListFragment.java]
package com.jiao.android.todolist;
import android.app.ListFragment;
public class ToDoListFragment extends ListFragment {
}
[ToDoListPlainFragment.java]
package com.jiao.android.todolist;
import android.app.ListFragment;
public class ToDoListPlainFragment extends ListFragment {
}
Below are the layout xml files:
[activity_main.xml]
<?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="match_parent"
>
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:id="#+id/swapButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/swap_button_text"
android:onClick="onSwapButtonClicked"
android:layout_weight="2"
/>
</LinearLayout>
<FrameLayout
android:id="#+id/item_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
[new_item_fragment.xml]
<?xml version="1.0" encoding="utf-8"?>
<EditText xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="#string/addItemHint"
android:contentDescription="#string/addItemContentDescription" />
[todolist_item.xml]
<?xml version="1.0" encoding="utf-8"?>
<com.jiao.android.todolist.MyTextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
android:scrollbars="vertical"
android:textColor="#color/notepad_text"
android:fadingEdge="vertical"
/>
Here is the [AndroidManifest.xml]
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.jiao.android.todolist"
android:versionCode="1"
android:versionName="1.0" >
<uses-sdk
android:minSdkVersion="11"
android:targetSdkVersion="11" />
<application
android:allowBackup="true"
android:icon="#drawable/ic_launcher"
android:label="#string/app_name"
android:theme="#style/AppTheme" >
<activity
android:name="com.jiao.android.todolist.MainActivity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
Try this..
You have given your LinearLayout height as match_parent so it will match the whole parent that's why FrameLayout is not showing. Give LinearLayout height as wrap_content and try it.
<?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" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" // change is here
android:orientation="horizontal" >
<Button
android:id="#+id/swapButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="2"
android:onClick="onSwapButtonClicked"
android:text="swap_button_text" />
</LinearLayout>
<FrameLayout
android:id="#+id/item_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
<FrameLayout
android:id="#+id/list_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1" />
</LinearLayout>
I am developing a PreferenceActivity with custom Preference views. My problem is that I created a view with a ListView and it only shows the first element. I post my code and an image:
http://imageshack.us/photo/my-images/545/sc20120307161530.png/
http://img545.imageshack.us/img545/7207/sc20120307161530.png' border='0'/>
xml:
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<PreferenceCategory
android:key="player_settings"
android:title="#string/settings_player_config" >
<EditTextPreference
android:defaultValue="#string/settings_player_default_name"
android:dialogMessage="#string/settings_player_summary"
android:dialogTitle="#string/settings_playersname"
android:key="player_name"
android:summary="#string/settings_player_summary"
android:title="#string/settings_playersname" />
</PreferenceCategory>
<PreferenceCategory
android:key="volume"
android:title="#string/settings_volume" >
<com.battleship.preferences.SeekBarPreferences
android:defaultValue="50"
android:key="volume"
android:title="#string/settings_volume" />
</PreferenceCategory>
<PreferenceCategory
android:key="shine"
android:title="#string/settings_shine" >
<com.battleship.preferences.SeekBarPreferences
android:defaultValue="50"
android:key="shine"
android:title="#string/settings_shine" />
</PreferenceCategory>
<PreferenceCategory
android:key="themeTitle"
android:title="#string/settings_group_themes" >
<com.battleship.preferences.ListPreferences android:key="theme" />
</PreferenceCategory>
<PreferenceCategory
android:key="fontsTitle"
android:title="#string/settings_group_font_size" >
<com.battleship.preferences.ListPreferences android:key="font" />
</PreferenceCategory>
</PreferenceScreen>
The Custom ListPreference:
package com.battleship.preferences;
import com.battleship.R;
import android.content.Context;
import android.content.SharedPreferences;
import android.media.AudioManager;
import android.preference.Preference;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RadioGroup.OnCheckedChangeListener;
import android.widget.Toast;
public class ListPreferences extends Preference implements
OnCheckedChangeListener {
public ListPreferences(Context context) {
super(context);
}
public ListPreferences(Context context, AttributeSet attrs) {
super(context, attrs);
}
public ListPreferences(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
#Override
protected void onClick() {
super.onClick();
Toast t = Toast.makeText(getContext(), "HOLA!", 3);
t.show();
}
#Override
protected View onCreateView(ViewGroup parent) {
String[] contentString = new String[3];
if (getKey().equals("theme")) {
contentString = new String[] {
(getContext().getString(R.string.settings_theme_default)),
(getContext().getString(R.string.settings_theme_black)),
(getContext().getString(R.string.settings_theme_white)) };
} else {
contentString = new String[] {
(getContext().getString(R.string.settings_font_big)),
(getContext().getString(R.string.settings_font_medium)),
(getContext().getString(R.string.settings_font_little)) };
}
ListView listView = new ListView(getContext());
ArrayAdapter<String> array = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_single_choice,
android.R.id.text1, contentString);
listView.setAdapter(array);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return listView;
}
private void updatePreference(int intRadio) {
SharedPreferences.Editor editor = getEditor();
editor.putInt(getKey(), intRadio);
editor.commit();
}
}
Don't you hate it when everyone tries to tell you that you shouldn't do it that way instead of just answering your question? Being able to dynamically generate content is crucial to app flexibility, I totally know what you're after.
This will work assuming all the ListView entries will be roughly the same height (non-pertinent parts omitted). The order is important, try to keep it as I've indicated:
import android.view.ViewGroup.OnHierarchyChangeListener;
public class ListPreferences extends Preference implements
OnCheckedChangeListener, OnHierarchyChangeListener {
private ListView listView;
private View thisView;
private int listHeight = 0;
#Override
protected View onCreateView(ViewGroup parent) {
this.setLayoutResource(R.layout.listview_preference_layout);
thisView = super.onCreateView(parent);
listView = (ListView) thisView.findViewById(android.R.id.list);
listView.setOnHierarchyChangeListener(this);
String[] contentString = new String[3];
if (getKey().equals("theme")) {
contentString = new String[] {
(getContext().getString(R.string.settings_theme_default)),
(getContext().getString(R.string.settings_theme_black)),
(getContext().getString(R.string.settings_theme_white)) };
} else {
contentString = new String[] {
(getContext().getString(R.string.settings_font_big)),
(getContext().getString(R.string.settings_font_medium)),
(getContext().getString(R.string.settings_font_little)) };
}
ArrayAdapter<String> array = new ArrayAdapter<String>(getContext(),
android.R.layout.simple_list_item_single_choice,
android.R.id.text1, contentString);
listView.setAdapter(array);
listView.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
return thisView;
}
public void onChildViewAdded(View parent, View child) {
int childHeight = child.getMeasuredHeight();
if(childHeight > 0)
{
listHeight = listView.getAdapter().getCount() * childHeight;
thisView.setMinimumHeight(listHeight);
Log.i(TAG,"onChildViewAdded, done: "+listHeight+" "+childHeight);
}
}
public void onChildViewRemoved(View parent, View child) {
}
}
You'll also need res/layout/listview_preference_layout.xml with the following:
<?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="fill_parent"
android:layout_gravity="fill_vertical|fill_horizontal|fill"
android:gravity="fill"
android:orientation="vertical"
>
<ListView
android:id="#android:id/list"
android:layout_width="fill_parent"
android:layout_height="0dip"
android:clipChildren="true"
android:isScrollContainer="true"
android:layout_gravity="fill_vertical|fill_horizontal|fill"
android:layout_weight="1"
android:choiceMode="singleChoice"/>
</LinearLayout
I would advise you create a custom layout for Preferences. You can then create and style your Preferences to how you like. And using the SharedPreferences from PreferenceManager.getDefaultPreferences() will allow you to save any changes as if you were using the normal Preferences solution.
As Malcolm suggested, you should probably adhere to the common practices, and not try to do anything to complex here.
Another suggestion, is dont use a ListView. Instead if you want all of your Views to be displayed, manually add these to a LinearLayout, which you then place inside your Preference View.
The problem is that you're trying to add a ListView as an item of another ListView. ListView is used in the layout of the PreferenceActivity. Therefore it doesn't work.
I don't understand why you don't want to go with the standard solution, ListPreference. It is made exactly for the purpose of presenting a user with a list of radio buttons.
I'm using the shapedrawable example word for word (nearly) and can't seem to call a shapedrawable class in xml. The only extra step stated by the documentation was to override the View(Context, AttributeSet), which I think I did. The docs I'm referring to are here: http://developer.android.com/guide/topics/graphics/2d-graphics.html Here is my code.
AndroidTest.java
package com.android.test;
import android.app.Activity;
import android.os.Bundle;
public class AndroidTest extends Activity {
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
}
}
ShapeSquare.java
package com.android.test;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.util.AttributeSet;
import android.view.View;
public class ShapeSquare extends View {
private ShapeDrawable mDrawable;
public ShapeSquare(Context context, AttributeSet attrs) {
super(context, attrs);
int x = 10;
int y = 10;
int width = 300;
int height = 50;
mDrawable = new ShapeDrawable(new OvalShape());
mDrawable.getPaint().setColor(0xff74AC23);
mDrawable.setBounds(x, y, x + width, y + height);
}
protected void onDraw(Canvas canvas) {
mDrawable.draw(canvas);
}
}
main.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<com.android.test.shapedrawable.ShapeSquare
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
The error is a force quit error and I can't figure out where the problem lies. The shape properties will be dictated by user input (eventually), so the shape needs to be created in a class as opposed to all xml.
Figured out the problem here. I had to remove "shapedrawable" from:
<com.android.test.shapedrawable.ShapeSquare
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
Apparently, that was just the location of the demo. I thought it was referencing the class somehow.
I have a radiogroup with custom radiobuttons. Icons are set using
rbFirst.setButtonDrawable(R.drawable.first);
But icon is not in the center, how do I fix it?
I tried different attributes in xml file and inside class but it had no effect.
Try using setGravity(Gravity.CENTER); of setting it as a background drawable.
Or if it does not help you will have to derive a new class from RadioButton and override onDraw().
Here's layout
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<org.test.TestProj.RadioButtonCenter
android:id="#+id/myview"
android:layout_width="fill_parent"
android:layout_height="100dp"
android:layout_centerInParent="true"
android:text="Button test"
/>
</RelativeLayout>
The code:
package org.test.TestProj;
import android.content.Context;
import android.content.res.TypedArray;
import android.util.AttributeSet;
import android.view.Gravity;
import android.widget.RadioButton;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
public class RadioButtonCenter extends RadioButton {
public RadioButtonCenter(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CompoundButton, 0, 0);
buttonDrawable = a.getDrawable(1);
setButtonDrawable(android.R.color.transparent);
}
Drawable buttonDrawable;
#Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (buttonDrawable != null) {
buttonDrawable.setState(getDrawableState());
final int verticalGravity = getGravity() & Gravity.VERTICAL_GRAVITY_MASK;
final int height = buttonDrawable.getIntrinsicHeight();
int y = 0;
switch (verticalGravity) {
case Gravity.BOTTOM:
y = getHeight() - height;
break;
case Gravity.CENTER_VERTICAL:
y = (getHeight() - height) / 2;
break;
}
int buttonWidth = buttonDrawable.getIntrinsicWidth();
int buttonLeft = (getWidth() - buttonWidth) / 2;
buttonDrawable.setBounds(buttonLeft, y, buttonLeft+buttonWidth, y + height);
buttonDrawable.draw(canvas);
}
}
}
Finally, here's an attrs.xml file you need to put in res/values so the code can get at platform-defined attributes.
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="CompoundButton">
<attr name="android:button" />
</declare-styleable>
</resources>