TV端Android聚焦focus
GridView TV
自定义网格视图
package com.src;
import android.annotation.SuppressLint;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.GridView;
public class MyGridView extends GridView {
private int position = 0;
public MyGridView(Context context) {
super(context);
}
public MyGridView(Context context, AttributeSet attrs) {
super(context, attrs);
setChildrenDrawingOrderEnabled(true);
}
public void setCurrentPosition(int pos) {
// 刷新adapter前,在activity中调用这句传入当前选中的item在屏幕中的次序
this.position = pos;
}
@SuppressLint("NewApi")
@Override
protected void setChildrenDrawingOrderEnabled(boolean enabled) {
// TODO Auto-generated method stub
super.setChildrenDrawingOrderEnabled(enabled);
}
@Override
protected int getChildDrawingOrder(int childCount, int i) {
if (i == childCount - 1) {// 这是最后一个需要刷新的item
return position;
}
if (i == position) {// 这是原本要在最后一个刷新的item
return childCount - 1;
}
return i;// 正常次序的item
}
}
**重点是gridview中绘画每个子类的顺序:因为我们想要在刷新适配器后想要聚焦的那个子类最后绘制来突出聚焦状态** ###网格适配器定义###
package com.src;
import java.util.ArrayList;
import java.util.HashMap;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.TextView;
public class ImageAdapter extends BaseAdapter {
private ArrayList<HashMap<String, String>> list = null;
private int isSelect = -1;
private int isClick = -1;
private Context context;
public ImageAdapter(Context context, ArrayList<HashMap<String, String>> list) {
this.list = list;
this.context = context;
}
public int getCount() {
// TODO Auto-generated method stub
return list.size();
}
public Object getItem(int position) {
// TODO Auto-generated method stub
return list.get(position);
}
public long getItemId(int position) {
// TODO Auto-generated method stub
return position;
}
public void setNotifyDataChange(int id) {
isSelect = id;
super.notifyDataSetChanged();
}
public void setNotifyItemSelected(int id) {
isClick = id;
super.notifyDataSetChanged();
}
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder holder = new ViewHolder();
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(
R.layout.gridview_item, null);
holder.mImageView = (ImageView) convertView.findViewById(R.id.img);
holder.mTextView = (TextView) convertView.findViewById(R.id.text);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.mImageView.setImageResource(R.drawable.icon);
String name = list.get(position).get("name");
holder.mTextView.setText(name);
convertView.setLayoutParams(new GridView.LayoutParams(150, 210));
if (isClick == position) {
holder.mImageView.setBackgroundResource(R.drawable.gvitemselect2);
} else {
if (isSelect == position) {
holder.mImageView
.setBackgroundResource(R.drawable.gvitemselect1);
} else {
holder.mImageView
.setBackgroundResource(R.drawable.gvitemselect);
}
}
return convertView;
}
class ViewHolder {
public ImageView mImageView = null;
public TextView mTextView = null;
}
}
Activity展示内容
package com.src;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.AnimationSet;
import android.view.animation.ScaleAnimation;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemSelectedListener;
public class GrideActivity extends Activity implements OnItemClickListener,
OnItemSelectedListener {
private ArrayList<HashMap<String, String>> itemList = null;
private ImageAdapter adapterItem = null;
private MyGridView gridview = null;
private AnimationSet manimationSet;
ScaleAnimation scaleAnimation = new ScaleAnimation(1.7f, 0.8f, 1.7f, 0.8f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
ScaleAnimation scaleAnimation1 = new ScaleAnimation(1, 1.7f, 1, 1.7f,
Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
itemList = new ArrayList<HashMap<String, String>>();
for (int i = 0; i < 10; i++) {
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", i + " item");
itemList.add(map);
}
adapterItem = new ImageAdapter(this, itemList);
gridview = (MyGridView) findViewById(R.id.gridview);
gridview.setAdapter(adapterItem);
gridview.setOnItemClickListener(this);
gridview.setOnItemSelectedListener(this);
gridview.smoothScrollToPosition(2);
}
/**
* 播放动画
*
* @param view
*/
private void startAnimation(View view) {
AnimationSet animationSet = new AnimationSet(true);
if (manimationSet != null && manimationSet != animationSet) {
scaleAnimation.setDuration(500);
manimationSet.addAnimation(scaleAnimation);
manimationSet.setFillAfter(false);
view.startAnimation(manimationSet);
}
scaleAnimation1.setDuration(500);
animationSet.addAnimation(scaleAnimation1);
animationSet.setFillAfter(true);
view.startAnimation(animationSet);
manimationSet = animationSet;
}
/**
* 点击选中
*/
public void onItemClick(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
startAnimation(view);
gridview.setCurrentPosition(position);
adapterItem.setNotifyItemSelected(position);
}
/**
* 移动焦点
*/
public void onItemSelected(AdapterView<?> parent, View view, int position,
long id) {
// TODO Auto-generated method stub
startAnimation(view);
gridview.setCurrentPosition(position);
adapterItem.setNotifyDataChange(position);
}
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
}
以上就是简单的TV端的网格展示demo
ListView TV + 自定义文本视图 + WindowManager显示
自定义TextView
package com.example.zbvfirsttest;
import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.widget.TextView;
public class MyTextView extends TextView {
public MyTextView(Context context) {
super(context);
}
public MyTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onFocusChanged(boolean focused, int direction,
Rect previouslyFocusedRect) {
if(focused){
zoomIn();
this.setTextColor(0xFF22222A);
this.setBackgroundResource(R.drawable.lv_focus);
}else{
zoomOut();
this.setTextColor(0xFFFFFFFF);
this.setBackgroundResource(R.drawable.semi_round_bg);
}
}
private void zoomIn(){
Animation animation=AnimationUtils.loadAnimation(getContext(), R.anim.scale_big);
startAnimation(animation);
}
private void zoomOut(){
Animation animation=AnimationUtils.loadAnimation(getContext(), R.anim.scale_normal);
startAnimation(animation);
}
}
自定义ListView
package com.example.zbvfirsttest;
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.ScaleAnimation;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.TextView;
public class RecomListView extends ListView {
private View lastView=null;
public RecomListView(Context context) {
super(context);
setChildrenDrawingOrderEnabled(true);
// setClipChildren(false);
// setClipToPadding(false);
}
public RecomListView(Context context, AttributeSet attrs) {
super(context, attrs);
setChildrenDrawingOrderEnabled(true);
// setClipChildren(false);
// setClipToPadding(false);
}
// @Override
// protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
// int width=256;
// int height=400;
// Log.d("zbv", "width="+width+";height="+height+";--->mesure_width="+widthMeasureSpec+";measure_heihgt="+heightMeasureSpec);
// setMeasuredDimension(width, height);
// }
/**
* 重新排列绘制顺序:如果i是最后一个就不用改变,如果不是最后一个是position那么就让其最后绘制
* */
@Override
protected int getChildDrawingOrder(int childCount, int i) {
int position=getSelectedItemPosition()-getFirstVisiblePosition();
if(position!=-1){
if(i==childCount-1){
return position;
}
if(i==position){
return childCount-1;
}
}
return i;
}
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id){
view.requestFocus();
// scaleBig(view);
// if(lastView!=null){
// scaleSmall(lastView);
// }
// lastView=view;
}
// public void onFocusChange(View v, boolean hasFocus){
// if(lastView!=null){
// if(hasFocus){
// scaleBig(lastView);
// }else{
// scaleSmall(lastView);
// }
// }
//
// }
/**
* 放大
* */
private void scaleBig(View view){
ScaleAnimation anim_big=new ScaleAnimation(1.0f, 1.1f, 1.0f, 1.05f, Animation.RELATIVE_TO_SELF,0.5f, Animation.RELATIVE_TO_SELF,0.5f);
anim_big.setDuration(200);
anim_big.setFillAfter(true);
view.startAnimation(anim_big);
}
/**
* 缩小
* */
private void scaleSmall(View view){
ScaleAnimation anim_small=new ScaleAnimation(1.1f, 1.0f, 1.05f, 1.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
anim_small.setDuration(200);
anim_small.setFillAfter(true);
view.startAnimation(anim_small);
}
}
WindowManager布局显示
package com.example.zbvfirsttest;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.graphics.PixelFormat;
import android.util.AttributeSet;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
public class MyView extends RelativeLayout {
//listview的聚焦位置
private static final String TAG = "MainView";
private int position=0;
private ImageView microphone = null;
private RelativeLayout tip_rl = null;
private ScrollView scroll = null;
private LinearLayout talk_line = null;
private LinearLayout recom_line = null;
private TextView tv_tip = null;
private List<String> recoms = null;
private RecomListView lv_recom = null;
private RecomAdapter adapter = null;
private WindowManager wManager = null;
private WindowManager.LayoutParams wmLayoutParams = null;
private MyTextView[] mtvs=null;
//test
// private TransparentView transView;
public MyView(Context context) {
this(context, null);
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// 加载布局
LayoutInflater.from(context).inflate(R.layout.wm_layout, this, true);
addOnAttachStateChangeListener(attachListener);
// 创建windowmanager服务对象
wManager = (WindowManager) context
.getSystemService(Context.WINDOW_SERVICE);
// 创建wm布局参数对象
wmLayoutParams = new WindowManager.LayoutParams();
// 参数设置
wmLayoutParams.type = WindowManager.LayoutParams.TYPE_PHONE;
wmLayoutParams.format = PixelFormat.RGBA_8888;// 设置bitmap格式
wmLayoutParams.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
wmLayoutParams.gravity = Gravity.LEFT|Gravity.TOP;
wmLayoutParams.x=0;
wmLayoutParams.y=0;
wmLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;
wmLayoutParams.height = WindowManager.LayoutParams.MATCH_PARENT;
// 初始化布局控件
microphone = (ImageView) findViewById(R.id.microphone);
tip_rl = (RelativeLayout) findViewById(R.id.first_tips);
scroll = (ScrollView) findViewById(R.id.mic_scroll);
talk_line = (LinearLayout) findViewById(R.id.mic_Layout);
recom_line = (LinearLayout) findViewById(R.id.recommend_contents);
tv_tip = (TextView) findViewById(R.id.tips);
// mtvs=new MyTextView[3];
// mtvs[0]=(MyTextView) findViewById(R.id.mytv_1);
// mtvs[1]=(MyTextView) findViewById(R.id.mytv_2);
// mtvs[2]=(MyTextView) findViewById(R.id.mytv_3);
// mtvs[position].requestFocus();
lv_recom = (RecomListView) findViewById(R.id.content_lv);
// 为lv添加内容
addLVCotents();
// View lastView = View.inflate(context, R.layout.wm_lv_setting, null);
// lv_recom.addFooterView(lastView);
// 为window添加view\
wManager.addView(this, wmLayoutParams);
// transView=new TransparentView(getContext());
// wManager.addView(transView, wmLayoutParams);
lv_recom.setSelection(position);
lv_recom.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view,
int position, long id) {
lv_recom.onItemSelected(parent, view, position, id);
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// TODO Auto-generated method stub
}
});
// lv_recom.setOnFocusChangeListener(new OnFocusChangeListener() {
//
// @Override
// public void onFocusChange(View v, boolean hasFocus) {
// lv_recom.onFocusChange(v, hasFocus);
//
// }
// });
}
private void addLVCotents() {
recoms = new ArrayList<String>();
recoms.add("功夫熊猫3");
recoms.add("大话西游1");
recoms.add("大话西游2");
recoms.add("西游记");
recoms.add("三国演义");
recoms.add("水浒传");
recoms.add("红楼梦");
recoms.add("斗鱼TV");
recoms.add("功夫熊猫3");
recoms.add("大话西游1");
recoms.add("大话西游2");
recoms.add("西游记");
recoms.add("三国演义");
recoms.add("水浒传");
recoms.add("红楼梦");
recoms.add("斗鱼TV");
adapter = new RecomAdapter(getContext(), recoms);
lv_recom.setAdapter(adapter);
// setListViewHeightBasedOnChildren(lv_recom);
}
/**
* 为该view添加绑定和解绑到window的监听器
* */
private OnAttachStateChangeListener attachListener = new
OnAttachStateChangeListener() {
@Override
public void onViewDetachedFromWindow(View v) {
Log.d(TAG, "to_detatch_window");
isAttacth=false;
}
@Override
public void onViewAttachedToWindow(View v) {
Log.d(TAG, "to_attatch_window");
isAttacth=true;
}
};
/**
* 适配器
* */
private class RecomAdapter extends BaseAdapter {
private List<String> list = null;
private Context context;
private ViewHolder holder = null;
public RecomAdapter(Context ct, List<String> data) {
list = data;
context = ct;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int position) {
return list.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
if (convertView == null) {
convertView = LayoutInflater.from(context).inflate(
R.layout.wm_lv_item, null);
holder = new ViewHolder();
holder.tv = (MyTextView) convertView.findViewById(R.id.recTV);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.tv.setText(list.get(position));
// holder.tv.setOnFocusChangeListener(new OnFocusChangeListener() {
//
// @Override
// public void onFocusChange(View v, boolean hasFocus) {
// if(hasFocus){
// holder.tv.setTextColor(0xffff0000);
// }else{
// holder.tv.setTextColor(0xffffffff);
// }
// }
// });
// holder.tv.setTextColor(0xffff0000);
// convertView.setOnFocusChangeListener(new OnFocusChangeListener() {
//
// @Override
// public void onFocusChange(View v, boolean hasFocus) {
// Log.d(TAG, "cv--->focusChange"+hasFocus);
// if(hasFocus){
// holder.tv.setTextColor(0xff22222A);
// }else{
// holder.tv.setTextColor(0x88FFFFFF);
// }
// }
// });
return convertView;
}
/**
* 让listview的item为自定义的TextView实现:
* 背景色的改变
* 字体颜色的改变
* */
private class ViewHolder {
MyTextView tv;
}
}
// @Override
// protected void onAttachedToWindow() {
// // TODO Auto-generated method stub
// super.onAttachedToWindow();
// }
//两次退出的第一次时间记录
private long clickTime;
//该视图是否绑定到窗口
private boolean isAttacth=false;
private void twiceBack(){
if(System.currentTimeMillis()-clickTime>2000){
Toast.makeText(getContext(), "再按一次后退键", 0).show();
clickTime=System.currentTimeMillis();
}else{
System.exit(0);
}
}
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(event.getAction()==KeyEvent.ACTION_DOWN){
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
Log.d(TAG, "back...");
if(isAttacth){
wManager.removeView(this);
}else{
twiceBack();
}
}
if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_DOWN) {
position++;
// if(position>mtvs.length){
// position=mtvs.length-1;
// return false;
// }
// mtvs[position].requestFocus();
// //因为有个tail
if(position>recoms.size()-1){
position=recoms.size()-1;
return false;
}
Log.d(TAG, "down...");
Toast.makeText(getContext(), "down--->", 0).show();
lv_recom.setSelection(position);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_UP) {
position--;
if(position<0){
position=0;
return false;
}
// mtvs[position].requestFocus();
Log.d(TAG, "up...");
Toast.makeText(getContext(), "up--->", 0).show();
lv_recom.setSelection(position);
}
if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_LEFT) {
Log.d(TAG, "left...");
Toast.makeText(getContext(), "left--->", 0).show();
}
if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_RIGHT) {
Log.d(TAG, "right...");
Toast.makeText(getContext(), "right--->", 0).show();
}
if (event.getKeyCode() == KeyEvent.KEYCODE_DPAD_CENTER) {
Log.d(TAG, "center...");
Toast.makeText(getContext(), "center--->", 0).show();
}
}
return false;
}
public static void setListViewHeightBasedOnChildren(ListView listView) {
ListAdapter listAdapter = listView.getAdapter();
if (listAdapter == null) {
return;
}
int totalHeight = 0;
for (int i = 0; i < 5; i++) {
View listItem = listAdapter.getView(i, null, listView);
listItem.measure(0, 0);
totalHeight += listItem.getMeasuredHeight();
Log.d(TAG, "itemHeight="+listItem.getMeasuredHeight());
}
ViewGroup.LayoutParams params = listView.getLayoutParams();
params.height = totalHeight
+ (listView.getDividerHeight() * (listAdapter.getCount() - 1));
listView.setLayoutParams(params);
}
}
值得一提的是setListViewHeightBasedOnChildren(ListView listView)这个函数,动态测试ListView的高度
^–^