編輯:Android編程入門
垂直滾動新聞欄的實現原理:
就是一個自定義的LinearLayout,並且textView能夠循環垂直滾動,而且條目可以點擊,顯示區域最多顯示2個條目,並且還有交替的屬性垂直移動的動畫效果,通過線程來控制滾動的實現。
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
自定義屬性:
<style name="AppTheme" parent="@android:style/Theme.Light.NoTitleBar">
<item name="android:windowNoTitle">true</item>
</style>
<declare-styleable name="NoticeView">
<attr name="gap" format="integer" />
<attr name="animDuration" format="integer" />
</declare-styleable>
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
自定義控件的獲取屬性方法都一樣:
//獲取自定義屬性
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.NoticeView);
mAdverHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, jdAdverHeight, getResources().getDisplayMetrics());
int gap = array.getInteger(R.styleable.NoticeView_gap, mGap);
//關閉清空TypedArray,防止內存洩露
int animDuration = array.getInteger(R.styleable.NoticeView_animDuration, mAnimDuration);
//關閉清空TypedArray
array.recycle();
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
自定義條目布局
<?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="60dp"
android:background="@drawable/blue_line_bg4"
android:layout_marginTop="10dp"
android:layout_marginLeft="15dp"
android:layout_marginRight="15dp"
android:gravity="center_vertical"
android:layout_marginBottom="10dp"
android:orientation="horizontal" >
<TextView
android:id="@+id/tag"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:background="@drawable/blue_line_bg"
android:padding="5dp"
android:text="最新"
android:textColor="#ff0000" />
<TextView
android:id="@+id/title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:ellipsize="end"
android:singleLine="true"
android:text="價格驚呆!電信千兆光纖上市"
android:textColor="#000000"
android:textSize="12sp" >
</TextView>
</LinearLayout>
...........................................................................................................................
//適配器
package com.notice.scroll;
import java.util.List;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.TextView;
import android.widget.Toast;
public class NoticeAdapter {
private List<NoticeEntity> mDatas;
public NoticeAdapter(List<NoticeEntity> datas) {
this.mDatas = datas;
if (datas == null || datas.isEmpty()) {
throw new RuntimeException("nothing to show");
}
}
/**
* 獲取數據的條數
*
* @return
*/
public int getCount() {
return mDatas == null ? 0 : mDatas.size();
}
/**
* 獲取摸個數據
*
* @param position
* @return
*/
public NoticeEntity getItem(int position) {
return mDatas.get(position);
}
/**
* 獲取條目布局
*
* @param parent
* @return
*/
public View getView(NoticeView parent) {
return LayoutInflater.from(parent.getContext()).inflate(R.layout.item, null);
}
/**
* 條目數據適配
*
* @param view
* @param data
*/
public void setItem(final View view, final NoticeEntity data) {
TextView tv = (TextView) view.findViewById(R.id.title);
tv.setText(data.title);
TextView tag = (TextView) view.findViewById(R.id.tag);
tag.setText(data.url);
// 你可以增加點擊事件
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 比如打開url
Toast.makeText(view.getContext(), data.url, Toast.LENGTH_SHORT).show();
}
});
}
}
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
公告實體
package com.notice.scroll;
public class NoticeEntity {
public String title;
public String url;
public NoticeEntity(String title, String url) {
super();
this.title = title;
this.url = url;
}
}
、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
自定義View
package com.notice.scroll;
public class NoticeView extends LinearLayout {
//控件高度
private float mAdverHeight = 0f;
//間隔時間
private final int mGap = 4000;
//動畫間隔時間
private final int mAnimDuration = 1000;
//顯示文字的尺寸
private final float TEXTSIZE = 20f;
private NoticeAdapter mAdapter;
private final float jdAdverHeight = 50;
//顯示的view
private View mFirstView;
private View mSecondView;
//播放的下標
private int mPosition;
//線程的標識
private boolean isStarted;
//畫筆
private Paint mPaint;
public NoticeView(Context context) {
this(context, null);
}
public NoticeView(Context context, AttributeSet attrs) {
this(context, attrs, 0);
}
public NoticeView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init(context, attrs, defStyleAttr);
}
/**
* 初始化屬性
* @param context
* @param attrs
* @param defStyleAttr
*/
private void init(Context context, AttributeSet attrs, int defStyleAttr) {
//設置為垂直方向
setOrientation(VERTICAL);
//抗鋸齒效果
mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
//獲取自定義屬性
TypedArray array = context.obtainStyledAttributes(attrs, R.styleable.NoticeView);
mAdverHeight = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, jdAdverHeight, getResources().getDisplayMetrics());
int gap = array.getInteger(R.styleable.NoticeView_gap, mGap);
//關閉清空TypedArray,防止內存洩露
int animDuration = array.getInteger(R.styleable.NoticeView_animDuration, mAnimDuration);
if (mGap <= mAnimDuration) {
gap = mGap;
animDuration = mAnimDuration;
}
//關閉清空TypedArray
array.recycle();
}
/**
* 設置數據
*/
public void setAdapter(NoticeAdapter adapter) {
this.mAdapter = adapter;
setupAdapter();
}
/**
* 開啟線程
*/
public void start() {
if (!isStarted && mAdapter.getCount() > 1) {
isStarted = true;
postDelayed(mRunnable, mGap);//間隔mgap刷新一次UI
}
}
/**
* 暫停滾動
*/
public void stop() {
//移除handle更新
removeCallbacks(mRunnable);
//暫停線程
isStarted = false;
}
/**
* 設置數據適配
*/
private void setupAdapter() {
//移除所有view
removeAllViews();
//只有一條數據,不滾東
if (mAdapter.getCount() == 1) {
mFirstView = mAdapter.getView(this);
mAdapter.setItem(mFirstView, mAdapter.getItem(0));
addView(mFirstView);
} else {
//多個數據
mFirstView = mAdapter.getView(this);
mSecondView = mAdapter.getView(this);
mAdapter.setItem(mFirstView, mAdapter.getItem(0));
mAdapter.setItem(mSecondView, mAdapter.getItem(1));
//把2個添加到此控件裡
addView(mFirstView);
addView(mSecondView);
mPosition = 1;
isStarted = false;
}
}
/**
* 測量控件的寬高
*
* @param widthMeasureSpec
* @param heightMeasureSpec
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
if (LayoutParams.WRAP_CONTENT == getLayoutParams().height) {
getLayoutParams().height = (int) mAdverHeight;
} else {
mAdverHeight = getHeight();
}
if (mFirstView != null) {
mFirstView.getLayoutParams().height = (int) mAdverHeight;
}
if (mSecondView != null) {
mSecondView.getLayoutParams().height = (int) mAdverHeight;
}
}
/**
* 畫布局
*
* @param canvas
*/
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
mPaint.setColor(Color.WHITE);
mPaint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, TEXTSIZE, getResources().getDisplayMetrics()));
mPaint.setStyle(Paint.Style.STROKE);
canvas.drawText("恭喜你中了5000w大獎", TEXTSIZE, getHeight() * 2 / 3, mPaint);//寫文字2/3的高度
}
/**
* 垂直滾蛋
*/
private void performSwitch() {
//屬性動畫控制控件滾動,y軸方向移動
ObjectAnimator animator1 = ObjectAnimator.ofFloat(mFirstView, "translationY", mFirstView.getTranslationY() - mAdverHeight);
ObjectAnimator animator2 = ObjectAnimator.ofFloat(mSecondView, "translationY", mSecondView.getTranslationY() - mAdverHeight);
//動畫集
AnimatorSet set = new AnimatorSet();
set.playTogether(animator1, animator2);//2個動畫一起
set.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {//動畫結束
mFirstView.setTranslationY(0);
mSecondView.setTranslationY(0);
View removedView = getChildAt(0);//獲得第一個子布局
mPosition++;
//設置顯示的布局
mAdapter.setItem(removedView, mAdapter.getItem(mPosition % mAdapter.getCount()));
//移除前一個view
removeView(removedView);
//添加下一個view
addView(removedView, 1);
}
});
set.setDuration(mAnimDuration);//持續時間
set.start();//開啟動畫
}
private AnimRunnable mRunnable = new AnimRunnable();
private class AnimRunnable implements Runnable {
@Override
public void run() {
performSwitch();
postDelayed(this, mGap);
}
}
/**
* 銷毀View的時候調用
*/
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
//停止滾動
stop();
}
/**
* 屏幕 旋轉
*
* @param newConfig
*/
@Override
protected void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
}
}
......................................................................................................
啟動Activity
package com.notice.scroll;
public class ScrollNoticeActivity extends Activity {
private List<NoticeEntity> mDataList = new ArrayList<NoticeEntity>();
private TextView mNoticeTextView;
private NoticeAdapter mNoticeAdapter;
private NoticeView mNoticeView;
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
super.handleMessage(msg);
switch (msg.what) {
case 1:
int index = msg.arg1 + 1;
if (index >= mDataList.size()) {
index = 0;
}
mNoticeTextView.setText(mDataList.get(index).title);
mHandler.sendMessageDelayed(mHandler.obtainMessage(1, index, 0), 2000);
break;
default:
break;
}
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initData();
}
private void initData() {
mDataList.add(new NoticeEntity("剩余流量查詢XXXXXXXX", "最新"));
mDataList.add(new NoticeEntity("恭喜你中了5000w大獎!", "最火爆"));
mDataList.add(new NoticeEntity("新入網用戶領取福利專區", "HOT"));
mDataList.add(new NoticeEntity("溫馨提示此乃詐騙消息", "new"));
mNoticeTextView = (TextView) findViewById(R.id.tv_notice);
mNoticeAdapter = new NoticeAdapter(mDataList);
mNoticeView = (NoticeView) findViewById(R.id.tv_notices);
mNoticeView.setAdapter(mNoticeAdapter);
// 開啟線程滾動
mNoticeView.start();
getNotices();
}
/**
* 直接通過設置textview達到公告顯示的效果
*/
private void getNotices() {
if (mDataList.size() > 0) {
mNoticeTextView.setText(mDataList.get(0).title);
mHandler.sendMessageDelayed(mHandler.obtainMessage(1, 0, 0), 2000);
}
}
}
我們在平時做開發的時候,免不了會用到各種各樣的對話框,相信有過其他平台開發經驗的朋友都會知道,大部分的平台都只提供了幾個最簡單的實現,如果我們想實現自己特定需求的對話框,
一、運行時的狀態遇到一個這樣的要求:“不進行掃描操作,怎麼對指定的免密碼WIFI進行連接(之前沒有連接過)”,於是動手寫了一個Demo,如圖所示未
Android Wear是連接安卓手機和可穿戴產品的一個平台。自從今年上半年發布以來,Android Wear獲得了大量關注,既有來自消費者的關注,也有來自開發商的關注,
放假之後電腦配置升級就開始用Android Studio(下面簡稱AS)了,那個酸爽真的不是一般的啊,這裡開一篇博客來記錄下AS裡面各種酷炫的功能,有更好玩的,大家不要吝