Alphabet Bar extended linearlayout problem
I'm trying to get an Android Alphabet positioning bar to work following an old example provided by Josh Guilfoyle:
AlphabetBarListView <- original project and screen capture can be found here
I was able to debug the code to get the alphabet bar itself to display using
setContentView(new AlphabetBar(this));
but I can't figure out how to display the alphabet bar over a listview under Android 2.1 as shown in the photo. I've created a really small project to try and get it to work, but I'm obviously doing something wrong. Thanks guys! I really appreciate the help.
HelloWorld.java
package com.demo.helloworld;
import android.app.Activity;
import android.os.Bundle;
import and开发者_StackOverflow社区roid.widget.ListView;
public class HelloWorld extends Activity {
/** Called when the activity is first created. */
public AlphabetBar mAlphabetBar;
public ListView listView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setContentView(new AlphabetBar(this));
listView = (ListView)findViewById(R.id.mylist);
mAlphabetBar = (AlphabetBar)findViewById(R.id.alphabet_bar);
}
}
AlphabetBar.java
package com.demo.helloworld;
import java.util.Map;
import android.content.Context;
import android.text.Layout.Alignment;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
public class AlphabetBar extends LinearLayout
{
private static final String TAG = "AlphabetBar";
public AlphabetBar(Context context)
{
super(context);
init();
}
public AlphabetBar(Context context, AttributeSet attrs, Map inflateParams)
{
super(context, attrs);
init();
}
public void init()
{
setLayoutParams(new LinearLayout.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.FILL_PARENT));
/* Not strictly necessary since we override onLayout and onMeasure with
* our custom logic, but it seems like good form to do this just to
* show how we're arranging the children. */
setOrientation(VERTICAL);
char[] labels =
{
'#',
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
};
for (int i = 0; i < labels.length; i++)
{
TextView label = new TextView(getContext());
label.setText(String.valueOf(labels[i]));
// label.setAlignment(Alignment.ALIGN_CENTER);
label.setGravity(Gravity.CENTER_VERTICAL);
label.setClickable(true);
label.setFocusable(true);
label.setOnClickListener(mLabelClicked);
addView(label, new LinearLayout.LayoutParams(
LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
}
}
private OnClickListener mLabelClicked = new OnClickListener()
{
public void onClick(View v)
{
if (mClickCallback != null)
mClickCallback.onClick(v);
}
};
private OnClickListener mClickCallback = null;
/**
* Set the click listener for alphabet labels.
*
* @param listener
* Click listener, or null to unset.
*/
public void setLabelClickListener(OnClickListener listener)
{
mClickCallback = listener;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b)
{
super.onLayout(changed, l, t, r, b);
}
private void useDefaultBackground()
{
setBackgroundResource(R.drawable.alphabet_bar_bg);
}
@Override
protected void onMeasure(int wSpec, int hSpec)
{
Log.d(TAG, "onMeasure(" + wSpec + ", " + hSpec + ")");
if (getBackground() == null)
useDefaultBackground();
int count = getChildCount();
int hMode = MeasureSpec.getMode(hSpec);
int hSize = MeasureSpec.getSize(hSpec);
assert hMode == MeasureSpec.EXACTLY;
int maxWidth = 0;
int hSizeAdj = hSize - getPaddingTop() - getPaddingBottom();
float childHeight = hSizeAdj / count;
/* Calculate how many extra 1-pixel spaces we'll need in order to make
* childHeight align to integer heights. */
int variance = hSizeAdj - ((int)childHeight * count);
int paddingWidth = getPaddingLeft() + getPaddingRight();
for (int i = 0; i < count; i++)
{
TextView label = (TextView)getChildAt(i);
label.setTextSize(childHeight * 0.9F);
int thisHeight = (int)childHeight;
if (variance > 0)
{
thisHeight++;
variance--;
}
label.measure
(MeasureSpec.makeMeasureSpec(13, MeasureSpec.EXACTLY),
MeasureSpec.makeMeasureSpec(thisHeight, MeasureSpec.EXACTLY));
maxWidth = Math.max(maxWidth, label.getMeasuredWidth());
}
maxWidth += paddingWidth;
setMeasuredDimension(resolveSize(maxWidth, wSpec), hSize);
}
}
alphabet_bar_bg.xml (under drawable folder)
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
type="rectangle">
<solid android:color="#20777777" />
<corners android:radius="8dip" />
</shape>
mail.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"
>
<ListView
android:id="@+id/mylist"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>
<com.demo.helloworld.AlphabetBar
android:id="@+id/alphabet_bar"
android:layout_width="wrap_content"
android:layout_height="fill_parent"
android:layout_alignParentRight="true"
android:layout_marginRight="6dip"
android:layout_marginTop="14dip"
android:layout_marginBottom="14dip"
android:paddingTop="2dip"
android:paddingBottom="2dip"
android:paddingLeft="4dip"
android:paddingRight="4dip"
/>
</LinearLayout>
Okay, I figured this out.
(1) Change the layout from LinearLayout to RelativeLayout.
(2) Remove Map inflateParams from the AlphabetBar constructor.
And Viola!! It works! LOL
精彩评论